Ejemplo n.º 1
0
  /**
   * @param config {@link MessageDispatcher}'s config
   * @see org.o3project.odenos.remoteobject.messagingclient.redis.PubSubDriverImpl
   */
  public MessageDispatcher(Config config) {

    // Config
    systemManagerId = config.getSystemManagerId();
    eventManagerId = config.getEventManagerId();
    sourceDispatcherId = config.getSourceDispatcherId();
    mode = config.getMode();
    localRequestsToPubSubServer = config.getMode().contains(MODE.LOCAL_REQUESTS_TO_PUBSUB);

    // Actor system instantiation.
    // The number of woker threads: the max number of remote transactions.
    actor = Actor.getInstance(config.getRemoteTransactionsMax());

    // Instantiates IPubSubDriver impl. class
    ClassLoader classLoader = ClassLoader.getSystemClassLoader();
    try {
      Class<?> clazz = classLoader.loadClass(config.getPubSubDriverImpl());
      Constructor<?> constructor =
          clazz.getDeclaredConstructor(Config.class, IMessageListener.class);
      driverImpl = (IPubSubDriver) constructor.newInstance(config, this);
    } catch (Exception e) {
      log.error("class load error", e);
    }

    // Remote Transactions pool
    remoteTransactions = new RemoteTransactions(this, config);
  }
Ejemplo n.º 2
0
  /**
   * onMessage implementation.
   *
   * <p>This method has two roles:
   *
   * <ul>
   *   <li>Works like a mail transfer agent to transfer a received request or event to {@link
   *       org.o3project.odenos.remoteobject.RemoteObject}.
   *   <li>Supports both synchronous and asynchronous messaging.
   * </ul>
   */
  @Override
  public void onMessage(final String channel, byte[] message) {

    serial++; // Serial number for incoming messages.

    try {
      BufferUnpacker upk = msgpack.createBufferUnpacker(message);
      // read delivery header.
      byte type = upk.readByte();
      final int sno = upk.readInt(); // Sequence number for outgoing request messages.
      final String sourceObjectId = upk.readString(); // i.e., channel

      RemoteObject localObject = null;
      Queue<Mail> mailbox = null;
      Mail mail = null;

      switch (type) {
        case TYPE_REQUEST: // Transaction(request): synchronous operation
          /*
           *  --- request --> dispatchRequest() -------> [RemoteObject]
           *                                                  |
           *  <-- response --- publishResponseAsync() <-------+
           */
          final Request request = upk.read(Request.class);
          if (log.isDebugEnabled()) {
            log.debug(
                "Request received:\n"
                    + "  MessageDispatcher: {}\n"
                    + "  sno: {}\n"
                    + "  channel: {}\n"
                    + "  method: {}\n"
                    + "  objectId: {}\n"
                    + "  sourceObjectId: {}\n"
                    + "  path: /{}/\n"
                    + "  body: {}",
                sourceDispatcherId,
                sno,
                channel,
                request.method,
                request.objectId,
                sourceObjectId,
                request.path,
                request.getBodyValue());
          }

          // Wraps the request with Mail and deliver it to a mailbox.
          String to = request.objectId;
          mail = new Mail(serial, sno, to, sourceObjectId, this, request, null);
          localObject = localObjectsMap.get(to);
          if (localObject != null) {
            mailbox = localObject.getMailbox();
            synchronized (mailbox) {
              mailbox.add(mail);
              if (!localObject.isRunning()) {
                localObject.setRunning(true);
                // Assigns a thread to read a mail in the mailbox.
                actor.read(localObject);
              }
            }
          }
          break;

        case TYPE_RESPONSE: // Transaction(response): synchronous operation
          /*
           *                                 publishRequestAsync()
           * requestSync() -> [RemoteTransaction] ---- request -----> [RemoteObject]
           *              <--            ^                                  |
           *                             |                     publishResponseAsync()
           *                             |                                  |
           *                             +- signalResponse() <-- response --+
           */
          Response response = upk.read(Response.class);
          if (log.isDebugEnabled()) {
            log.debug(
                "Response received:\n"
                    + "  MessageDispatcher: {}\n"
                    + "  channel: {}\n"
                    + "  statusCode: {}\n"
                    + "  body: {}",
                sourceDispatcherId,
                channel,
                response.statusCode,
                response.getBodyValue());
          }
          remoteTransactions.signalResponse(sno, response);
          break;

        case TYPE_EVENT: // Asynchronous
          /*
           * publishEventAsync() -- event --> dispatchEvent() --> [RemoteObject]
           *                                         :
           *                              [EventSubscriptionMap]
           */
          final Event event = upk.read(Event.class);
          if (log.isDebugEnabled()) {
            log.debug(
                "Event received:\n"
                    + "  MessageDispatcher: {}\n"
                    + "  channel: {}\n"
                    + "  body: {}",
                sourceDispatcherId,
                channel,
                event.getBodyValue());
          }

          // All the subscribers of the channel
          final Collection<String> subscribers = subscribersMap.getSubscribers(channel);
          if (subscribers == null) { // No subscribers found on the channel
            if (log.isDebugEnabled()) {
              log.debug("no subscribers subscribing the channel: {}", channel);
            }
            return; // Silently discards the event
          }

          // Wraps the event with Mail and deliver it to a mailbox.
          for (String subscriber : subscribers) {
            localObject = localObjectsMap.get(subscriber);
            if (localObject != null) {
              mail = new Mail(serial, sno, subscriber, channel, this, null, event);
              mailbox = localObject.getMailbox();
              synchronized (mailbox) {
                mailbox.add(mail);
                if (!localObject.isRunning()) {
                  localObject.setRunning(true);
                  // Assigns a thread to read a mail in the mailbox.
                  actor.read(localObject);
                }
              }
            }
          }
          break;

        default:
          break;
      }
    } catch (Exception e) {
      log.error("onMessage failed", e);
    }
  }