org.rhq.enterprise.communications.command.client
Class PersistentFifo

java.lang.Object
  extended by org.rhq.enterprise.communications.command.client.PersistentFifo

public class PersistentFifo
extends Object

Persists byte arrays in a FIFO queue file. The file will grow to a limited, maximum size. If more entries are put on the queue and those new entries cause the file to grow beyond the maximum file size, the file will be compressed and, quite possibly, older entries will get deleted to shrink the file back down under a configured percentage of used space.

This queue is implemented as a linked list with each entry in the file sequentially written (that is, the linked list is actually a chain link running from start to end of the file - the next linked entry is always the next entry in the file). Each list entry consists of a next pointer (a long) followed by a byte array that contains the entry's true data. The next pointer is actually relative to the entry - meaning the next pointer is really the size of the entry in bytes not including the size of the next pointer itself. If you know the file position of the next pointer and the next pointer value itself, add the two together along with the size of the next pointer itself (a long which is 8-bytes usually) and you get the file position of the next entry. We do it this way in order to make the purging more efficient - since all the next pointers are relative to the actual position of the file (and we know all entries are written sequentially in the file), we don't have to update the next pointers if we shift all entries down in the file en masse.

The first long in the file is the count of elements in the FIFO - this allows you to know the number of entries in the FIFO without walking all the links to count along the way. The second long in the file is the head pointer. The third long in the file is the tail pointer. If the head pointer is -1, the FIFO queue is considered empty. If it is 0 or larger, it is the file pointer position within the file where the first entry starts. When entries are put on the queue, they are added to the tail. When entries are taken from the queue, they are removed from head.

 count | HEAD | TAIL | next | entry-byte-array-data | next | entry-byte-array-data | next | entry | EOF
          |      |     ^  |                           ^  |                           ^ ^
          |      |     |  |                           |  |                           | |
          |      |     |  +---------------------------+  +---------------------------+ |
          |      +-----|---------------------------------------------------------------+
          +------------+
 

Author:
John Mazzitelli

Constructor Summary
PersistentFifo(File file, long max_size_bytes, int purge_percentage, boolean compress)
          Creates a new PersistentFifo object.
 
Method Summary
 long count()
          Returns the number of entries currently in the FIFO.
static void dumpContents(PrintWriter out, File fifo_file, boolean compressed, int raw_byte_base)
          A simple utility that dumps all the data found in the persistent FIFO to the given stream.
 void initializeEmptyFile()
          This initializes the file to indicate that the queue is empty - call this when the file does not yet exist or if you want to shrink the file down to its minimal size.
 boolean isEmpty()
          Returns true if the file does not contain any entries in the queue.
static void main(String[] args)
          A simple utility that dumps all the data found in the persistent FIFO to stdout.
 void put(byte[] bytes)
          Puts an array of bytes on the FIFO queue
 void putObject(Serializable o)
          Puts the given Object in the FIFO queue.
 byte[] take()
          Takes the next entry from the queue and returns it.
 Object takeObject()
          Takes an object from the FIFO, deserializes it and returns it.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

PersistentFifo

public PersistentFifo(File file,
                      long max_size_bytes,
                      int purge_percentage,
                      boolean compress)
               throws IOException
Creates a new PersistentFifo object. The max_size_bytes indicates the maximum size this file is allowed to grow before a purge is triggered. If this threshold is crossed (that is, if the file grows larger than the maximum size allowed), the file is compressed and, if needed, the oldest entries in the queue will get deleted to make room for new entries. The amount of space purged will be enough to lower the used space percentage down to purge_percentage or less.

Parameters:
file - the file containing the FIFO data
max_size_bytes - the maximum size, in bytes, the persistent file is allowed to grow before a purge is triggered
purge_percentage - when a purge is triggered, it will free up enough space to lower the amount of used space down to this percentage of the total max space
compress - if true, the data spooled to the file should be compressed
Throws:
IOException - if the file does not exist but cannot be created
IllegalArgumentException - if purge_percentage is not between 0 and 99 or max_size_bytes is less than 1000
Method Detail

main

public static void main(String[] args)
                 throws IOException
A simple utility that dumps all the data found in the persistent FIFO to stdout.

Parameters:
args - "filename [objects|bytes [compressed]]"
Throws:
IOException

dumpContents

public static void dumpContents(PrintWriter out,
                                File fifo_file,
                                boolean compressed,
                                int raw_byte_base)
                         throws IOException
A simple utility that dumps all the data found in the persistent FIFO to the given stream. If the raw_byte_base is -1, then only the number of entries is dumped - each individual entry is not. If the raw_byte_base is 0, then the data in the file is assumed to be serialized objects and thus their toString() is dumped. Otherwise, a dump of each entry's raw byte array is retrieved in the given raw_byte_base, where a base of 10 is for decimal, 16 is for hexidecimal, etc.

Parameters:
out - the stream to dump the output
fifo_file - the FIFO file that contains 0 or more persisted entries
compressed - if true, the entries will be assumed to be compressed in the file
raw_byte_base - if greater than 0, the raw entry data (i.e. the actual bytes) is dumped in this base (where base=16 for hexidecimal for example; see DumpBytes for the various BASE constants: DumpBytes.BASE_HEX, et. al.). 0 means dump entries as objects, -1 means do not dump any entry data
Throws:
IOException

putObject

public void putObject(Serializable o)
               throws IOException,
                      RuntimeException
Puts the given Object in the FIFO queue. This method will attempt to serialize the object and store the serialized bytes via put(byte[]). An exception will occur if the serialization fails.

Parameters:
o - the object to serialize and put in the FIFO queue
Throws:
IOException - if failed to put the data in the file
RuntimeException - if failed to serialize the data

takeObject

public Object takeObject()
                  throws IOException,
                         RuntimeException
Takes an object from the FIFO, deserializes it and returns it.

Returns:
the object that was taken from the FIFO and deserialized
Throws:
IOException - if failed to access the file
RuntimeException - if failed to deserialize the object after taking its serialized bytes off the FIFO queue

put

public void put(byte[] bytes)
         throws IOException
Puts an array of bytes on the FIFO queue

Parameters:
bytes - the data to put in the queue
Throws:
IOException - if failed to access the file

take

public byte[] take()
            throws IOException
Takes the next entry from the queue and returns it.

Returns:
the next entry from the queue, or null if the queue is empty
Throws:
IOException

isEmpty

public boolean isEmpty()
                throws IOException
Returns true if the file does not contain any entries in the queue.

Returns:
true if the queue is empty, false if at least one entry can be taken from the queue.
Throws:
IOException - if failed to access the file

count

public long count()
           throws IOException
Returns the number of entries currently in the FIFO.

Returns:
the number of entries
Throws:
IOException - if failed to access the file

initializeEmptyFile

public void initializeEmptyFile()
                         throws IOException
This initializes the file to indicate that the queue is empty - call this when the file does not yet exist or if you want to shrink the file down to its minimal size.

Throws:
IOException


Copyright © 2008-2012 Red Hat, Inc.. All Rights Reserved.