/**
   * Executes example.
   *
   * @param args Command line arguments, none required.
   * @throws GridException If example execution failed.
   */
  public static void main(String[] args) throws Exception {
    Timer timer = new Timer("priceBars");

    // Start grid.
    final Grid g = GridGain.start("examples/config/example-streamer.xml");

    System.out.println();
    System.out.println(">>> Streaming price bars example started.");

    try {
      TimerTask task = scheduleQuery(g, timer);

      streamData(g);

      // Force one more run to get final results.
      task.run();

      timer.cancel();

      // Reset all streamers on all nodes to make sure that
      // consecutive executions start from scratch.
      g.compute()
          .broadcast(
              new Runnable() {
                @Override
                public void run() {
                  if (!ExamplesUtils.hasStreamer(g, "priceBars"))
                    System.err.println(
                        "Default streamer not found (is example-streamer.xml "
                            + "configuration used on all nodes?)");
                  else {
                    GridStreamer streamer = g.streamer("priceBars");

                    System.out.println("Clearing bars from streamer.");

                    streamer.reset();
                  }
                }
              })
          .get();
    } finally {
      GridGain.stop(true);
    }
  }
  /**
   * Schedules the query to periodically output built bars to the console.
   *
   * @param g Grid.
   * @param timer Timer.
   * @return Scheduled task.
   */
  private static TimerTask scheduleQuery(final Grid g, Timer timer) {
    TimerTask task =
        new TimerTask() {
          @Override
          public void run() {
            final GridStreamer streamer = g.streamer("priceBars");

            try {
              Collection<Bar> bars =
                  streamer
                      .context()
                      .reduce(
                          // This closure will execute on remote nodes.
                          new GridClosure<GridStreamerContext, Collection<Bar>>() {
                            @Override
                            public Collection<Bar> apply(GridStreamerContext ctx) {
                              Collection<Bar> values = ctx.<String, Bar>localSpace().values();

                              Collection<Bar> res = new ArrayList<>(values.size());

                              for (Bar bar : values) res.add(bar.copy());

                              return res;
                            }
                          },
                          // The reducer will always execute locally, on the same node
                          // that submitted the query.
                          new GridReducer<Collection<Bar>, Collection<Bar>>() {
                            private final Collection<Bar> res = new ArrayList<>();

                            @Override
                            public boolean collect(@Nullable Collection<Bar> col) {
                              res.addAll(col);

                              return true;
                            }

                            @Override
                            public Collection<Bar> reduce() {
                              return res;
                            }
                          });

              for (Bar bar : bars) System.out.println(bar.toString());

              System.out.println("-----------------");
            } catch (GridException e) {
              e.printStackTrace();
            }
          }
        };

    timer.schedule(task, 2000, 2000);

    return task;
  }