package org.openedit.entermedia.cluster;
import java.util.ConcurrentModificationException;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.entermedia.locks.Lock;
import org.entermedia.locks.LockManager;
import org.openedit.Data;
import org.openedit.data.Searcher;
import org.openedit.data.SearcherManager;
import com.openedit.OpenEditException;
import com.openedit.hittracker.HitTracker;
import com.openedit.hittracker.SearchQuery;
public class ClusterLockManager implements LockManager
{
private static final Log log = LogFactory.getLog(ClusterLockManager.class);
protected SearcherManager fieldSearcherManager;
protected NodeManager fieldNodeManager;
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#lock(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public Lock lock(String inCatId, String inPath, String inOwnerId)
{
Searcher searcher = getLockSearcher(inCatId);
Lock lock = loadLock(inCatId, inPath);
int tries = 0;
while( !grabLock(inCatId, inOwnerId, lock))
{
tries++;
if( tries > 9)
{
throw new OpenEditException("Could not lock file " + inPath + " locked by " + lock.getNodeId() + " " + lock.getOwnerId() );
}
try
{
Thread.sleep(250);
}
catch( Exception ex)
{
//does not happen
log.info(ex);
}
log.info("Could not lock " + inPath + " trying again " + tries);
lock = loadLock(inCatId, inPath);
}
return lock;
}
public boolean grabLock(String inCatId, String inOwner, Lock lock)
{
if( lock == null)
{
throw new OpenEditException("Lock should not be null");
}
if( lock.isLocked())
{
return false;
}
//set owner
try
{
lock.setOwnerId(inOwner);
lock.setDate(new Date());
lock.setNodeId(getNodeManager().getLocalNodeId());
lock.setLocked(true);
getLockSearcher(inCatId).saveData(lock, null);
}
catch( ConcurrentModificationException ex)
{
return false;
}
catch( OpenEditException ex)
{
if( ex.getCause() instanceof ConcurrentModificationException)
{
return false;
}
throw ex;
}
return true;
}
protected Lock createLock(String inPath, Searcher searcher)
{
Lock lockrequest = (Lock)searcher.createNewData();
lockrequest.setPath(inPath);
lockrequest.setLocked(false);
return lockrequest;
}
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#loadLock(java.lang.String, java.lang.String)
*/
@Override
public Lock loadLock(String inCatId, String inPath)
{
Searcher searcher = getLockSearcher(inCatId);
SearchQuery q = searcher.createSearchQuery();
q.addExact("path",inPath);
//q.addSortBy("date");
HitTracker tracker = searcher.search(q);
Data first = (Data)tracker.first();
if( first == null)
{
Lock lock = createLock(inPath, searcher);
searcher.saveData(lock, null);
return lock;
}
first = (Data)searcher.searchById(first.getId());
Lock lock = new Lock();
lock.setId(first.getId());
lock.getProperties().putAll(first.getProperties());
return lock;
}
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#getLocksByDate(java.lang.String, java.lang.String)
*/
@Override
public HitTracker getLocksByDate(String inCatId, String inPath)
{
Searcher searcher = getLockSearcher(inCatId);
SearchQuery q = searcher.createSearchQuery();
q.addExact("path", inPath);
q.addSortBy("date");
return searcher.search(q);
}
public Searcher getLockSearcher(String inCatalogId)
{
Searcher searcher = getSearcherManager().getSearcher(inCatalogId, "lock");
return searcher;
}
public boolean isOwner(String inCatId, Lock lock)
{
if( lock == null)
{
throw new OpenEditException("Lock should not be null");
}
if( lock.getId() == null)
{
throw new OpenEditException("lock id is currently null");
}
Lock owner = loadLock(inCatId, lock.getPath());
if( owner == null)
{
throw new OpenEditException("Owner lock is currently null");
}
if( lock.getOwnerId() == null)
{
return false;
}
boolean sameowner = lock.getOwnerId().equals(owner.getOwnerId());
return sameowner;
}
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#lockIfPossible(java.lang.String, java.lang.String, java.lang.String)
*/
@Override
public Lock lockIfPossible(String inCatId, String inPath, String inOwnerId)
{
Lock lock = loadLock(inCatId, inPath);
if( lock.isLocked() )
{
return null;
}
if( grabLock(inCatId, inOwnerId, lock) )
{
return lock;
}
return null;
}
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#release(java.lang.String, org.entermedia.locks.Lock)
*/
@Override
public boolean release(String inCatId, Lock inLock)
{
if( inLock != null)
{
Searcher searcher = getLockSearcher(inCatId);
inLock.setLocked(false);
inLock.setProperty("version", (String)null);
searcher.saveData(inLock, null);
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.entermedia.locks.LockManagerI#releaseAll(java.lang.String, java.lang.String)
*/
@Override
public void releaseAll(String inCatalogId, String inPath)
{
Lock existing = loadLock(inCatalogId, inPath);
release(inCatalogId, existing);
}
public SearcherManager getSearcherManager()
{
return fieldSearcherManager;
}
public void setSearcherManager(SearcherManager inSearcherManager)
{
fieldSearcherManager = inSearcherManager;
}
public NodeManager getNodeManager()
{
return fieldNodeManager;
}
public void setNodeManager(NodeManager inNodeManager)
{
fieldNodeManager = inNodeManager;
}
}