Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    *  jDTAUS - DTAUS fileformat.
    *  Copyright (c) 2005 Christian Schulte <cs@schulte.it>
    *
    *  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.1 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   */
  package org.jdtaus.core.io.util;
  
  import java.util.Locale;
  import java.util.Map;
  import java.util.TreeMap;
  import  org.jdtaus.core.container.ContainerFactory;
  import  org.jdtaus.core.container.ContextFactory;
  import  org.jdtaus.core.container.ContextInitializer;
  import  org.jdtaus.core.container.Implementation;
  import  org.jdtaus.core.container.ModelFactory;
  import  org.jdtaus.core.container.Properties;
  import  org.jdtaus.core.container.Property;
  import  org.jdtaus.core.container.PropertyException;
  import  org.jdtaus.core.io.FileOperations;
  import  org.jdtaus.core.lang.spi.MemoryManager;
  import  org.jdtaus.core.logging.spi.Logger;

Coalescing FileOperations cache.

This implementation implements a coalescing cache for FileOperations implementations. The cache is controlled by configuration property blockSize. By default property blockSize is initialized to 2097152 leading to a cache size of 10 MB (multiplied by property cacheSize which defaults to 5). All memory is allocated during instantiation so that an OutOfMemoryError may be thrown when constructing the cache but not when working with the instance.

Note:
This implementation is not thread-safe and concurrent changes to the underlying FileOperations implementation are not supported.

Author(s):
Christian Schulte
Version:
$Id: CoalescingFileOperations.java 4521 2007-12-25 21:36:55Z schulte2005 $
  
  public final class CoalescingFileOperations implements FlushableFileOperations
  {
      //--Implementation----------------------------------------------------------
  
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausImplementation
      // This section is managed by jdtaus-container-mojo.
  
    
Meta-data describing the implementation.
  
      private static final Implementation META =
          ModelFactory.getModel().getModules().
          getImplementation(CoalescingFileOperations.class.getName());
  // </editor-fold>//GEN-END:jdtausImplementation
  
      //----------------------------------------------------------Implementation--
      //--Constructors------------------------------------------------------------
  
  // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausConstructors
      // This section is managed by jdtaus-container-mojo.
  
    
Initializes the properties of the instance.

Parameters:
meta the property values to initialize the instance with.
Throws:
NullPointerException if meta is null.
  
      private void initializeProperties(final Properties meta)
      {
          Property p;
  
          if(meta == null)
          {
              throw new NullPointerException("meta");
          }
  
          p = meta.getProperty("cacheSize");
          this. = ((java.lang.Integerp.getValue()).intValue();
  
  
          p = meta.getProperty("blockSize");
          this. = ((java.lang.Integerp.getValue()).intValue();
 
     }
 // </editor-fold>//GEN-END:jdtausConstructors
 
     //------------------------------------------------------------Constructors--
     //--Dependencies------------------------------------------------------------
 
 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausDependencies
     // This section is managed by jdtaus-container-mojo.
 
    
Configured Logger implementation.
 
     private transient Logger _dependency1;

    
Gets the configured Logger implementation.

Returns:
the configured Logger implementation.
 
     private Logger getLogger()
     {
         Logger ret = null;
         if(this. != null)
         {
             ret = this.;
         }
         else
         {
             ret = (Logger) ContainerFactory.getContainer().
                 getDependency(CoalescingFileOperations.class,
                 "Logger");
 
             if(ModelFactory.getModel().getModules().
                 getImplementation(CoalescingFileOperations.class.getName()).
                 getDependencies().getDependency("Logger").
                 isBound())
             {
                 this. = ret;
             }
         }
 
         if(ret instanceof ContextInitializer && !((ContextInitializer) ret).
             isInitialized(ContextFactory.getContext()))
         {
             ((ContextInitializer) ret).initialize(ContextFactory.getContext());
         }
 
         return ret;
     }
    
Configured MemoryManager implementation.
 
     private transient MemoryManager _dependency0;

    
Gets the configured MemoryManager implementation.

Returns:
the configured MemoryManager implementation.
 
     private MemoryManager getMemoryManager()
     {
         MemoryManager ret = null;
         if(this. != null)
         {
             ret = this.;
         }
         else
         {
             ret = (MemoryManager) ContainerFactory.getContainer().
                 getDependency(CoalescingFileOperations.class,
                 "MemoryManager");
 
             if(ModelFactory.getModel().getModules().
                 getImplementation(CoalescingFileOperations.class.getName()).
                 getDependencies().getDependency("MemoryManager").
                 isBound())
             {
                 this. = ret;
             }
         }
 
         if(ret instanceof ContextInitializer && !((ContextInitializer) ret).
             isInitialized(ContextFactory.getContext()))
         {
             ((ContextInitializer) ret).initialize(ContextFactory.getContext());
         }
 
         return ret;
     }
 // </editor-fold>//GEN-END:jdtausDependencies
 
     //------------------------------------------------------------Dependencies--
     //--Properties--------------------------------------------------------------
 
 // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:jdtausProperties
     // This section is managed by jdtaus-container-mojo.
 
    
Property cacheSize.

Serial:
 
     private int _cacheSize;

    
Gets the value of property cacheSize.

Returns:
the value of property cacheSize.
 
     private int getCacheSize()
     {
         return this.;
     }

    
Property blockSize.

Serial:
 
     private int _blockSize;

    
Gets the value of property blockSize.

Returns:
the value of property blockSize.
 
     public int getBlockSize()
     {
         return this.;
     }
 
 // </editor-fold>//GEN-END:jdtausProperties
 
     //--------------------------------------------------------------Properties--
     //--FileOperations----------------------------------------------------------
 
     public long getLength() throws IOException
     {
         this.assertNotClosed();
 
         return this..getLength();
     }
 
     public void setLength(final long newLengththrows IOException
     {
         this.assertNotClosed();
 
         // Update the length of any cache nodes involved in the operation.
         final long oldLength = this.getLength();
         if(newLength > oldLength)
         {
             final long delta = newLength - oldLength;
 
             assert delta <= . :
                 "Unexpected implementation limit reached.";
 
             final Node[] nodes =
                 this.getCacheNodesForLength(oldLength, (intdelta);
 
             for(int i = 0; i < nodes.lengthi++)
             {
                 final long startPos = nodes[i]. * this.getBlockSize();
                 final long blockDelta = newLength - startPos;
 
                 assert blockDelta <= . :
                     "Unexpected implementation limit reached.";
 
                 nodes[i]. = blockDelta >= this.getBlockSize() ?
                     this.getBlockSize() : (intblockDelta;
 
             }
         }
         else if(newLength < oldLength)
         {
             final long delta = oldLength - newLength;
 
             assert delta <= . :
                 "Unexpected implementation limit reached.";
 
             final Node[] nodes =
                 this.getCacheNodesForLength(newLength, (intdelta);
 
             for(int i = 0; i < nodes.lengthi++)
             {
                 final long startPos = nodes[i]. * this.getBlockSize();
                 if(startPos > newLength)
                 { // Discard the block.
                     this..remove(new Long(nodes[i].));
                 }
                 else
                 { // Update the blocks length.
                     final long blockDelta = newLength - startPos;
 
                     assert blockDelta <= . :
                         "Unexpected implementation limit reached.";
 
                     nodes[i]. = blockDelta >= this.getBlockSize() ?
                         this.getBlockSize() : (intblockDelta;
 
                 }
             }
         }
 
         this..setLength(newLength);
 
         if(this. > newLength)
         {
             this. = newLength;
         }
     }
 
     public long getFilePointer() throws IOException
     {
         this.assertNotClosed();
 
         return this.;
     }
 
     public void setFilePointer(final long posthrows IOException
     {
         this.assertNotClosed();
 
         this. = pos;
     }
 
     public int read(final byte[] bufint offint lenthrows IOException
     {
         if(buf == null)
         {
             throw new NullPointerException("buf");
         }
         if(off < 0)
         {
             throw new IndexOutOfBoundsException(Integer.toString(off));
         }
         if(len < 0)
         {
             throw new IndexOutOfBoundsException(Integer.toString(len));
         }
         if(off + len > buf.length)
         {
             throw new IndexOutOfBoundsException(Integer.toString(off + len));
         }
 
         this.assertNotClosed();
 
         int read = FileOperations.EOF;
 
         if(len == 0)
         {
             read = 0;
         }
         else if(this. < this.getLength())
         { // End of file not reached.
             final Node[] nodes =
                 this.getCacheNodesForLength(this.len);
 
             // Ensure cache holds the data of the involved blocks.
             this.fillCache(nodes);
 
             int copied = 0;
             for(int i = 0; i < nodes.lengthi++)
             {
                 if(nodes[i]. == FileOperations.EOF)
                 { // Skip any end of file nodes.
                     continue;
                 }
 
                 if(nodes[i]. != .)
                 { // Node is associated with cache memory; cache is used.
 
                     // Use the current file pointer as the starting index.
                     final long delta = nodes[i]. + (this. -
                         nodes[i]. * this.getBlockSize());
 
                     assert delta <= . :
                         "Unexpected implementation limit reached.";
 
                     final int blockOffset = (intdelta;
                     final int blockDelta = nodes[i]. -
                         (blockOffset - nodes[i].);
 
                     final int copyLength = len >  blockDelta ? blockDelta : len;
                     System.arraycopy(this.blockOffsetbufoff,
                         copyLength);
 
                     off += copyLength;
                     len -= copyLength;
                     copied += copyLength;
                     this. += copyLength;
                 }
                 else
                 { // Node is not associated with cache memory; read directly.
                     this..setFilePointer(this.);
                     copied += this..read(bufofflen);
                     this. += len;
 
                     this.getLogger().debug(CoalescingFileOperationsBundle.
                         getReadBypassesCacheMessage(Locale.getDefault()).
                         format(new Object[] { new Integer(this.getBlockSize()),
                         new Integer(this.getCacheSize()), new Integer(len) }));
 
                     break;
                 }
             }
 
             read = copied;
         }
 
         return read;
     }
 
     public void write(final byte[] bufint offint lenthrows IOException
     {
         if(buf == null)
         {
             throw new NullPointerException("buf");
         }
         if(off < 0)
         {
             throw new IndexOutOfBoundsException(Integer.toString(off));
         }
         if(len < 0)
         {
             throw new IndexOutOfBoundsException(Integer.toString(len));
         }
         if(off + len > buf.length)
         {
             throw new IndexOutOfBoundsException(Integer.toString(off + len));
         }
 
         this.assertNotClosed();
 
         if(this. + len > this.getLength())
         { // Expand the file of the backing instance.
             this.setLength(this. + len);
         }
 
         final Node[] nodes =
             this.getCacheNodesForLength(this.len);
 
         // Ensure cache holds the data of the involved blocks.
         this.fillCache(nodes);
 
         for(int i = 0; i < nodes.lengthi++)
         {
             // Check for correct file length update.
             assert nodes[i]. != FileOperations.EOF :
                 "Unexpected cache state.";
 
             if(nodes[i]. != .)
             { // Node is associated with cache memory; cache is used.
 
                 // Use the current file pointer as the starting index.
                 final long delta = nodes[i]. + (this. -
                     nodes[i]. * this.getBlockSize());
 
                 assert delta <= . :
                     "Unexpected implementation limit reached.";
 
                 final int blockOffset = (intdelta;
                 final int blockDelta = nodes[i]. -
                     (blockOffset - nodes[i].);
 
                 final int copyLength = len > blockDelta ? blockDelta : len;
                 System.arraycopy(bufoffthis.blockOffsetcopyLength);
                 off += copyLength;
                 len -= copyLength;
                 this. += copyLength;
                 nodes[i]. = true;
             }
             else
             { // Node is not associated with cache memory; write out directly.
                 this..setFilePointer(this.);
                 this..write(bufofflen);
                 this. += len;
 
                 this.getLogger().debug(CoalescingFileOperationsBundle.
                     getWriteBypassesCacheMessage(Locale.getDefault()).
                     format(new Object[] { new Integer(this.getBlockSize()),
                     new Integer(this.getCacheSize()), new Integer(len) }));
 
                 break;
             }
         }
     }
 
     public void read(final OutputStream outthrows IOException
     {
         this.assertNotClosed();
 
         this..read(out);
         this. = this..getFilePointer();
     }
 
     public void write(final InputStream inthrows IOException
     {
         this.assertNotClosed();
 
         this..write(in);
         this. = this..getFilePointer();
     }

    
Flushes the cache and closes the FileOperations implementation backing the instance.

Throws:
IOException if flushing or closing the FileOperations implementation backing the instance fails, or if the instance already is closed.
 
     public void close() throws IOException
     {
         this.assertNotClosed();
 
         this.flush();
         this.getFileOperations().close();
         this. = true;
     }
 
     //----------------------------------------------------------FileOperations--
     //--FlushableFileOperations-------------------------------------------------
 
    
This method calls the flush() method of an underlying FlushableFileOperations implementation, if any.

Throws:
IOException if writing any pending changes fails or if the instance is closed.
 
     public void flush() throws IOException
     {
         this.assertNotClosed();
 
         this.defragmentCache();
 
         long startPos = FileOperations.EOF;
         int startIndex = FileOperations.EOF;
         int length = FileOperations.EOF;
         Node previous = null;
         boolean dirty = false;
 
         for(Iterator it = this..entrySet().iterator(); it.hasNext();)
         {
             final Map.Entry entry = (Map.Entryit.next();
             final long block = ((Longentry.getKey()).longValue();
             final Node current = (Nodeentry.getValue();
 
             // Skip any end of file nodes and nodes not associated with memory.
             if(current.length == FileOperations.EOF ||
                 current.cacheIndex == .)
             {
                 continue;
             }
 
             assert current.block == block : "Unexpected cache state.";
 
             if(previous == null)
             { // Start the first chunk.
                 previous = current;
                 startPos = current.block * this.getBlockSize();
                 startIndex = current.cacheIndex;
                 length = current.length;
                 dirty = current.dirty;
             }
             else if(current.block == previous.block + 1L)
             { // Expand the current chunk.
 
                 assert current.cacheIndex == previous.cacheIndex +
                     this.getBlockSize() : "Unexpected cache state.";
 
                 previous = current;
                 length += current.length;
                 if(!dirty)
                 {
                     dirty = current.dirty;
                 }
             }
             else
             { // Write out the current chunk and start a new one.
                 if(dirty)
                 {
                     this..setFilePointer(startPos);
                     this..write(
                         this.startIndexlength);
 
                 }
 
                 previous = current;
                 startPos = current.block * this.getBlockSize();
                 startIndex = current.cacheIndex;
                 length = current.length;
                 dirty = current.dirty;
             }
         }
 
         if(dirty)
         { // Write the remaining chunk.
             this..setFilePointer(startPos);
             this..write(
                 this.startIndexlength);
 
         }
 
         // Reset cache state.
         for(Iterator it = this..entrySet().iterator(); it.hasNext();)
         {
             final Map.Entry entry = (Map.Entryit.next();
             final Node current = (Nodeentry.getValue();
 
             current.cacheIndex = .;
             current.dirty = false;
         }
 
         this. = 0;
 
         if(this. instanceof FlushableFileOperations)
         { // Cache of the backing instance also needs to get flushed.
             ((FlushableFileOperationsthis.).flush();
         }
     }
 
     //-------------------------------------------------FlushableFileOperations--
     //--CoalescingFileOperations------------------------------------------------
 
    
Node describing a cache block.
 
     private static final class Node
     {
         private static final int NO_CACHEINDEX = .;
 
         long block;
         int cacheIndex = ;
         int length;
         boolean dirty;
     }

    
The FileOperations backing the instance.
 
     private final FileOperations fileOperations;

    
Cached blocks.
 
     private final byte[] cache;

    
Second cache memory used during defragmentation.
 
     private final byte[] defragCache;

    
Index of the next free cached block.
 
     private int nextCacheIndex;

    
Maps blocks to corresponding Nodes.
 
     private final Map root = new TreeMap();

    
File pointer.
 
     private long filePointer;

    
Caches the value returned by method getFilePointerBlock.
 
     private long cachedFilePointerBlock = ;
     private long cachedFilePointerBlockStart = FileOperations.EOF;
     private static final long NO_FILEPOINTERBLOCK = .;

    
Flags the instance as beeing closed.
 
     private boolean closed;

    
Creates a new CoalescingFileOperations instance taking the FileOperations backing the instance.

Parameters:
fileOperations the FileOperations backing the instance.
Throws:
NullPointerException if fileOperations is null.
IOException if reading fails.
 
     public CoalescingFileOperations(final FileOperations fileOperations)
     throws IOException
     {
         super();
 
         if(fileOperations == null)
         {
             throw new NullPointerException("fileOperations");
         }
 
         this.initializeProperties(.getProperties());
         this.assertValidProperties();
 
         this. = fileOperations;
 
         // Pre-allocate the cache memory.
         this. = this.getMemoryManager().allocateBytes(
             this.getBlockSize() * this.getCacheSize());
 
         this. = this.getMemoryManager().allocateBytes(
             this.getBlockSize() * this.getCacheSize());
 
         this. = fileOperations.getFilePointer();
     }

    
Creates a new CoalescingFileOperations instance taking the FileOperations backing the instance and the number of bytes occupied by one cache block.

Parameters:
fileOperations the FileOperations backing the instance.
blockSize the number of bytes occupied by one cache block.
Throws:
NullPointerException if fileOperations is null.
PropertyException if blockSize is negative or zero.
IOException if reading fails.
 
     public CoalescingFileOperations(final FileOperations fileOperations,
         final int blockSizethrows IOException
     {
         super();
 
         if(fileOperations == null)
         {
             throw new NullPointerException("fileOperations");
         }
 
         this.initializeProperties(.getProperties());
         this. = blockSize;
         this.assertValidProperties();
 
         this. = fileOperations;
 
         // Pre-allocate the cache memory.
         this. = this.getMemoryManager().allocateBytes(
             this.getBlockSize() * this.getCacheSize());
 
         this. = this.getMemoryManager().allocateBytes(
             this.getBlockSize() * this.getCacheSize());
 
         this. = fileOperations.getFilePointer();
     }

    
Gets the FileOperations implementation operations are performed with.

Returns:
the FileOperations implementation operations are performed with.
 
     public FileOperations getFileOperations()
     {
         return this.;
     }

    
Checks configured properties.

Throws:
PropertyException for illegal property values.
 
     private void assertValidProperties()
     {
         if(this.getBlockSize() <= 0)
         {
             throw new PropertyException("blockSize",
                 Integer.toString(this.getBlockSize()));
 
         }
         if(this.getCacheSize() <= 0)
         {
             throw new PropertyException("cacheSize",
                 Integer.toString(this.getCacheSize()));
 
         }
     }

    
Checks that the instance is not closed.

Throws:
IOException if the instance is closed.
 
     private void assertNotClosed() throws IOException
     {
         if(this.)
         {
             throw new IOException(CoalescingFileOperationsBundle.
                 getAlreadyClosedText(Locale.getDefault()));
 
         }
     }

    
Gets the block pointed to by a given file pointer value.

Parameters:
filePointer the file pointer value for which to return the corresponding block.
Returns:
the block pointed to by filePointer.
 
     private long getFilePointerBlock(final long filePointer)
     {
         if(this. == )
         {
             this. = (filePointer / this.getBlockSize()) -
                 ((filePointer % this.getBlockSize()) / this.getBlockSize());
 
             this. =
                 this. * this.getBlockSize();
 
         }
         else
         {
             if(!(filePointer >= this. &&
                 filePointer <= this. +
                 this.getBlockSize()))
             {
                 this. =
                     (filePointer / this.getBlockSize()) -
                     ((filePointer % this.getBlockSize()) / this.getBlockSize());
 
                 this. =
                     this. * this.getBlockSize();
 
             }
         }
 
         return this.;
     }

    
Gets the cache nodes for all blocks involved in a read or write operation of a given length for a given file pointer value.

Parameters:
filePointer the file pointer value to use for computing the number of involved blocks for a read or write operation of length.
length the length of the operation to perform.
Returns:
an array of cache nodes for all blocks involved in the operation in the order corresponding to the operation's needs.
 
     private Node[] getCacheNodesForLength(final long filePointer,
         final int length)
     {
         final long startingBlock = this.getFilePointerBlock(filePointer);
         final long endingBlock = this.getFilePointerBlock(filePointer + length);
 
         assert endingBlock - startingBlock <= . :
             "Unexpected implementation limit reached.";
 
         final Node[] nodes = new Node[(int) (endingBlock - startingBlock + 1L)];
 
         if(startingBlock == endingBlock)
         {
             nodes[0] = this.getCacheNode(startingBlock);
         }
         else
         {
             int i;
             long block;
 
             for(block = startingBlocki = 0; block <= endingBlock;
             block++, i++)
             {
                 nodes[i] = this.getCacheNode(block);
             }
         }
 
         return nodes;
     }

    
Fills the cache for a given set of cache nodes.

This method ensures that each given node gets associated with corresponding cache memory possibly flushing the cache before reading.

Parameters:
nodes the nodes to fill the cache for.
Throws:
NullPointerException if nodes is null.
IOException if reading fails.
 
     private void fillCache(final Node[] nodesthrows IOException
     {
         if(nodes == null)
         {
             throw new NullPointerException("nodes");
         }
 
         // Calculate the amount of bytes needed to be available in the cache
         // and flush the cache if nodes would not fit.
         long neededBytes = 0L;
         for(int i = nodes.length - 1; i >= 0; i--)
         {
             if(nodes[i]. == .)
             { // Node's block needs to be read.
                 neededBytes += this.getBlockSize();
             }
         }
 
         if(this. + neededBytes > this..length)
         { // Cache cannot hold the needed blocks so needs flushing.
             this.flush();
         }
 
         // Associate each node with cache memory for nodes not already
         // associated with cache memory and fill these nodes' cache memory.
         for(int i = nodes.length - 1; i >= 0; i--)
         {
             if(nodes[i]. == . &&
                 this. < this..length)
             { // Node is not associated with any cache memory and can be read.
 
                 // Update the length field of the node for the block checking
                 // for a possible end of file condition.
                 long pos = nodes[i]. * this.getBlockSize();
                 if(pos > this.getLength())
                 { // Node is behind the end of the file.
                     nodes[i]. = FileOperations.EOF;
                     continue;
                 }
                 else if(pos + this.getBlockSize() > this.getLength())
                 {
                     final long delta = this.getLength() - pos;
 
                     assert delta <= . :
                         "Unexpected implementation limit reached.";
 
                     nodes[i]. = (intdelta;
                 }
                 else
                 {
                     nodes[i]. = this.getBlockSize();
                 }
 
                 // Associated the node with cache memory.
                 nodes[i]. = this.;
                 this. += this.getBlockSize();
 
                 // Read the node's block into cache.
                 int read = FileOperations.EOF;
                 int totalRead = 0;
                 int toRead = nodes[i].;
                 this..setFilePointer(pos);
 
                 do
                 {
                     read = this..read(this.,
                         nodes[i]. + totalReadtoRead);
 
                     assert read != FileOperations.EOF :
                         "Unexpected end of file.";
 
                     totalRead += read;
                     toRead -= read;
 
                 } while(totalRead < nodes[i].);
             }
         }
     }

    
Defragments the cache.
 
     private void defragmentCache()
     {
         int defragIndex = 0;
 
         // Step through the cached blocks and defragment the cache.
         for(Iterator it = this..entrySet().iterator(); it.hasNext();)
         {
             final Map.Entry entry = (Map.Entryit.next();
             final long block = ((Longentry.getKey()).longValue();
             final Node current = (Nodeentry.getValue();
 
             // Skip any end of file nodes and nodes not associated with memory.
             if(current.length == FileOperations.EOF ||
                 current.cacheIndex == .)
             {
                 continue;
             }
 
             assert current.block == block : "Unexpected cache state.";
 
             System.arraycopy(this.current.cacheIndexthis.,
                 defragIndexthis.getBlockSize());
 
             current.cacheIndex = defragIndex;
             defragIndex += this.getBlockSize();
         }
 
         System.arraycopy(this., 0, this., 0, this..length);
     }

    
Gets the cache node for a given block.

Parameters:
block the block to return the corresponding cache node for.
Returns:
the cache node for block.
 
     private Node getCacheNode(final long block)
     {
         final Long key = new Long(block);
         Node node = (Nodethis..get(key);
         if(node == null)
         {
             node = new Node();
             node.block = block;
             this..put(keynode);
         }
 
         return node;
     }

    
Gets the cache node for a given cache index.

Parameters:
cacheIndex the index where the node's data is kept in the cache.
Returns:
the cache node for cacheIndex.
    private Node getCacheNode(final int cacheIndex)
    {
        Node node = null;
        for(Iterator it = this..entrySet().iterator(); it.hasNext();)
        {
            final Map.Entry entry = (Map.Entryit.next();
            if(((Nodeentry.getValue()). == cacheIndex)
            {
                node = (Nodeentry.getValue();
                break;
            }
        }
        return node;
    }
    //------------------------------------------------CoalescingFileOperations--
New to GrepCode? Check out our FAQ X