package org.entermedia.locks; import java.util.Collection; import java.util.ConcurrentModificationException; import java.util.Date; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openedit.util.DateStorageUtil; import com.openedit.OpenEditException; public class MemoryLockManager implements LockManager { private static final Log log = LogFactory.getLog(MemoryLockManager.class); protected Map<String,Lock> fieldLocks; protected long fieldLockId = 0; protected String fieldCatalogId; public String getCatalogId() { return fieldCatalogId; } public void setCatalogId(String inCatalogId) { fieldCatalogId = inCatalogId; } protected Map<String,Lock> getLocks() { if (fieldLocks == null) { fieldLocks = new ConcurrentHashMap<String,Lock>(); } return fieldLocks; } public Lock lock(String inPath, String inOwnerId) { Lock lock = loadLock(inPath); int tries = 0; while( !grabLock( inOwnerId, lock)) { tries++; if( tries > 20) { throw new OpenEditException("Could not lock file " + inPath + " locked by " + lock.getNodeId() + " " + lock.getOwnerId() ); } try { Thread.sleep(500); } catch( Exception ex) { //does not happen log.info(ex); } log.info("Could not lock " + inPath + " trying again " + tries + " locked by " + lock.getNodeId() + " " + lock.getOwnerId() ); lock = loadLock(inPath); } return lock; } public boolean isOwner(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(lock.getSourcePath()); 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; } protected long nextId() { return fieldLockId++; } @Override public Lock loadLock(String inPath) { Lock lock = getLocks().get(inPath); if( lock == null) { synchronized (getLocks()) { lock = getLocks().get(inPath); if( lock == null) { lock = addLock(inPath, null); getLocks().put(inPath,lock); } } } return lock; } @Override public Collection getLocksByDate(String inPath) { throw new OpenEditException("Not implemented"); } @Override public boolean release(Lock inLock) { if( inLock == null) { return true; } inLock.setLocked(false); return true; } @Override public void releaseAll(String inPath) { getLocks().clear(); } protected Lock addLock(String inPath, String inOwnerId) { Lock lockrequest = new Lock(); lockrequest.setId(String.valueOf( nextId() ) ); lockrequest.setSourcePath(inPath); lockrequest.setOwnerId(inOwnerId); lockrequest.setDate(new Date()); lockrequest.setNodeId("inmemory"); lockrequest.setProperty("date", DateStorageUtil.getStorageUtil().formatForStorage(new Date())); return lockrequest; } public boolean grabLock(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.setLocked(true); saveLock(lock); } catch( ConcurrentModificationException ex) { return false; } return true; } /** * Tries once then gives up and returns null */ public Lock lockIfPossible(String inPath, String inOwnerId) { Lock lock = loadLock(inPath); if( grabLock(inOwnerId, lock) ) { return lock; } return null; } private void saveLock(Lock inLock) { //TODO: Throw error if someone else saved this lock } }