Exemple #1
0
 /**
  * Removes a local object.
  *
  * <p>This method also sends "UNSUBSCRIBE own-object-ID-as-channel" to pubsub server to stop
  * receiving PUBLISH destined to the remote object.
  *
  * @param localObject a remote object
  */
 public void removeLocalObject(RemoteObject localObject) {
   String objectId = localObject.getObjectId();
   if (localObjectsMap.remove(objectId) != null) {
     // Unsubscribes objectId as a channel to stop receiving Request
     // from remote objects via PubSub.
     driverImpl.unsubscribeChannel(objectId);
   }
 }
Exemple #2
0
 /**
  * Adds a local object as a listener of messages.
  *
  * <p>The user (i.e., RemoteObject) of this class calls this method to register the RemoteObject
  * as "local RemoteObject" with this class.
  *
  * <pre>
  *   [RemoteObject]    [RemoteObject]    [RemoteObject]
  *   dispatchEvent()  dispatchRequest() dispatchRequest()
  *         ^                 ^                 ^
  *         |                 |                 |
  *         +---------------+ + +---------------+
  *                         | | |
  *                  [MessageDispatcher]<>-----[SubscribersMap]
  *                           |
  *                        message
  *                           |
  *                    [pubsub server]
  * </pre>
  *
  * <p>This method also sends "SUBSCRIBE own-object-ID-as-channel" to pubsub server to receive
  * PUBLISH destined to the remote object, since requestSync() method sends PUBLISH as "request" to
  * the remote object.
  *
  * @param localObject a remote object
  * @see org.o3project.odenos.remoteobject.RemoteObject#dispatchEvent
  * @see org.o3project.odenos.remoteobject.RemoteObject#dispatchRequest
  */
 public void addLocalObject(RemoteObject localObject) {
   String objectId = localObject.getObjectId();
   if (localObjectsMap.putIfAbsent(objectId, localObject) == null) {
     driverImpl.subscribeChannel(objectId);
   }
   if (objectId.equals(systemManagerId)) {
     driverImpl.systemManagerAttached();
   }
 }
Exemple #3
0
 /**
  * Synchronous request/response service (remote transactions)
  *
  * <p>This method operates in two modes:
  *
  * <ul>
  *   <li>if the request is to "local RemoteObject", then this method works like a local loopback
  *       interface to dispatch the request to "local RemoteObject".
  *   <li>else if the request is to "remote RemoteObject", then this method uses RemoteTransactions
  *       class to send the request to "remote RemoteObject" via pubsub server.
  * </ul>
  *
  * <pre>
  *                 (local)
  * [RemoteObject]  [RemoteObject]
  *  requestSync()        ^
  *       |               |
  *       |               |
  *       +---------------+
  *           loopback
  *
  *                               (remote)
  * [RemoteObject]                [RemoteObject]
  *  requsetSync()                      ^
  *       |                             |
  *       |                             |
  *       +-------[pubsub server]-------+
  * </pre>
  *
  * @param request Request to be sent
  * @return Response response to the request
  * @throws Exception exception
  */
 public Response requestSync(Request request) throws Exception {
   String objectId = request.objectId;
   Response response;
   RemoteObject localObject = localObjectsMap.get(objectId);
   if (localObject != null && !localRequestsToPubSubServer) {
     // synchronized with Actor#read()
     synchronized (localObject) {
       Request requested = deepCopy(request);
       Response responsed = localObject.dispatchRequest(requested);
       response = deepCopy(responsed);
     }
     // TODO: remoteObjectsMap is not unused.
   } else if (remoteObjectsMap.containsKey(objectId)) {
     response = remoteTransactions.sendRequest(request);
   } else {
     // request to an unregistered remote object
     remoteObjectsMap.put(objectId, Boolean.valueOf(false));
     response = remoteTransactions.sendRequest(request);
   }
   return response;
 }
Exemple #4
0
 // When closed, componentManager will be deleted. (Expect when
 // componentManager is finalized, the components created by it automatically
 // deleted.)
 @Override
 public void onFinalize() {
   deleteAllComponentConnection();
   deleteAllComponentManagers();
   super.onFinalize();
 }
Exemple #5
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);
    }
  }