Beispiel #1
0
  public void sendContinuations(
      final int packetSize, final long messageBodySize, final byte[] body, final boolean continues)
      throws Exception {
    if (currentLargeMessage == null) {
      throw HornetQMessageBundle.BUNDLE.largeMessageNotInitialised();
    }

    // Immediately release the credits for the continuations- these don't contribute to the
    // in-memory size
    // of the message

    currentLargeMessage.addBytes(body);

    if (!continues) {
      currentLargeMessage.releaseResources();

      if (messageBodySize >= 0) {
        currentLargeMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, messageBodySize);
      }

      doSend(currentLargeMessage, false);

      currentLargeMessage = null;
    }
  }
    public void finish() throws Exception {
      synchronized (lock) {
        if (largeMessage == null) {
          // handleClose could be calling close while handle is also calling finish.
          // As a result one of them could get here after the largeMessage is already gone.
          // On that case we just ignore this call
          return;
        }
        if (context != null) {
          context.close();
        }

        largeMessage.releaseResources();

        largeMessage.decrementDelayDeletionCount();

        if (preAcknowledge && !browseOnly) {
          // PreAck will have an extra reference
          largeMessage.decrementDelayDeletionCount();
        }

        largeMessageDeliverer = null;

        largeMessage = null;
      }
    }
Beispiel #3
0
  private synchronized void doClose(final boolean failed) throws Exception {
    if (tx != null && tx.getXid() == null) {
      // We only rollback local txs on close, not XA tx branches

      try {
        rollback(failed, false);
      } catch (Exception e) {
        HornetQLogger.LOGGER.warn(e.getMessage(), e);
      }
    }

    Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values());

    for (ServerConsumer consumer : consumersClone) {
      consumer.close(failed);
    }

    consumers.clear();

    server.removeSession(name);

    if (currentLargeMessage != null) {
      try {
        currentLargeMessage.deleteFile();
      } catch (Throwable error) {
        HornetQLogger.LOGGER.errorDeletingLargeMessageFile(error);
      }
    }

    remotingConnection.removeFailureListener(this);

    callback.closed();
  }
    public LargeMessageDeliverer(final LargeServerMessage message, final MessageReference ref)
        throws Exception {
      largeMessage = message;

      largeMessage.incrementDelayDeletionCount();

      this.ref = ref;
    }
Beispiel #5
0
  public void sendInternalLarge(ServerMessageImpl message, boolean direct) throws Exception {
    int headerSize = message.getHeadersAndPropertiesEncodeSize();
    if (headerSize >= connection.getMinLargeMessageSize()) {
      throw BUNDLE.headerTooBig();
    }

    StorageManager storageManager = ((ServerSessionImpl) session).getStorageManager();
    long id = storageManager.generateUniqueID();
    LargeServerMessage largeMessage = storageManager.createLargeMessage(id, message);

    byte[] bytes = new byte[message.getBodyBuffer().writerIndex() - MessageImpl.BODY_OFFSET];
    message.getBodyBuffer().readBytes(bytes);

    largeMessage.addBytes(bytes);

    largeMessage.releaseResources();

    largeMessage.putLongProperty(Message.HDR_LARGE_BODY_SIZE, bytes.length);

    session.send(largeMessage, direct);

    largeMessage = null;
  }
Beispiel #6
0
  public boolean delete(final PagedMessage[] messages) throws Exception {
    if (storageManager != null) {
      storageManager.pageDeleted(storeName, pageId);
    }

    if (isDebug) {
      HornetQServerLogger.LOGGER.debug("Deleting pageId=" + pageId + " on store " + storeName);
    }

    if (messages != null) {
      for (PagedMessage msg : messages) {
        if (msg.getMessage().isLargeMessage()) {
          LargeServerMessage lmsg = (LargeServerMessage) msg.getMessage();

          // Remember, cannot call delete directly here
          // Because the large-message may be linked to another message
          // or it may still being delivered even though it has been acked already
          lmsg.decrementDelayDeletionCount();
        }
      }
    }

    try {
      if (suspiciousRecords) {
        HornetQServerLogger.LOGGER.pageInvalid(file.getFileName(), file.getFileName());
        file.renameTo(file.getFileName() + ".invalidPage");
      } else {
        file.delete();
      }

      return true;
    } catch (Exception e) {
      HornetQServerLogger.LOGGER.pageDeleteError(e);
      return false;
    }
  }
Beispiel #7
0
  public void sendLarge(final MessageInternal message) throws Exception {
    // need to create the LargeMessage before continue
    long id = storageManager.generateUniqueID();

    LargeServerMessage largeMsg = storageManager.createLargeMessage(id, message);

    if (HornetQLogger.LOGGER.isTraceEnabled()) {
      HornetQLogger.LOGGER.trace("sendLarge::" + largeMsg);
    }

    if (currentLargeMessage != null) {
      HornetQLogger.LOGGER.replacingIncompleteLargeMessage(currentLargeMessage.getMessageID());
    }

    currentLargeMessage = largeMsg;
  }
  private void doClose(final boolean failed) throws Exception {
    synchronized (this) {
      if (closed) return;

      if (tx != null && tx.getXid() == null) {
        // We only rollback local txs on close, not XA tx branches

        try {
          rollback(failed, false);
        } catch (Exception e) {
          HornetQServerLogger.LOGGER.warn(e.getMessage(), e);
        }
      }

      server.removeSession(name);

      remotingConnection.removeFailureListener(this);

      callback.closed();

      closed = true;
    }

    // putting closing of consumers outside the sync block
    // https://issues.jboss.org/browse/HORNETQ-1141
    Set<ServerConsumer> consumersClone = new HashSet<ServerConsumer>(consumers.values());

    for (ServerConsumer consumer : consumersClone) {
      consumer.close(failed);
    }

    consumers.clear();

    if (currentLargeMessage != null) {
      try {
        currentLargeMessage.deleteFile();
      } catch (Throwable error) {
        HornetQServerLogger.LOGGER.errorDeletingLargeMessageFile(error);
      }
    }
  }
    public boolean deliver() throws Exception {
      lockDelivery.readLock().lock();
      try {
        if (largeMessage == null) {
          return true;
        }

        if (availableCredits != null && availableCredits.get() <= 0) {
          if (HornetQServerLogger.LOGGER.isTraceEnabled()) {
            HornetQServerLogger.LOGGER.trace(
                this
                    + "::FlowControl::delivery largeMessage interrupting as there are no more credits, available="
                    + availableCredits);
          }

          return false;
        }

        if (!sentInitialPacket) {
          context = largeMessage.getBodyEncoder();

          sizePendingLargeMessage = context.getLargeBodySize();

          context.open();

          sentInitialPacket = true;

          int packetSize =
              callback.sendLargeMessage(
                  largeMessage, id, context.getLargeBodySize(), ref.getDeliveryCount());

          if (availableCredits != null) {
            availableCredits.addAndGet(-packetSize);

            if (HornetQServerLogger.LOGGER.isTraceEnabled()) {
              HornetQServerLogger.LOGGER.trace(
                  this
                      + "::FlowControl::"
                      + " deliver initialpackage with "
                      + packetSize
                      + " delivered, available now = "
                      + availableCredits);
            }
          }

          // Execute the rest of the large message on a different thread so as not to tie up the
          // delivery thread
          // for too long

          resumeLargeMessage();

          return false;
        } else {
          if (availableCredits != null && availableCredits.get() <= 0) {
            if (ServerConsumerImpl.isTrace) {
              HornetQServerLogger.LOGGER.trace(
                  this
                      + "::FlowControl::deliverLargeMessage Leaving loop of send LargeMessage because of credits, available="
                      + availableCredits);
            }

            return false;
          }

          int localChunkLen = 0;

          localChunkLen =
              (int)
                  Math.min(
                      sizePendingLargeMessage - positionPendingLargeMessage, minLargeMessageSize);

          HornetQBuffer bodyBuffer = HornetQBuffers.fixedBuffer(localChunkLen);

          context.encode(bodyBuffer, localChunkLen);

          byte[] body = bodyBuffer.toByteBuffer().array();

          int packetSize =
              callback.sendLargeMessageContinuation(
                  id,
                  body,
                  positionPendingLargeMessage + localChunkLen < sizePendingLargeMessage,
                  false);

          int chunkLen = body.length;

          if (availableCredits != null) {
            availableCredits.addAndGet(-packetSize);

            if (HornetQServerLogger.LOGGER.isTraceEnabled()) {
              HornetQServerLogger.LOGGER.trace(
                  this
                      + "::FlowControl::largeMessage deliver continuation, packetSize="
                      + packetSize
                      + " available now="
                      + availableCredits);
            }
          }

          positionPendingLargeMessage += chunkLen;

          if (positionPendingLargeMessage < sizePendingLargeMessage) {
            resumeLargeMessage();

            return false;
          }
        }

        if (ServerConsumerImpl.isTrace) {
          HornetQServerLogger.LOGGER.trace("Finished deliverLargeMessage");
        }

        finish();

        return true;
      } finally {
        lockDelivery.readLock().unlock();
      }
    }
  public HandleStatus handle(final MessageReference ref) throws Exception {
    if (availableCredits != null && availableCredits.get() <= 0) {
      if (HornetQServerLogger.LOGGER.isDebugEnabled()) {
        HornetQServerLogger.LOGGER.debug(
            this
                + " is busy for the lack of credits. Current credits = "
                + availableCredits
                + " Can't receive reference "
                + ref);
      }

      return HandleStatus.BUSY;
    }

    // TODO - https://jira.jboss.org/browse/HORNETQ-533
    // if (!writeReady.get())
    // {
    // return HandleStatus.BUSY;
    // }

    synchronized (lock) {
      // If the consumer is stopped then we don't accept the message, it
      // should go back into the
      // queue for delivery later.
      if (!started || transferring) {
        return HandleStatus.BUSY;
      }

      // If there is a pendingLargeMessage we can't take another message
      // This has to be checked inside the lock as the set to null is done inside the lock
      if (largeMessageDeliverer != null) {
        if (HornetQServerLogger.LOGGER.isDebugEnabled()) {
          HornetQServerLogger.LOGGER.debug(
              this
                  + " is busy delivering large message "
                  + largeMessageDeliverer
                  + ", can't deliver reference "
                  + ref);
        }
        return HandleStatus.BUSY;
      }
      final ServerMessage message = ref.getMessage();

      if (filter != null && !filter.match(message)) {
        if (HornetQServerLogger.LOGGER.isTraceEnabled()) {
          HornetQServerLogger.LOGGER.trace(
              "Reference " + ref + " is a noMatch on consumer " + this);
        }
        return HandleStatus.NO_MATCH;
      }

      if (HornetQServerLogger.LOGGER.isTraceEnabled()) {
        HornetQServerLogger.LOGGER.trace("Handling reference " + ref);
      }

      if (!browseOnly) {
        if (!preAcknowledge) {
          deliveringRefs.add(ref);
        }

        ref.handled();

        ref.incrementDeliveryCount();

        // If updateDeliveries = false (set by strict-update),
        // the updateDeliveryCount would still be updated after c
        if (strictUpdateDeliveryCount && !ref.isPaged()) {
          if (ref.getMessage().isDurable()
              && ref.getQueue().isDurable()
              && !ref.getQueue().isInternalQueue()
              && !ref.isPaged()) {
            storageManager.updateDeliveryCount(ref);
          }
        }

        if (preAcknowledge) {
          if (message.isLargeMessage()) {
            // we must hold one reference, or the file will be deleted before it could be delivered
            ((LargeServerMessage) message).incrementDelayDeletionCount();
          }

          // With pre-ack, we ack *before* sending to the client
          ref.getQueue().acknowledge(ref);
        }
      }

      if (message.isLargeMessage()) {
        largeMessageDeliverer = new LargeMessageDeliverer((LargeServerMessage) message, ref);
      }

      lockDelivery.readLock().lock();

      return HandleStatus.HANDLED;
    }
  }