
org.objectweb.dream.queue.keyed.buffer.BufferAscendingKeyKeyChunkAddDoubleKeyedRemove 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.keyed.buffer;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import org.objectweb.dream.message.AbstractChunk;
import org.objectweb.dream.message.Message;
import org.objectweb.dream.message.MessageManagerType;
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.dream.dreamannotation.DreamComponent;
import org.objectweb.dream.dreamannotation.DreamMonolog;
import org.objectweb.fractal.fraclet.annotation.annotations.Requires;
import org.objectweb.util.monolog.api.Logger;
/**
* This buffer stores every incoming message according to
*
* - a key (
keyChunk
) that is contained in the message as a
* {@link AbstractChunk} which name can be specified as a Fractal component
* attribute using the
* {@link org.objectweb.dream.queue.keyed.buffer.BufferAttributeControllerKeyChunkAdd}
* interface. This method is used when adding the message using the
* {@link #add(Message, Object)} method.
* - a key (
key
) that is explicitely passed as a parameter,
* when adding the message using the {@link #add(Message, Object)} method.
*
* Messages can then be removed from the buffer using the
* {@link #remove(Object, Object)} method. This method returns the message with
* the highest key for the specified keyChunk
key.
*/
@DreamComponent(controllerDesc = "dreamUnstoppablePrimitive")
public class BufferAscendingKeyKeyChunkAddDoubleKeyedRemove
implements
KeyedBufferAdd,
DoubleKeyedBufferRemove,
BufferMonitoringKeyed
{
// ------------------------------------------------------------------------
// Client interfaces.
// ------------------------------------------------------------------------
/**
* Can be used by subclasses to create aggregated messages in {@link
* DoubleKeyedBufferRemove#removeAll()}.
*/
@Requires(name = "message-manager")
protected MessageManagerType messageManagerItf;
// --------------------------------------------------------------------------
// Services interfaces
// --------------------------------------------------------------------------
/**
* Component reference
*/
@Service
Component weaveableC;
/**
* Logger of the component
*/
@DreamMonolog()
protected Logger logger;
// ------------------------------------------------------------------------
// Attributes.
// ------------------------------------------------------------------------
/**
* The maximal capacity of the buffer.
*/
@Attribute(argument = "maxCapacity")
protected int maxCapacity = 0;
/**
* The count of stored messages into the buffer. This attribute should only be
* updated using the {@link #incrementStoredMessagesCount(int, Object)}
* method.
*/
protected int storedMessagesCount = 0;
@Attribute(argument = "keyChunkName")
protected String keyChunkName = "key-chunk";
// ------------------------------------------------------------------------
// Fields.
// ------------------------------------------------------------------------
/**
* Used to sort the messages according to the key stored in each message as a
* {@link AbstractChunk chunk}.
*/
protected Map> queue = new HashMap>();
/**
* The lock object.
*/
protected final Object lock = new Object();
// ------------------------------------------------------------------------
// Implementation of the KeyedBufferAdd method.
// ------------------------------------------------------------------------
/**
* @see KeyedBufferAdd#add(Message, Object)
*/
public void add(Message message, Object key) throws InterruptedException
{
synchronized (lock)
{
while (!canAdd(message))
{
lock.wait();
}
doAdd(message, key);
lock.notifyAll();
}
}
/**
* @see KeyedBufferAdd#tryAdd(Message, Object)
*/
public boolean tryAdd(Message message, Object key)
{
synchronized (lock)
{
if (canAdd(message))
{
doAdd(message, key);
lock.notifyAll();
return true;
}
return false;
}
}
// ------------------------------------------------------------------------
// Implementation of the DoubleKeyedBufferRemove method.
// ------------------------------------------------------------------------
/**
* @see DoubleKeyedBufferRemove#remove(Object, Object)
*/
public Message remove(Object key1, Object key2) throws InterruptedException
{
synchronized (lock)
{
Message message = null;
while (message == null)
{
message = doRemove(key1, key2);
if (message == null)
{
lock.wait();
}
}
return message;
}
}
/**
* @see DoubleKeyedBufferRemove#tryRemove(Object, Object)
*/
public Message tryRemove(Object key1, Object key2)
{
synchronized (lock)
{
Message message = doRemove(key1, key2);
return message;
}
}
/**
* @see DoubleKeyedBufferRemove#get(Object, Object)
*/
public Message get(Object key1, Object key2) throws InterruptedException
{
synchronized (lock)
{
Message message = null;
while (message == null)
{
message = doGet(key1, key2);
if (message == null)
{
lock.wait();
}
}
return message;
}
}
/**
* @see DoubleKeyedBufferRemove#tryGet(Object, Object)
*/
public Message tryGet(Object key1, Object key2)
{
synchronized (lock)
{
Message message = doGet(key1, key2);
return message;
}
}
/**
* @see DoubleKeyedBufferRemove#removeAll(Object)
*/
public Message removeAll(Object key)
{
throw new UnsupportedOperationException();
}
/**
* @see DoubleKeyedBufferRemove#removeAll()
*/
public Message removeAll()
{
throw new UnsupportedOperationException();
}
// ------------------------------------------------------------------------
// Methods that may be overridden by concrete sub classes.
// ------------------------------------------------------------------------
/**
* Checks whether the given message can be added into the buffer. The
* {@link #lock lock}has been acquired when this method is called.
*
* @param message the message to be tested.
* @return true
if the message can be added.
*/
protected boolean canAdd(Message message)
{
if (maxCapacity > 0 && (maxCapacity - storedMessagesCount <= 0))
{
return false;
}
return true;
}
// ------------------------------------------------------------------------
// Utility methods.
// ------------------------------------------------------------------------
@SuppressWarnings("unchecked")
protected void doAdd(Message message, Object key)
{
AbstractChunk keyChunk = messageManagerItf.getChunk(message, keyChunkName);
TreeMap
© 2015 - 2025 Weber Informatics LLC | Privacy Policy