All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.objectweb.dream.queue.buffer.BufferAscendingSequenceNumber Maven / Gradle / Ivy

/**
 * Dream
 * Copyright (C) 2003-2004 INRIA Rhone-Alpes
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Contact: [email protected]
 *
 * Initial developer(s): Vivien Quema
 * Contributor(s): Romain Lenglet
 */

package org.objectweb.dream.queue.buffer;

import java.lang.ref.Reference;

import org.objectweb.dream.message.Message;
import org.objectweb.dream.pool.Recyclable;
import org.objectweb.dream.queue.SequenceNumberChunk;
import org.objectweb.dream.util.Error;
import org.objectweb.fractal.api.Component;
import org.objectweb.fractal.fraclet.annotation.annotations.Attribute;
import org.objectweb.fractal.fraclet.annotation.annotations.Service;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.dream.dreamannotation.DreamComponent;
import org.objectweb.dream.dreamannotation.DreamMonolog;

/**
 * Implementation of the Buffer interface using a sorted list. This
 * buffer sorts messages according to a sequence number. For that purpose all
 * messages must contain a {@link SequenceNumberChunk}chunk. The name under
 * which this chunk is registered is specified using the
 * sortingChunkName.
 * 

* This buffer guarantees that if message m1 (with sequence number sn * ) is removed from the buffer, then next message to be removed will have * sequence number sn+1 . As a consequence, the number of available * message may be different from the number of stored messages. *

*

* Note: This buffer DOES NOT ALLOW incoming handlers that drop messages. * Indicators on available space, available messages, and stored * messages are expressed as number of messages. * * @see BufferAdd * @see BufferRemove * @see AbstractBuffer */ @DreamComponent(controllerDesc = "dreamUnstoppablePrimitive") public class BufferAscendingSequenceNumber extends AbstractBuffer { // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ /** * The maximal capacity of the buffer. Inherited from {@link AbstractBuffer} */ @Attribute(argument = "maxCapacity") protected int maxCapacity = 0; /** The last sequence number in sequence. */ @Attribute(argument = "lastInSequence") protected long lastInSequence = -1; /** * The name under which the chunk containing the sequence number is * registered. */ @Attribute(argument = "sortingChunkName") protected String sortingChunkName; // ------------------------------------------------------------------------ // Fields // ------------------------------------------------------------------------ /** The first element stored in this buffer. */ protected Element first = null; /** The last element stored in this buffer. */ protected Element last = null; // -------------------------------------------------------------------------- // Services interfaces // -------------------------------------------------------------------------- /** * Component reference */ @Service Component weaveableC; /** * Logger of the component */ @DreamMonolog() protected Logger logger; // --------------------------------------------------------------------------- // Implementation of the AbstractBuffer methods. // --------------------------------------------------------------------------- /** * @see AbstractBuffer#doAdd(Message) */ protected void doAdd(Message message) { SequenceNumberChunk sequenceNumberChunk = messageManagerItf.getChunk(message, sortingChunkName); long sequenceNumber = sequenceNumberChunk.getSequenceNumber(); if (sequenceNumber <= lastInSequence) { // The message has already been stored or delivered. messageManagerItf.deleteMessage(message); return; } Element current = last; while (current != null && sequenceNumber < current.sequenceNumber) { current = current.previous; } if (current != null && sequenceNumber == current.sequenceNumber) { // The message is already stored in the buffer. messageManagerItf.deleteMessage(message); return; } Element element = new Element(); element.msg = message; element.sequenceNumber = sequenceNumber; if (current == null) { // insert at the beginning if (first != null) { // list not empty element.next = first; first.previous = element; } else { // list is empty, first = last last = element; } first = element; } else { // insert after current element.previous = current; if (current.next != null) { // new element is not the new last element.next = current.next; element.next.previous = element; } else { // insert at the end last = element; } element.previous.next = element; } // update last in sequence // logger.log(BasicLevel.INFO, "inserted element " + // element.sequenceNumber); current = element; int counter = 0; while (current != null && current.sequenceNumber == lastInSequence + 1) { counter++; lastInSequence++; current = current.next; } if (counter > 0) { incrementAvailableMessagesCount(counter); } incrementStoredMessagesCount(1); } /** * @see AbstractBuffer#doRemove() */ protected Message doRemove() { incrementAvailableMessagesCount(-1); incrementStoredMessagesCount(-1); Element newFirst = first.next; if (newFirst != null) { newFirst.previous = null; } else { last = null; } Message msg = first.msg; first = newFirst; return msg; } /** * @see AbstractBuffer#doGet() */ protected Message doGet() { return first.msg; } /** * @see AbstractBuffer#doRemoveAll() */ public Message doRemoveAll() { Message message = null; Element current = first; int i = 0; while (current != null) { if (message == null) { message = messageManagerItf.createMessage(); } messageManagerItf.addSubMessage(message, current.msg); first = current.next; current = first; i--; } incrementAvailableMessagesCount(i); incrementStoredMessagesCount(i); return message; } // --------------------------------------------------------------------------- // Overriding of the AttributeController // interface generated by fraclet // --------------------------------------------------------------------------- /** * Overriding of the AttributeController interface generated by fraclet. It * manages synchronization and check if the buffer is in an incoherent * state. */ public long getLastInSequence() { synchronized (lock) { if (storedMessagesCount > 0) { // At this time we do not allow this method to be called when // the buffer // is not empty. This could be done, but this requires scanning // the // buffer in order to remove messages with a sequence number // below // lastInSequence and in order to modify the value of // availableMessageIndicator. Error.bug(logger); } return lastInSequence; } } /** * Overriding of the AttributeController interface generated by fraclet. It * manages synchronization. */ public void setLastInSequence(long lastInSequence) { synchronized (lock) { this.lastInSequence = lastInSequence; } } /** * @see org.objectweb.dream.queue.buffer.AbstractBuffer#setMaxCapacity(int) */ public void setMaxCapacity(int maxCapacity) { super.setMaxCapacity(maxCapacity); } // --------------------------------------------------------------------------- // Inner class. // --------------------------------------------------------------------------- /** * This class represents elements of a linked list. Each element contains a * reference to its predecessor (previous), its successor ( * next), a message, and a sequence number. */ public static class Element implements Recyclable { Element previous; Element next; Message msg; long sequenceNumber; Reference recyclableReference; // --------------------------------------------------------------------------- // Implementation of the Recyclable interface. // --------------------------------------------------------------------------- /** * @see Recyclable#recycle() */ public void recycle() { previous = null; next = null; msg = null; sequenceNumber = -1; } /** * @see Recyclable#setReference(Reference) */ public void setReference(Reference recyclableReference) { this.recyclableReference = recyclableReference; } /** * @see Recyclable#getReference() */ public Reference getReference() { return recyclableReference; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy