/**
   * Prints every word a phrase on different nodes.
   *
   * @param phrase Phrase from which to print words on different nodes.
   * @throws GridException If failed.
   */
  private static void spreadWordsClosure(String phrase) throws GridException {
    X.println(">>> Starting spreadWordsClosure() example...");

    // Splits the passed in phrase into words and prints every word
    // on a individual grid node. If there are more words than nodes -
    // some nodes will print more than one word.
    G.grid()
        .run(
            SPREAD,
            F.yield(
                phrase.split(" "),
                new GridInClosure<String>() {
                  @Override
                  public void apply(String word) {
                    X.println(word);
                  }
                }));

    // NOTE:
    //
    // Alternatively, you can use existing closure 'F.println()' to
    // print any yield result in 'F.yield()' like so:
    //
    // G.grid().run(SPREAD, F.yield(phrase.split(" "), F.println()));
    //

    X.println(">>>");
    X.println(
        ">>> Finished printing individual words on different nodes based on GridGain 3.0 API.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * Broadcasts a give phrase to all nodes.
   *
   * @param phrase Phrase to broadcast.
   * @throws GridException If failed.
   */
  private static void broadcastWordsClosure(final String phrase) throws GridException {
    X.println(">>> Starting broadcastWordsClosure() example...");

    G.grid()
        .run(
            BROADCAST,
            new GridAbsClosure() {
              @Override
              public void apply() {
                X.println(">>> Printing phrase: " + phrase);
              }
            });

    // NOTE:
    //
    // Alternatively, you can use existing closure 'F.println()' to
    // print any text like so:
    //
    // G.grid().run(BROADCAST, F.println(">>> Printing phrase: " + phrase));
    //

    X.println(">>>");
    X.println(">>> Finished broadcasting a phrase to all grid nodes based on GridGain 3.0 API.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * Prints a phrase on the grid nodes running anonymous closure objects and calculating total
   * number of letters.
   *
   * @param phrase Phrase to print on of the grid nodes.
   * @throws GridException If failed.
   */
  private static void countLettersClosure(String phrase) throws GridException {
    X.println(">>> Starting countLettersClosure() example...");

    // Explicitly execute the collection of callable objects and receive a result.
    Collection<Integer> results =
        G.grid()
            .call(
                SPREAD,
                new GridClosure<String, Integer>() { // Create executable logic.
                  @Override
                  public Integer apply(String word) {
                    // Print out a given word, just so we can
                    // see which node is doing what.
                    X.println(">>> Executing word: " + word);

                    // Return the length of a given word, i.e. number of letters.
                    return word.length();
                  }
                },
                Arrays.asList(phrase.split(" "))); // Collection of arguments for closures.

    // Add up all results using convenience 'sum()' method.
    int letterCnt = F.sum(results);

    X.println(">>>");
    X.println(">>> Finished execution of counting letters with closure based on GridGain 3.0 API.");
    X.println(">>> You should see the phrase '" + phrase + "' printed out on the nodes.");
    X.println(">>> Total number of letters in the phrase is '" + letterCnt + "'.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * Prints a phrase on the grid nodes running anonymous callable objects and calculating total
   * number of letters.
   *
   * @param phrase Phrase to print on of the grid nodes.
   * @throws GridException If failed.
   */
  private static void countLettersCallable(String phrase) throws GridException {
    X.println(">>> Starting countLettersCallable() example...");

    Collection<Callable<Integer>> calls = new HashSet<Callable<Integer>>();

    for (final String word : phrase.split(" "))
      calls.add(
          new GridCallable<Integer>() { // Create executable logic.
            @Override
            public Integer call() throws Exception {
              // Print out a given word, just so we can
              // see which node is doing what.
              X.println(">>> Executing word: " + word);

              // Return the length of a given word, i.e. number of letters.
              return word.length();
            }
          });

    // Explicitly execute the collection of callable objects and receive a result.
    Collection<Integer> results = G.grid().call(SPREAD, calls);

    // Add up all results using convenience 'sum()' method on GridFunc class.
    int letterCnt = F.sum(results);

    X.println(">>>");
    X.println(
        ">>> Finished execution of counting letters with callables based on GridGain 3.0 API.");
    X.println(">>> You should see the phrase '" + phrase + "' printed out on the nodes.");
    X.println(">>> Total number of letters in the phrase is '" + letterCnt + "'.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * Prints a phrase on one of the grid nodes running anonymous runnable.
   *
   * @param phrase Phrase to print on one of the grid nodes.
   * @throws GridException If failed.
   */
  private static void unicastWordsRunnable(final String phrase) throws GridException {
    X.println(">>> Starting unicastWordsRunnable() example...");

    G.grid()
        .run(
            UNICAST,
            new GridRunnable() {
              @Override
              public void run() {
                X.println(">>> Printing phrase: " + phrase);
              }
            });

    // NOTE:
    //
    // Alternatively, you can use existing closure 'F.println()' to
    // print any text like so:
    //
    // G.grid().run(UNICAST, F.println(">>> Printing phrase: " + phrase));
    //

    X.println(">>>");
    X.println(">>> Finished execution of runnable object based on GridGain 3.0 API.");
    X.println(">>> You should see the phrase '" + phrase + "' printed out on one of the nodes.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * Calculates length of a given phrase on the grid.
   *
   * @param phrase Phrase to count the number of letters in.
   * @throws GridException If failed.
   */
  private static void countLettersReducer(String phrase) throws GridException {
    X.println(">>> Starting countLettersReducer() example...");

    Grid grid = G.grid();

    // Logger to use in your closure. Note that even though we assign it
    // to a local variable, GridGain still allows to use it from remotely
    // executed code.
    final GridLogger log = grid.log();

    // Execute Hello World task.
    int letterCnt =
        grid.reduce(
            BALANCE,
            new GridClosure<String, Integer>() { // Create executable logic.
              @Override
              public Integer apply(String word) {
                // Print out a given word, just so we can
                // see which node is doing what.
                log.info(">>> Calculating for word: " + word);

                // Return the length of a given word, i.e. number of letters.
                return word.length();
              }
            },
            Arrays.asList(phrase.split(" ")), // Collection of words.
            // Create custom reducer.
            // NOTE: Alternatively, you can use existing reducer: F.sumIntReducer()
            new GridReducer<Integer, Integer>() {
              private int sum;

              @Override
              public boolean collect(Integer res) {
                sum += res;

                return true; // True means continue collecting until last result.
              }

              @Override
              public Integer apply() {
                return sum;
              }
            });

    X.println(">>>");
    X.println(">>> Finished execution of counting letters with reducer based on GridGain 3.0 API.");
    X.println(">>> Total number of letters in the phrase is '" + letterCnt + "'.");
    X.println(">>> You should see individual words printed out on different nodes.");
    X.println(">>> Check all nodes for output (this node is also part of the grid).");
    X.println(">>>");
  }
  /**
   * @param args Command arguments.
   * @throws GridException If failed.
   */
  public static void main(String[] args) throws GridException {
    // Starts grid.
    Grid grid = args.length == 0 ? G.start() : G.start(args[0]);

    try {
      // Create portfolio.
      GridCredit[] portfolio = new GridCredit[5000];

      Random rnd = new Random();

      // Generate some test portfolio items.
      for (int i = 0; i < portfolio.length; i++) {
        portfolio[i] =
            new GridCredit(
                50000 * rnd.nextDouble(), // Credit amount.
                rnd.nextInt(1000), // Credit term in days.
                rnd.nextDouble() / 10, // APR.
                rnd.nextDouble() / 20 + 0.02 // EDF.
                );
      }

      // Forecast horizon in days.
      int horizon = 365;

      // Number of Monte-Carlo iterations.
      int iter = 10000;

      // Percentile.
      double percentile = 0.95;

      // Mark the stopwatch.
      long start = System.currentTimeMillis();

      // Calculate credit risk and print it out.
      // As you can see the grid enabling is completely hidden from the caller
      // and it is fully transparent to him. In fact, the caller is never directly
      // aware if method was executed just locally or on the 100s of grid nodes.
      // Credit risk crdRisk is the minimal amount that creditor has to have
      // available to cover possible defaults.
      double crdRisk =
          grid.reduce(
              SPREAD,
              closures(grid.size(), portfolio, horizon, iter, percentile),
              new R1<Double, Double>() {
                /** Collected values sum. */
                private double sum;

                /** Collected values count. */
                private int count;

                /** {@inheritDoc} */
                @Override
                public boolean collect(Double e) {
                  sum += e;
                  count++;

                  return true;
                }

                /** {@inheritDoc} */
                @Override
                public Double apply() {
                  return sum / count;
                }
              });

      X.println(
          "Credit risk [crdRisk="
              + crdRisk
              + ", duration="
              + (System.currentTimeMillis() - start)
              + "ms]");
    }
    // We specifically don't do any error handling here to
    // simplify the example. Real application may want to
    // add error handling and application specific recovery.
    finally {
      // Stops grid.
      G.stop(true);
    }
  }
  /**
   * Runs basic cache example.
   *
   * @param args Command line arguments, none required.
   * @throws Exception If example execution failed.
   */
  public static void main(String[] args) throws Exception {
    final Grid g =
        args.length == 0 ? G.start("examples/config/spring-cache.xml") : G.start(args[0]);

    try {
      // Subscribe to events on every node, so we can visualize what's
      // happening in remote caches.
      g.run(
          BROADCAST,
          new CA() {
            @Override
            public void apply() {
              GridLocalEventListener lsnr =
                  new GridLocalEventListener() {
                    @Override
                    public void onEvent(GridEvent event) {
                      switch (event.type()) {
                        case EVT_CACHE_OBJECT_PUT:
                        case EVT_CACHE_OBJECT_READ:
                        case EVT_CACHE_OBJECT_REMOVED:
                          {
                            GridCacheEvent e = (GridCacheEvent) event;

                            X.println("Cache event [name=" + e.name() + ", key=" + e.key() + ']');
                          }
                      }
                    }
                  };

              GridNodeLocal<String, GridLocalEventListener> loc = g.nodeLocal();

              GridLocalEventListener prev = loc.remove("lsnr");

              // If there is a listener subscribed from previous runs, unsubscribe it.
              if (prev != null) g.removeLocalEventListener(prev);

              // Record new listener, so we can check it on next run.
              loc.put("lsnr", lsnr);

              // Subscribe listener.
              g.addLocalEventListener(lsnr, EVTS_CACHE);
            }
          });

      final GridCacheProjection<Integer, String> cache =
          g.cache(CACHE_NAME).projection(Integer.class, String.class);

      final int keyCnt = 20;

      // Store keys in cache.
      for (int i = 0; i < keyCnt; i++) cache.putx(i, Integer.toString(i));

      // Peek and get on local node.
      for (int i = 0; i < keyCnt; i++) {
        X.println("Peeked [key=" + i + ", val=" + cache.peek(i) + ']');
        X.println("Got [key=" + i + ", val=" + cache.get(i) + ']');
      }

      // Projection (view) for remote nodes.
      GridProjection rmts = g.remoteProjection();

      if (!rmts.isEmpty()) {
        // Peek and get on remote nodes (comment it out if output gets too crowded).
        g.remoteProjection()
            .run(
                BROADCAST,
                new GridAbsClosureX() {
                  @Override
                  public void applyx() throws GridException {
                    for (int i = 0; i < keyCnt; i++) {
                      X.println("Peeked [key=" + i + ", val=" + cache.peek(i) + ']');
                      X.println("Got [key=" + i + ", val=" + cache.get(i) + ']');
                    }
                  }
                });
      }
    } finally {
      G.stop(true);
    }
  }