DocArchiveLockManager.java from BIRT at Krugle
Show DocArchiveLockManager.java syntax highlighted
/*******************************************************************************
* Copyright (c) 2004 Actuate Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Actuate Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.birt.core.archive;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
class DocArchiveLockManager
{
protected static Logger log = Logger.getLogger( DocArchiveLockManager.class
.getName( ) );
protected static DocArchiveLockManager instance;
public synchronized static DocArchiveLockManager getInstance( )
{
if ( instance == null )
{
instance = new DocArchiveLockManager( );
}
return instance;
}
protected DocArchiveLockManager( )
{
}
private class Lock
{
String name;
FileLock lock;
}
private class Channel
{
RandomAccessFile file;
FileChannel channel;
int refCount;
}
protected HashMap channels = new HashMap( );
protected synchronized FileChannel getChannel( String name )
throws IOException
{
Channel channel = (Channel) channels.get( name );
if ( channel == null )
{
channel = new Channel( );
channel.file = new RandomAccessFile( name, "rw" );
channel.channel = channel.file.getChannel( );
channels.put( name, channel );
}
channel.refCount++;
return channel.channel;
}
protected synchronized void releaseChannel( String name )
{
Channel channel = (Channel) channels.get( name );
if ( channel != null )
{
channel.refCount--;
if ( channel.refCount == 0 )
{
channels.remove( name );
try
{
channel.file.close( );
new File( name ).delete( );
}
catch ( IOException ex )
{
log.log( Level.FINE, "failed to close the file", ex );
}
}
}
}
/**
* try to lock the file. If some thread is locking this file, wait until it
* sucess.
*
* @param name
* file name.
* @return the lock object used to unlock.
* @throws IOException
*/
public Object lock( String name ) throws IOException
{
FileChannel channel = getChannel( name );
try
{
while ( true )
{
synchronized ( channel )
{
try
{
FileLock fLock = channel.lock( );
Lock lock = new Lock( );
lock.name = name;
lock.lock = fLock;
return lock;
}
catch ( OverlappingFileLockException ov )
{
// another thread has locked the file, so wait them
// release the lock and retry
try
{
channel.wait( );
}
catch ( InterruptedException ex )
{
}
}
}
}
}
catch ( IOException ex )
{
releaseChannel( name );
throw ex;
}
}
/**
* unlock the previous locked file.
*
* @param lockObj
* the object get from the lock.
*/
public void unlock( Object lockObj )
{
if ( lockObj instanceof Lock )
{
Lock lock = (Lock) lockObj;
FileLock fLock = lock.lock;
FileChannel channel = fLock.channel( );
try
{
fLock.release( );
}
catch ( Exception ex )
{
log.log( Level.FINE, "exception occus while release the lock",
ex );
}
// after unlock the file, notify the waiting threads
synchronized ( channel )
{
channel.notify( );
}
releaseChannel( lock.name );
}
}
}
See more files for this project here