示例#1
0
 /**
  * Asynchronous event publication service for requestSync().
  *
  * <p>requestSync() turns into this method via RemoteMessageTransport.
  *
  * <p>Remote objects uses this method to publish a request as event asynchronously.
  *
  * <p>Although this method is asynchronous, {@link RemoteTransactions} provides a synchronous
  * method to wait for a response from another remote object.
  */
 protected void publishRequestAsync(final int sno, final Request request) throws IOException {
   BufferPacker pk = msgpack.createBufferPacker();
   // write delivery header.
   pk.write(TYPE_REQUEST);
   pk.write(sno);
   pk.write(getSourceDispatcherId());
   // write delivery body.
   pk.write(request);
   byte[] message = pk.toByteArray();
   String channel = request.objectId;
   // PUBLISH
   driverImpl.publish(channel, message);
   if (log.isDebugEnabled()) {
     log.debug(
         "Request sent:\n"
             + "  MessageDispatcher: {}\n"
             + "  sno: {}\n"
             + "  channel: {}\n"
             + "  method: {}\n"
             + "  objectId: {}\n"
             + "  path: /{}/\n"
             + "  body: {}",
         sourceDispatcherId,
         sno,
         channel,
         request.method,
         request.objectId,
         request.path,
         request.getBodyValue());
   }
 }
示例#2
0
  @Override
  protected Response onRequest(final Request req) {
    log.debug("onRequest: " + req.method + ", " + req.path);

    RequestParser<IActionCallback>.ParsedRequest parsed = parser.parse(req);
    if (parsed == null) {
      // Transfer Other Component
      Pattern pattern = Pattern.compile("^components/.*/.*");
      if (pattern.matcher(req.path).matches()) {
        String compId = getDestinationCompId(req.path);
        String command = getDestinationPath(req.path);
        return transferComponent(compId, command, req.method, req.getBodyValue());
      }

      return new Response(Response.BAD_REQUEST, null);
    }

    Response response = null;
    try {
      IActionCallback callback = parsed.getResult();
      if (callback == null) {
        return new Response(Response.BAD_REQUEST, null);
      }
      response = callback.process(parsed);
    } catch (Exception e) {
      log.error("Exception Request: " + req.method + ", " + req.path, e);
      response = new Response(Response.BAD_REQUEST, null);
    }
    if (response == null) {
      response = new Response(Response.BAD_REQUEST, null);
    }
    return response;
  }
示例#3
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);
    }
  }