Example #1
0
  /**
   * This method is invoked remotely via jgroups. It builds a snapshot of the local subscription
   * state and sends it back to the requesting server by calling its receiveSubscriptions method.
   *
   * @exclude
   */
  public void sendSubscriptions(String destinationId, Object remoteAddress) {
    MessageDestination destination = (MessageDestination) getDestination(destinationId);
    Object subscriptions;

    /*
     * Avoid trying to use the cluster stuff if this destination does not
     * exist or is not clustered on this server.
     */
    if (destination == null) {
      if (Log.isError())
        Log.getLogger(LOG_CATEGORY)
            .error(
                "Destination: "
                    + destinationId
                    + " does not exist on this server but we received a request for the subscription info from a peer server where the destination exists as clustered.  Check the cluster configuration for this destination and make sure it matches on all servers.");
      return;
    } else if (!destination.isClustered()) {
      if (Log.isError())
        Log.getLogger(LOG_CATEGORY)
            .error(
                "Destination: "
                    + destinationId
                    + " is not clustered on this server but we received a request for the subscription info from a peer server which is clustered.  Check the cluster configuration for this destination and make sure it matches on all servers.");
      return;
    }

    RemoteSubscriptionManager subMgr = destination.getRemoteSubscriptionManager();

    /*
     * The remote server has no subscriptions initially since it has not
     * started yet.  We initialize the server here so that when it sends
     * the first add subscription request, we'll receive it.  This is because
     * servers will not process remote add/remove subscribe requests until
     * they have received the subscription state from each server.
     */
    subMgr.setSubscriptionState(Collections.EMPTY_LIST, remoteAddress);

    /*
     * To ensure that we send the remote server a clean copy of the subscription
     * table we need to block out the code which adds/removes subscriptions and sends
     * them to remote servers between here...
     */
    try {
      subscribeLock.writeLock().lock();
      subscriptions = destination.getSubscriptionManager().getSubscriptionState();
      ClusterManager clm = getMessageBroker().getClusterManager();
      clm.invokePeerToPeerOperation(
          getClass().getName(),
          destinationId,
          "receiveSubscriptions",
          new Object[] {destinationId, subscriptions},
          remoteAddress);
    } finally {
      /* ... And here */
      subscribeLock.writeLock().unlock();
    }
  }
Example #2
0
  /**
   * This is called remotely from other cluster members when a new remote subscription is
   * identified.
   *
   * <p>We add or remove a remote subscription...
   */
  public void subscribeFromPeer(
      String destinationId,
      Boolean subscribe,
      String selector,
      String subtopic,
      Object remoteAddress) {
    Destination destination = getDestination(destinationId);

    RemoteSubscriptionManager subMgr =
        ((MessageDestination) destination).getRemoteSubscriptionManager();

    if (destination instanceof MessageDestination) {
      if (debug)
        Log.getLogger(MessageService.LOG_CATEGORY)
            .debug(
                "Received subscription from peer: "
                    + remoteAddress
                    + " subscribe? "
                    + subscribe
                    + " selector: "
                    + selector
                    + " subtopic: "
                    + subtopic);
      if (subscribe) subMgr.addSubscriber(remoteAddress, selector, subtopic, null);
      else subMgr.removeSubscriber(remoteAddress, selector, subtopic, null);
    } else if (Log.isError())
      Log.getLogger(LOG_CATEGORY)
          .error(
              "subscribeFromPeer called with destination: "
                  + destinationId
                  + " that is not a MessageDestination");
  }
Example #3
0
  /** Return an entry from the property descrpitor cache for a class. */
  private PropertyDescriptorCacheEntry getPropertyDescriptorCacheEntry(Class c) {
    PropertyDescriptorCacheEntry pce =
        (PropertyDescriptorCacheEntry) propertyDescriptorCache.get(c);

    try {
      if (pce == null) {
        BeanInfo beanInfo = Introspector.getBeanInfo(c, stopClass);
        pce = new PropertyDescriptorCacheEntry();
        pce.propertyDescriptors = beanInfo.getPropertyDescriptors();
        pce.propertiesByName = createPropertiesByNameMap(pce.propertyDescriptors, c.getFields());
        if (cachePropertiesDescriptors) {
          synchronized (propertyDescriptorCache) {
            PropertyDescriptorCacheEntry pce2 =
                (PropertyDescriptorCacheEntry) propertyDescriptorCache.get(c);
            if (pce2 == null) propertyDescriptorCache.put(c, pce);
            else pce = pce2;
          }
        }
      }
    } catch (IntrospectionException ex) {
      // Log failed property set errors
      if (Log.isError()) {
        Logger log = Log.getLogger(LOG_CATEGORY);
        log.error(
            "Failed to introspect object of type: " + c + " error: " + ExceptionUtil.toString(ex));
      }

      // Return an empty descriptor rather than crashing
      pce = new PropertyDescriptorCacheEntry();
      pce.propertyDescriptors = new PropertyDescriptor[0];
      pce.propertiesByName = new TreeMap();
    }
    return pce;
  }
Example #4
0
 /**
  * This method is provided for a cluster peer broadcast, it is not invoked locally. It is used by
  * remote clients to send their subscription table to this server.
  *
  * @exclude
  */
 public void receiveSubscriptions(
     String destinationId, Object subscriptions, Object senderAddress) {
   Destination destination = getDestination(destinationId);
   if (destination instanceof MessageDestination)
     ((MessageDestination) destination)
         .getRemoteSubscriptionManager()
         .setSubscriptionState(subscriptions, senderAddress);
   else if (subscriptions != null && Log.isError())
     Log.getLogger(LOG_CATEGORY)
         .error(
             "receiveSubscriptions called with non-null value but destination: "
                 + destinationId
                 + " is not a MessageDestination");
 }
Example #5
0
  /**
   * A utility method to handle incoming throttling results in a common way.
   *
   * @param message The message that is being throttled.
   * @param throttleResult The throttling result.
   * @param isClientLevel Whether the message is being throttled at the client level or not.
   */
  protected void handleIncomingThrottleResult(
      Message message, ThrottleResult throttleResult, boolean isClientLevel) {
    Result result = throttleResult.getResult();

    // Update the management metrics.
    if (result != Result.OK && isManaged()) {
      if (isClientLevel)
        ((ThrottleManagerControl) getControl()).incrementClientIncomingMessageThrottleCount();
      else
        ((ThrottleManagerControl) getControl()).incrementDestinationIncomingMessageThrottleCount();
    }

    // Result can be IGNORE or ERROR (or NONE which means no throttling).
    if (result == Result.IGNORE || result == Result.ERROR) {
      if (isClientLevel)
        throttleResult.setDetail(
            "Message '"
                + message.getMessageId()
                + "' throttled: Too many messages sent by the client '"
                + message.getClientId()
                + "' in too small of a time interval "
                + throttleResult.getDetail());
      else
        throttleResult.setDetail(
            "Message '"
                + message.getMessageId()
                + "' throttled: Too many messages sent to destination '"
                + message.getDestination()
                + "' in too small of a time interval "
                + throttleResult.getDetail());

      String detail = throttleResult.getDetail();
      if (result == Result.ERROR) {
        if (Log.isError()) Log.getLogger(LOG_CATEGORY).error(detail);
        // And, throw an exception, so the client gets the error.
        MessageException me = new MessageException(detail);
        throw me;
      }
      // Otherwise, just log it.
      if (Log.isInfo()) Log.getLogger(LOG_CATEGORY).info(detail);
    }
  }