Beispiel #1
0
func (channel *Channel) ackBelow(tag uint64, commitTx bool) *amqp.AMQPError {
	if channel.txMode && !commitTx {
		channel.txLock.Lock()
		defer channel.txLock.Unlock()
		channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, false, false, true))
		return nil
	}
	channel.ackLock.Lock()
	defer channel.ackLock.Unlock()
	for k, unacked := range channel.awaitingAcks {
		if k <= tag || tag == 0 {
			consumer, cFound := channel.consumers[unacked.ConsumerTag]
			// Initialize resource holders array
			var rhs = []amqp.MessageResourceHolder{channel}
			if cFound {
				rhs = append(rhs, consumer)
			}
			err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs)
			// TODO: if this was an error do I still delete the ack we're waiting for?
			// The resources probably haven't been released.
			if err != nil {
				return amqp.NewSoftError(500, err.Error(), 60, 80)
			}
			delete(channel.awaitingAcks, k)

			if cFound {
				consumer.Ping()
			}
		}
	}
	// TODO: should this be an error if nothing was actually deleted and tag != 0?
	return nil
}
Beispiel #2
0
func (channel *Channel) nackBelow(tag uint64, requeue bool, commitTx bool) *amqp.AMQPError {
	channel.ackLock.Lock()
	defer channel.ackLock.Unlock()

	// Transaction mode
	if channel.txMode && !commitTx {
		channel.txLock.Lock()
		defer channel.txLock.Unlock()
		channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, true, requeue, true))
		return nil
	}

	// Non-transaction mode
	var count = 0
	for k, unacked := range channel.awaitingAcks {
		if k <= tag || tag == 0 {
			count += 1
			// Init
			consumer, cFound := channel.consumers[unacked.ConsumerTag]
			queue, qFound := channel.server.queues[unacked.QueueName]

			// Initialize resource holders array
			var rhs = []amqp.MessageResourceHolder{channel}
			if cFound {
				rhs = append(rhs, consumer)
			}

			// requeue and release the approriate resources
			if requeue && qFound {
				// If we're requeueing we release the resources but don't remove the
				// reference.
				queue.Readd(unacked.QueueName, unacked.Msg)
				for _, rh := range rhs {
					rh.ReleaseResources(unacked.Msg)
				}
			} else {
				// If we aren't re-adding, remove the ref and all associated
				// resources
				err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs)
				if err != nil {
					return amqp.NewSoftError(500, err.Error(), 60, 120)
				}
			}

			// Remove this unacked message from the ones
			// we're waiting for acks on and ping the consumer
			// since there might be a message available now
			delete(channel.awaitingAcks, k)
			if cFound {
				consumer.Ping()
			}
		}
	}
	return nil
}
Beispiel #3
0
func (channel *Channel) ackOne(tag uint64, commitTx bool) *amqp.AMQPError {
	channel.ackLock.Lock()
	defer channel.ackLock.Unlock()

	var unacked, found = channel.awaitingAcks[tag]
	if !found {
		var msg = fmt.Sprintf("Precondition Failed: Delivery Tag not found: %d", tag)
		return amqp.NewSoftError(406, msg, 60, 80)
	}
	// Tx mode
	if channel.txMode && !commitTx {
		channel.txLock.Lock()
		defer channel.txLock.Unlock()
		channel.txAcks = append(channel.txAcks, amqp.NewTxAck(tag, false, false, false))
		return nil
	}
	// Normal mode
	// Init
	consumer, cFound := channel.consumers[unacked.ConsumerTag]

	// Initialize resource holders array
	var rhs = []amqp.MessageResourceHolder{channel}
	if cFound {
		rhs = append(rhs, consumer)
	}
	err := channel.server.msgStore.RemoveRef(unacked.Msg, unacked.QueueName, rhs)
	// TODO: if this is an error, do I still delete the tag? the resources
	// probably haven't been freed
	if err != nil {
		return amqp.NewSoftError(500, err.Error(), 60, 80)
	}
	delete(channel.awaitingAcks, tag)

	if cFound {
		consumer.Ping()
	}
	return nil
}