summaryrefslogtreecommitdiff
path: root/src/mongo/client/distlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/client/distlock.cpp')
-rw-r--r--src/mongo/client/distlock.cpp50
1 files changed, 48 insertions, 2 deletions
diff --git a/src/mongo/client/distlock.cpp b/src/mongo/client/distlock.cpp
index d1fff0c1124..8b932e73b3a 100644
--- a/src/mongo/client/distlock.cpp
+++ b/src/mongo/client/distlock.cpp
@@ -492,12 +492,58 @@ namespace mongo {
return true;
}
+
+ bool DistributedLock::isLockHeld( double timeout, string* errMsg ) {
+ scoped_ptr<ScopedDbConnection> connPtr(
+ ScopedDbConnection::getInternalScopedDbConnection( _conn.toString(), timeout ) );
+ ScopedDbConnection& conn = *connPtr;
+
+ BSONObj lockObj;
+ try {
+ lockObj = conn->findOne( LocksType::ConfigNS,
+ BSON( LocksType::name(_name) ) ).getOwned();
+ }
+ catch ( DBException& e ) {
+ *errMsg = str::stream() << "error checking whether lock " << _name << " is held "
+ << causedBy( e );
+ return false;
+ }
+ conn.done();
+
+ if ( lockObj.isEmpty() ) {
+ *errMsg = str::stream() << "no lock for " << _name << " exists in the locks collection";
+ return false;
+ }
+
+ if ( lockObj[LocksType::state()].numberInt() < 2 ) {
+ *errMsg = str::stream() << "lock " << _name << " current state is not held ("
+ << lockObj[LocksType::state()].numberInt() << ")";
+ return false;
+ }
+
+ if ( lockObj[LocksType::process()].String() != _processId ) {
+ *errMsg = str::stream() << "lock " << _name << " is currently being held by "
+ << "another process ("
+ << lockObj[LocksType::process()].String() << ")";
+ return false;
+ }
+
+ if ( distLockPinger.willUnlockOID( lockObj[LocksType::lockID()].OID() ) ) {
+ *errMsg = str::stream() << "lock " << _name << " is not held and is currently being "
+ << "scheduled for lazy unlock by "
+ << lockObj[LocksType::lockID()].OID();
+ return false;
+ }
+
+ return true;
+ }
+
// Semantics of this method are basically that if the lock cannot be acquired, returns false, can be retried.
// If the lock should not be tried again (some unexpected error) a LockException is thrown.
// If we are only trying to re-enter a currently held lock, reenter should be true.
// Note: reenter doesn't actually make this lock re-entrant in the normal sense, since it can still only
// be unlocked once, instead it is used to verify that the lock is already held.
- bool DistributedLock::lock_try( const string& why , bool reenter, BSONObj * other ) {
+ bool DistributedLock::lock_try( const string& why , bool reenter, BSONObj * other, double timeout ) {
// TODO: Start pinging only when we actually get the lock?
// If we don't have a thread pinger, make sure we shouldn't have one
@@ -520,7 +566,7 @@ namespace mongo {
other = &dummyOther;
scoped_ptr<ScopedDbConnection> connPtr(
- ScopedDbConnection::getInternalScopedDbConnection( _conn.toString() ) );
+ ScopedDbConnection::getInternalScopedDbConnection( _conn.toString(), timeout ) );
ScopedDbConnection& conn = *connPtr;
BSONObjBuilder queryBuilder;