Пример #1
0
  @Test
  public void workerOrchestrator() throws InterruptedException {
    Reactor reactor = Reactors.reactor(env, Environment.WORK_QUEUE);

    CountDownLatch latch = new CountDownLatch(3);

    reactor.on(
        Selectors.$("worker"),
        new Consumer() {
          @Override
          public void accept(Object o) {
            System.out.println(Thread.currentThread().getName() + " worker " + o);
            reactor.notify("orchestrator", Event.wrap(1000));
            latch.countDown();
            System.out.println(Thread.currentThread().getName() + " ok");
          }
        });

    reactor.on(
        Selectors.$("orchestrator"),
        new Consumer<Event<Integer>>() {

          @Override
          public void accept(Event<Integer> event) {
            sendTask();
          }

          void sendTask() {
            System.out.println(Thread.currentThread().getName() + " sendTask ");
            reactor.notify("worker", Event.wrap(latch.getCount()));
            latch.countDown();
          }
        });

    reactor.notify("orchestrator", Event.wrap(1000));

    Assert.isTrue(latch.await(10, TimeUnit.SECONDS));
  }
Пример #2
0
 /**
  * Subclasses should register the given {@link reactor.net.NetChannel} for later use.
  *
  * @param ioChannel The channel object.
  * @param netChannel The {@link NetChannel}.
  * @param <C> The type of the channel object.
  * @return {@link reactor.event.registry.Registration} of this channel in the {@link Registry}.
  */
 protected <C> Registration<? extends NetChannel<IN, OUT>> register(
     @Nonnull C ioChannel, @Nonnull NetChannel<IN, OUT> netChannel) {
   Assert.notNull(ioChannel, "Channel cannot be null.");
   Assert.notNull(netChannel, "NetChannel cannot be null.");
   return netChannels.register(Selectors.$(ioChannel), netChannel);
 }
Пример #3
0
/**
 * Abstract base class that implements common functionality shared by clients and servers.
 *
 * @author Jon Brisbin
 */
public abstract class AbstractNetPeer<IN, OUT> {

  private final Registry<NetChannel<IN, OUT>> netChannels =
      new CachingRegistry<NetChannel<IN, OUT>>();
  private final Event<AbstractNetPeer<IN, OUT>> selfEvent = Event.wrap(this);
  private final Selector open = Selectors.$();
  private final Selector close = Selectors.$();
  private final Selector start = Selectors.$();
  private final Selector shutdown = Selectors.$();

  private final Environment env;
  private final Reactor reactor;
  private final Codec<Buffer, IN, OUT> codec;
  private final Collection<Consumer<NetChannel<IN, OUT>>> consumers;

  protected AbstractNetPeer(
      @Nonnull Environment env,
      @Nonnull Reactor reactor,
      @Nullable Codec<Buffer, IN, OUT> codec,
      @Nonnull Collection<Consumer<NetChannel<IN, OUT>>> consumers) {
    this.env = env;
    this.reactor = reactor;
    this.codec = codec;
    this.consumers = consumers;

    for (final Consumer<NetChannel<IN, OUT>> consumer : consumers) {
      reactor.on(
          open,
          new Consumer<Event<NetChannel<IN, OUT>>>() {
            @Override
            public void accept(Event<NetChannel<IN, OUT>> ev) {
              consumer.accept(ev.getData());
            }
          });
    }
  }

  public Promise<Boolean> close() {
    Deferred<Boolean, Promise<Boolean>> d = Promises.defer(env, reactor.getDispatcher());
    close(d);
    return d.compose();
  }

  public void close(@Nullable final Consumer<Boolean> onClose) {
    reactor.schedule(
        new Consumer<Void>() {
          @Override
          public void accept(Void v) {
            for (Registration<? extends NetChannel<IN, OUT>> reg : getChannels()) {
              if (null == reg) {
                continue;
              }
              doCloseChannel(reg.getObject());
            }
            getChannels().clear();
            doClose(onClose);
          }
        },
        null);
  }

  /**
   * Subclasses should register the given {@link reactor.net.NetChannel} for later use.
   *
   * @param ioChannel The channel object.
   * @param netChannel The {@link NetChannel}.
   * @param <C> The type of the channel object.
   * @return {@link reactor.event.registry.Registration} of this channel in the {@link Registry}.
   */
  protected <C> Registration<? extends NetChannel<IN, OUT>> register(
      @Nonnull C ioChannel, @Nonnull NetChannel<IN, OUT> netChannel) {
    Assert.notNull(ioChannel, "Channel cannot be null.");
    Assert.notNull(netChannel, "NetChannel cannot be null.");
    return netChannels.register(Selectors.$(ioChannel), netChannel);
  }

  /**
   * Find the {@link NetChannel} for the given IO channel object.
   *
   * @param ioChannel The channel object.
   * @param <C> The type of the channel object.
   * @return The {@link NetChannel} associated with the given channel.
   */
  protected <C> NetChannel<IN, OUT> select(@Nonnull C ioChannel) {
    Assert.notNull(ioChannel, "Channel cannot be null.");
    Iterator<Registration<? extends NetChannel<IN, OUT>>> channs =
        netChannels.select(ioChannel).iterator();
    if (channs.hasNext()) {
      return channs.next().getObject();
    } else {
      NetChannel<IN, OUT> conn = createChannel(ioChannel);
      register(ioChannel, conn);
      notifyOpen(conn);
      return conn;
    }
  }

  /**
   * Close the given channel.
   *
   * @param channel The channel object.
   * @param <C> The type of the channel object.
   */
  protected <C> void close(@Nonnull C channel) {
    Assert.notNull(channel, "Channel cannot be null");
    for (Registration<? extends NetChannel<IN, OUT>> reg : netChannels.select(channel)) {
      NetChannel<IN, OUT> chann = reg.getObject();
      reg.cancel();
      notifyClose(chann);
    }
  }

  /**
   * Subclasses should implement this method and provide a {@link NetChannel} object.
   *
   * @param ioChannel The IO channel object to associate with this {@link reactor.net.NetChannel}.
   * @param <C> The type of the channel object.
   * @return The new {@link NetChannel} object.
   */
  protected abstract <C> NetChannel<IN, OUT> createChannel(C ioChannel);

  /** Notify this server's consumers that the server has started. */
  protected void notifyStart(final Runnable started) {
    getReactor().notify(start.getObject(), selfEvent);
    if (null != started) {
      getReactor()
          .schedule(
              new Consumer<Runnable>() {
                @Override
                public void accept(Runnable r) {
                  r.run();
                }
              },
              started);
    }
  }

  /**
   * Notify this client's consumers than a global error has occurred.
   *
   * @param error The error to notify.
   */
  protected void notifyError(@Nonnull Throwable error) {
    Assert.notNull(error, "Error cannot be null.");
    reactor.notify(error.getClass(), Event.wrap(error));
  }

  /**
   * Notify this peer's consumers that the channel has been opened.
   *
   * @param channel The channel that was opened.
   */
  protected void notifyOpen(@Nonnull NetChannel<IN, OUT> channel) {
    reactor.notify(open.getObject(), Event.wrap(channel));
  }

  /**
   * Notify this peer's consumers that the given channel has been closed.
   *
   * @param channel The channel that was closed.
   */
  protected void notifyClose(@Nonnull NetChannel<IN, OUT> channel) {
    reactor.notify(close.getObject(), Event.wrap(channel));
  }

  /** Notify this server's consumers that the server has stopped. */
  protected void notifyShutdown() {
    getReactor().notify(shutdown.getObject(), selfEvent);
  }

  /**
   * Get the {@link Codec} in use.
   *
   * @return The codec. May be {@literal null}.
   */
  @Nullable
  protected Codec<Buffer, IN, OUT> getCodec() {
    return codec;
  }

  @Nonnull
  protected Environment getEnvironment() {
    return env;
  }

  @Nonnull
  protected Reactor getReactor() {
    return reactor;
  }

  @Nonnull
  protected Collection<Consumer<NetChannel<IN, OUT>>> getConsumers() {
    return consumers;
  }

  @Nonnull
  protected Registry<NetChannel<IN, OUT>> getChannels() {
    return netChannels;
  }

  /**
   * Subclasses should implement this method to perform the actual IO channel close.
   *
   * @param onClose
   */
  protected void doClose(@Nullable Consumer<Boolean> onClose) {
    getReactor().schedule(onClose, null);
  }

  /**
   * Close the given channel.
   *
   * @param channel
   */
  protected void doCloseChannel(NetChannel<IN, OUT> channel) {
    channel.close();
  }
}