* <li>Restore system to standard operation.</li>
* </ol>
*/
protected void optimizeFile()
{
ElapsedTimer timer = new ElapsedTimer();
timesOptimized++;
if ( log.isInfoEnabled() )
{
log.info( logCacheName + "Beginning Optimization #" + timesOptimized );
}
// CREATE SNAPSHOT
IndexedDiskElementDescriptor[] defragList = null;
try
{
storageLock.writeLock().acquire();
queueInput = true;
// shut off recycle while we're optimizing,
doRecycle = false;
defragList = createPositionSortedDescriptorList();
// Release iff I aquired.
storageLock.writeLock().release();
}
catch ( InterruptedException e )
{
log.error( logCacheName + "Error setting up optimization.", e );
return;
}
// Defrag the file outside of the write lock. This allows a move to be made,
// and yet have the element still accessible for reading or writing.
long expectedNextPos = defragFile( defragList, 0 );
// ADD THE QUEUED ITEMS to the end and then truncate
try
{
storageLock.writeLock().acquire();
if ( !queuedPutList.isEmpty() )
{
// This is perhaps unecessary, but the list might not be as sorted as we think.
defragList = new IndexedDiskElementDescriptor[queuedPutList.size()];
queuedPutList.toArray( defragList );
Arrays.sort( defragList, new PositionComparator() );
// pack them at the end
expectedNextPos = defragFile( defragList, expectedNextPos );
}
// TRUNCATE THE FILE
dataFile.truncate( expectedNextPos );
}
catch ( Exception e )
{
log.error( logCacheName + "Error optimizing queued puts.", e );
}
finally
{
// RESTORE NORMAL OPERATION
removeCount = 0;
bytesFree = 0;
initRecycleBin();
queuedPutList.clear();
queueInput = false;
// turn recycle back on.
doRecycle = true;
isOptimizing = false;
storageLock.writeLock().release();
}
if ( log.isInfoEnabled() )
{
log.info( logCacheName + "Finished #" + timesOptimized + " Optimization took "
+ timer.getElapsedTimeString() );
}
}