private void doRollback( final boolean clientFailed, final boolean lastMessageAsDelived, final Transaction theTx) throws Exception { boolean wasStarted = started; List<MessageReference> toCancel = new ArrayList<MessageReference>(); for (ServerConsumer consumer : consumers.values()) { if (wasStarted) { consumer.setStarted(false); } toCancel.addAll(consumer.cancelRefs(clientFailed, lastMessageAsDelived, theTx)); } for (MessageReference ref : toCancel) { ref.getQueue().cancel(theTx, ref); } if (wasStarted) { theTx.addOperation( new TransactionOperationAbstract() { public void afterRollback(Transaction tx) { for (ServerConsumer consumer : consumers.values()) { consumer.setStarted(true); } } }); } theTx.rollback(); }
public synchronized void xaStart(final Xid xid) throws Exception { if (tx != null) { HornetQServerLogger.LOGGER.xidReplacedOnXStart(tx.getXid().toString(), xid.toString()); try { if (tx.getState() != Transaction.State.PREPARED) { // we don't want to rollback anything prepared here if (tx.getXid() != null) { resourceManager.removeTransaction(tx.getXid()); } tx.rollback(); } } catch (Exception e) { HornetQServerLogger.LOGGER.debug( "An exception happened while we tried to debug the previous tx, we can ignore this exception", e); } } tx = newTransaction(xid); if (isTrace) { HornetQServerLogger.LOGGER.trace("xastart into tx= " + tx); } boolean added = resourceManager.putTransaction(xid, tx); if (!added) { final String msg = "Cannot start, there is already a xid " + tx.getXid(); throw new HornetQXAException(XAException.XAER_DUPID, msg); } }
private void doRollback( final boolean clientFailed, final boolean lastMessageAsDelived, final Transaction theTx) throws Exception { boolean wasStarted = started; List<MessageReference> toCancel = new ArrayList<MessageReference>(); for (ServerConsumer consumer : consumers.values()) { if (wasStarted) { consumer.setStarted(false); } toCancel.addAll(consumer.cancelRefs(clientFailed, lastMessageAsDelived, theTx)); } for (MessageReference ref : toCancel) { ref.getQueue().cancel(theTx, ref); } // if we failed don't restart as an attempt to deliver messages may be made before we actually // close the consumer if (wasStarted && !clientFailed) { theTx.addOperation( new TransactionOperationAbstract() { @Override public void afterRollback(Transaction tx) { for (ServerConsumer consumer : consumers.values()) { consumer.setStarted(true); } } }); } theTx.rollback(); }
public void individualAcknowledge(final long consumerID, final long messageID) throws Exception { ServerConsumer consumer = consumers.get(consumerID); if (this.xa && tx == null) { throw new HornetQXAException(XAException.XAER_PROTO, "Invalid transaction state"); } if (tx != null && tx.getState() == State.ROLLEDBACK) { // JBPAPP-8845 - if we let stuff to be acked on a rolled back TX, we will just // have these messages to be stuck on the limbo until the server is restarted // The tx has already timed out, so we need to ack and rollback immediately Transaction newTX = newTransaction(); consumer.individualAcknowledge(autoCommitAcks, tx, messageID); newTX.rollback(); } else { consumer.individualAcknowledge(autoCommitAcks, tx, messageID); } }
public void acknowledge(final long consumerID, final long messageID) throws Exception { ServerConsumer consumer = consumers.get(consumerID); if (consumer == null) { throw HornetQMessageBundle.BUNDLE.consumerDoesntExist(consumerID); } if (tx != null && tx.getState() == State.ROLLEDBACK) { // JBPAPP-8845 - if we let stuff to be acked on a rolled back TX, we will just // have these messages to be stuck on the limbo until the server is restarted // The tx has already timed out, so we need to ack and rollback immediately Transaction newTX = newTransaction(); consumer.acknowledge(autoCommitAcks, newTX, messageID); newTX.rollback(); } else { consumer.acknowledge(autoCommitAcks, tx, messageID); } }
public void acknowledge(final boolean autoCommitAcks, Transaction tx, final long messageID) throws Exception { if (browseOnly) { return; } // Acknowledge acknowledges all refs delivered by the consumer up to and including the one // explicitly // acknowledged // We use a transaction here as if the message is not found, we should rollback anything done // This could eventually happen on retries during transactions, and we need to make sure we // don't ACK things we are not supposed to acknowledge boolean startedTransaction = false; if (tx == null || autoCommitAcks) { startedTransaction = true; tx = new TransactionImpl(storageManager); } try { MessageReference ref; do { ref = deliveringRefs.poll(); if (HornetQServerLogger.LOGGER.isTraceEnabled()) { HornetQServerLogger.LOGGER.trace( "ACKing ref " + ref + " on tx= " + tx + ", consumer=" + this); } if (ref == null) { throw HornetQMessageBundle.BUNDLE.consumerNoReference( id, messageID, messageQueue.getName()); } ref.getQueue().acknowledge(tx, ref); } while (ref.getMessage().getMessageID() != messageID); if (startedTransaction) { tx.commit(); } } catch (HornetQException e) { if (startedTransaction) { tx.rollback(); } else { tx.markAsRollbackOnly(e); } throw e; } catch (Throwable e) { HornetQServerLogger.LOGGER.errorAckingMessage((Exception) e); HornetQException hqex = new HornetQIllegalStateException(e.getMessage()); if (startedTransaction) { tx.rollback(); } else { tx.markAsRollbackOnly(hqex); } throw hqex; } }
public void close(final boolean failed) throws Exception { callback.removeReadyListener(this); setStarted(false); LargeMessageDeliverer del = largeMessageDeliverer; if (del != null) { del.finish(); } if (browseOnly) { browserDeliverer.close(); } else { messageQueue.removeConsumer(this); } session.removeConsumer(id); LinkedList<MessageReference> refs = cancelRefs(failed, false, null); Iterator<MessageReference> iter = refs.iterator(); Transaction tx = new TransactionImpl(storageManager); while (iter.hasNext()) { MessageReference ref = iter.next(); ref.getQueue().cancel(tx, ref); } tx.rollback(); if (!browseOnly) { TypedProperties props = new TypedProperties(); props.putSimpleStringProperty(ManagementHelper.HDR_ADDRESS, binding.getAddress()); props.putSimpleStringProperty(ManagementHelper.HDR_CLUSTER_NAME, binding.getClusterName()); props.putSimpleStringProperty(ManagementHelper.HDR_ROUTING_NAME, binding.getRoutingName()); props.putSimpleStringProperty( ManagementHelper.HDR_FILTERSTRING, filter == null ? null : filter.getFilterString()); props.putIntProperty(ManagementHelper.HDR_DISTANCE, binding.getDistance()); props.putIntProperty(ManagementHelper.HDR_CONSUMER_COUNT, messageQueue.getConsumerCount()); // HORNETQ-946 props.putSimpleStringProperty( ManagementHelper.HDR_USER, SimpleString.toSimpleString(session.getUsername())); props.putSimpleStringProperty( ManagementHelper.HDR_REMOTE_ADDRESS, SimpleString.toSimpleString( ((ServerSessionImpl) session).getRemotingConnection().getRemoteAddress())); props.putSimpleStringProperty( ManagementHelper.HDR_SESSION_NAME, SimpleString.toSimpleString(session.getName())); Notification notification = new Notification(null, NotificationType.CONSUMER_CLOSED, props); managementService.sendNotification(notification); } }