コード例 #1
0
  private void callOnMessage() throws Exception {
    if (closing || stopped) {
      return;
    }

    session.workDone();

    // We pull the message from the buffer from inside the Runnable so we can ensure priority
    // ordering. If we just added a Runnable with the message to the executor immediately as we get
    // it
    // we could not do that

    ClientMessageInternal message;

    // Must store handler in local variable since might get set to null
    // otherwise while this is executing and give NPE when calling onMessage
    MessageHandler theHandler = handler;

    if (theHandler != null) {
      if (rateLimiter != null) {
        rateLimiter.limit();
      }

      failedOver = false;

      synchronized (this) {
        message = buffer.poll();
      }

      if (message != null) {
        if (message.containsProperty(ClientConsumerImpl.FORCED_DELIVERY_MESSAGE)) {
          // Ignore, this could be a relic from a previous receiveImmediate();
          return;
        }

        boolean expired = message.isExpired();

        flowControlBeforeConsumption(message);

        if (!expired) {
          if (isTrace) {
            ActiveMQClientLogger.LOGGER.trace("Calling handler.onMessage");
          }
          final ClassLoader originalLoader =
              AccessController.doPrivileged(
                  new PrivilegedAction<ClassLoader>() {
                    public ClassLoader run() {
                      ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();

                      Thread.currentThread().setContextClassLoader(contextClassLoader);

                      return originalLoader;
                    }
                  });

          onMessageThread = Thread.currentThread();
          try {
            theHandler.onMessage(message);
          } finally {
            try {
              AccessController.doPrivileged(
                  new PrivilegedAction<Object>() {
                    public Object run() {
                      Thread.currentThread().setContextClassLoader(originalLoader);
                      return null;
                    }
                  });
            } catch (Exception e) {
              ActiveMQClientLogger.LOGGER.warn(e.getMessage(), e);
            }

            onMessageThread = null;
          }

          if (isTrace) {
            ActiveMQClientLogger.LOGGER.trace("Handler.onMessage done");
          }

          if (message.isLargeMessage()) {
            message.discardBody();
          }
        } else {
          session.expire(this, message);
        }

        // If slow consumer, we need to send 1 credit to make sure we get another message
        if (clientWindowSize == 0) {
          startSlowConsumer();
        }
      }
    }
  }
コード例 #2
0
  private ClientMessage receive(final long timeout, final boolean forcingDelivery)
      throws ActiveMQException {
    checkClosed();

    if (largeMessageReceived != null) {
      // Check if there are pending packets to be received
      largeMessageReceived.discardBody();
      largeMessageReceived = null;
    }

    if (rateLimiter != null) {
      rateLimiter.limit();
    }

    if (handler != null) {
      throw ActiveMQClientMessageBundle.BUNDLE.messageHandlerSet();
    }

    if (clientWindowSize == 0) {
      startSlowConsumer();
    }

    receiverThread = Thread.currentThread();

    // To verify if deliveryForced was already call
    boolean deliveryForced = false;
    // To control when to call deliveryForce
    boolean callForceDelivery = false;

    long start = -1;

    long toWait = timeout == 0 ? Long.MAX_VALUE : timeout;

    try {
      while (true) {
        ClientMessageInternal m = null;

        synchronized (this) {
          while ((stopped || (m = buffer.poll()) == null) && !closed && toWait > 0) {
            if (start == -1) {
              start = System.currentTimeMillis();
            }

            if (m == null && forcingDelivery) {
              if (stopped) {
                break;
              }

              // we only force delivery once per call to receive
              if (!deliveryForced) {
                callForceDelivery = true;
                break;
              }
            }

            try {
              wait(toWait);
            } catch (InterruptedException e) {
              throw new ActiveMQInterruptedException(e);
            }

            if (m != null || closed) {
              break;
            }

            long now = System.currentTimeMillis();

            toWait -= now - start;

            start = now;
          }
        }

        if (failedOver) {
          if (m == null) {
            // if failed over and the buffer is null, we reset the state and try it again
            failedOver = false;
            deliveryForced = false;
            toWait = timeout == 0 ? Long.MAX_VALUE : timeout;
            continue;
          } else {
            failedOver = false;
          }
        }

        if (callForceDelivery) {
          if (isTrace) {
            ActiveMQClientLogger.LOGGER.trace("Forcing delivery");
          }
          // JBPAPP-6030 - Calling forceDelivery outside of the lock to avoid distributed dead locks
          sessionContext.forceDelivery(this, forceDeliveryCount++);
          callForceDelivery = false;
          deliveryForced = true;
          continue;
        }

        if (m != null) {
          session.workDone();

          if (m.containsProperty(ClientConsumerImpl.FORCED_DELIVERY_MESSAGE)) {
            long seq = m.getLongProperty(ClientConsumerImpl.FORCED_DELIVERY_MESSAGE);

            // Need to check if forceDelivery was called at this call
            // As we could be receiving a message that came from a previous call
            if (forcingDelivery && deliveryForced && seq == forceDeliveryCount - 1) {
              // forced delivery messages are discarded, nothing has been delivered by the queue
              resetIfSlowConsumer();

              if (isTrace) {
                ActiveMQClientLogger.LOGGER.trace(
                    "There was nothing on the queue, leaving it now:: returning null");
              }

              return null;
            } else {
              if (isTrace) {
                ActiveMQClientLogger.LOGGER.trace(
                    "Ignored force delivery answer as it belonged to another call");
              }
              // Ignore the message
              continue;
            }
          }
          // if we have already pre acked we can't expire
          boolean expired = m.isExpired();

          flowControlBeforeConsumption(m);

          if (expired) {
            m.discardBody();

            session.expire(this, m);

            if (clientWindowSize == 0) {
              startSlowConsumer();
            }

            if (toWait > 0) {
              continue;
            } else {
              return null;
            }
          }

          if (m.isLargeMessage()) {
            largeMessageReceived = m;
          }

          if (isTrace) {
            ActiveMQClientLogger.LOGGER.trace("Returning " + m);
          }

          return m;
        } else {
          if (isTrace) {
            ActiveMQClientLogger.LOGGER.trace("Returning null");
          }
          resetIfSlowConsumer();
          return null;
        }
      }
    } finally {
      receiverThread = null;
    }
  }