rapture.lock.mongodb.MongoLockHandler2 Maven / Gradle / Ivy
/**
* The MIT License (MIT)
*
* Copyright (c) 2011-2016 Incapture Technologies LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package rapture.lock.mongodb;
import java.util.Map;
import org.apache.log4j.Logger;
import org.bson.Document;
import com.mongodb.MongoServerException;
import com.mongodb.WriteConcern;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.result.DeleteResult;
import rapture.common.LockHandle;
import rapture.common.exception.ExceptionToString;
import rapture.lock.ILockingHandler;
import rapture.mongodb.MongoDBFactory;
/**
*
*/
public class MongoLockHandler2 implements ILockingHandler {
private static Logger log = Logger.getLogger(MongoLockHandler2.class);
private static final String tableName = "raplock2_";
private String instanceName = "default";
@Override
public void setInstanceName(String instanceName) {
this.instanceName = instanceName;
}
@Override
public LockHandle acquireLock(String lockHolder, String lockName, long secondsToWait, long secondsToHold) {
log.debug("Mongo acquire lock2 " + lockName + ":" + secondsToHold + ":" + secondsToWait);
long start = System.currentTimeMillis();
MongoCollection coll = getLockCollection(lockName);
log.debug("lock COLLECTION for " + lockName + "IS " + coll.getNamespace().getFullName());
long bailTime = System.currentTimeMillis() + secondsToWait * 1000;
long leaseTime = System.currentTimeMillis() + secondsToHold * 1000;
Document lockFile = new Document();
lockFile.put("lockName", lockName);
lockFile.put("lockHolder", lockHolder);
lockFile.put("lease", leaseTime);
long myLockID = System.currentTimeMillis();
lockFile.put("_id", "" + myLockID);
log.debug("id is " + myLockID);
log.debug("bailtime " + bailTime);
while (bailTime > System.currentTimeMillis()) {
try {
myLockID = System.currentTimeMillis();
lockFile.put("_id", "" + myLockID);
lockFile.put("lease", myLockID + secondsToHold * 1000);
coll.withWriteConcern(WriteConcern.ACKNOWLEDGED).insertOne(lockFile);
log.debug("inserted file" + lockFile);
break;
} catch (MongoServerException e) {
log.error(ExceptionToString.format(e));
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
// loop until we acquire lock or timeout
while (bailTime > System.currentTimeMillis()) {
// we have the lock if no lock file exists with a smaller number
FindIterable results = coll.find(new Document("lease", new Document("$gt", System.currentTimeMillis()))).sort(new Document("_id", 1))
.limit(1);
Document lock = results.first();
if (lock != null && ((String) lock.get("_id")).equals("" + myLockID)) {
log.debug("* i have the lock" + lock.get("_id") + ":" + myLockID);
LockHandle lockHandle = new LockHandle();
lockHandle.setLockName(lockName);
lockHandle.setHandle("" + myLockID);
lockHandle.setLockHolder(lockHolder);
long end = System.currentTimeMillis();
log.debug("* NG acquired lock in " + (end - start));
return lockHandle;
} else {
// log.info("* waiting for lock held by "+ lock.get("_id"));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// ran out of time trying to get lock.
log.debug("giving up " + myLockID);
long end2 = System.currentTimeMillis();
log.debug("denied lock in " + (end2 - start));
return null;
}
@Override
public Boolean releaseLock(String lockHolder, String lockName, LockHandle lockHandle) {
return releaseLock(lockHandle);
}
protected MongoCollection getLockCollection(String lockName) {
// log.info("COLLECTION is " + tableName + lockName);
return MongoDBFactory.getCollection(instanceName, tableName + lockName);
}
public Boolean releaseLock(LockHandle lockHandle) {
log.debug("Mongo release lock");
if (lockHandle != null) {
String id = lockHandle.getHandle();
String lockName = lockHandle.getLockName();
return releaseLockWithID(lockName, id);
} else {
log.error("Unable to release lock %s, because null lockHandle passed in.");
return false;
}
}
private Boolean releaseLockWithID(String lockName, String id) {
Document lockFileQuery = new Document();
lockFileQuery.put("_id", id);
MongoCollection coll = getLockCollection(lockName);
DeleteResult res = coll.deleteOne(lockFileQuery);
return (res.getDeletedCount() == 1);
}
@Override
public Boolean forceReleaseLock(String lockName) {
MongoCollection coll = getLockCollection(lockName);
if (coll != null) {
coll.drop();
}
return true;
}
@Override
public void setConfig(Map config) {
}
public LockHandle getLockForName(String lockName) {
// a lock is the document with the smallest id number whose lease hasn't
// expired.
FindIterable results = getLockCollection(lockName).find(new Document("lease", new Document("$gt", System.currentTimeMillis())))
.sort(new Document("_id", 1)).limit(1);
Document lock = results.first();
if (lock != null) {
LockHandle lockHandle = new LockHandle();
lockHandle.setLockName((String) lock.get("lockName"));
lockHandle.setHandle((String) lock.get("_id"));
lockHandle.setLockHolder((String) lock.get("lockHolder"));
return lockHandle;
} else {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy