summaryrefslogtreecommitdiff
path: root/src/mongo/db/s/dist_lock_manager.h
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2020-12-04 08:13:42 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-01-03 11:56:04 +0000
commit5431150d116b70fc9401c46deaacc9ae049f064e (patch)
treed1784b3cb2355cee9401e539f4574f0172995d8d /src/mongo/db/s/dist_lock_manager.h
parent98a7731d21a8746e584f7092aadbee60a5fad6ef (diff)
downloadmongo-5431150d116b70fc9401c46deaacc9ae049f064e.tar.gz
SERVER-53227 Move the DistLockManager to only be available on MongoD
Diffstat (limited to 'src/mongo/db/s/dist_lock_manager.h')
-rw-r--r--src/mongo/db/s/dist_lock_manager.h189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/mongo/db/s/dist_lock_manager.h b/src/mongo/db/s/dist_lock_manager.h
new file mode 100644
index 00000000000..61da53109b1
--- /dev/null
+++ b/src/mongo/db/s/dist_lock_manager.h
@@ -0,0 +1,189 @@
+/**
+ * Copyright (C) 2018-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/base/string_data.h"
+#include "mongo/bson/oid.h"
+#include "mongo/db/service_context.h"
+#include "mongo/stdx/chrono.h"
+
+namespace mongo {
+
+using DistLockHandle = OID;
+
+/**
+ * Interface for handling distributed locks.
+ *
+ * Usage:
+ *
+ * auto scopedDistLock = mgr->lock(...);
+ *
+ * if (!scopedDistLock.isOK()) {
+ * // Did not get lock. scopedLockStatus destructor will not call unlock.
+ * }
+ *
+ * // To check if lock is still owned:
+ * auto status = scopedDistLock.getValue().checkStatus();
+ *
+ * if (!status.isOK()) {
+ * // Someone took over the lock! Unlock will still be called at destructor, but will
+ * // practically be a no-op since it doesn't own the lock anymore.
+ * }
+ */
+class DistLockManager {
+public:
+ // Default timeout which will be used if one is not passed to the lock method.
+ static const Seconds kDefaultLockTimeout;
+
+ // Timeout value, which specifies that if the lock is not available immediately, no attempt
+ // should be made to wait for it to become free.
+ static const Milliseconds kSingleLockAttemptTimeout;
+
+ /**
+ * RAII type for distributed lock. Not meant to be shared across multiple threads.
+ */
+ class ScopedDistLock {
+ ScopedDistLock(const ScopedDistLock&) = delete;
+ ScopedDistLock& operator=(const ScopedDistLock&) = delete;
+
+ public:
+ ScopedDistLock(OperationContext* opCtx,
+ DistLockHandle lockHandle,
+ DistLockManager* lockManager);
+ ~ScopedDistLock();
+
+ ScopedDistLock(ScopedDistLock&& other);
+ ScopedDistLock& operator=(ScopedDistLock&& other);
+
+ /**
+ * Checks whether the lock is still being held by querying the config server.
+ */
+ Status checkStatus();
+
+ private:
+ OperationContext* _opCtx;
+ DistLockHandle _lockID;
+ DistLockManager* _lockManager; // Not owned here.
+ };
+
+ virtual ~DistLockManager() = default;
+
+ /**
+ * Retrieves the DistLockManager singleton for the node.
+ */
+ static DistLockManager* get(OperationContext* opCtx);
+ static void create(ServiceContext* service, std::unique_ptr<DistLockManager> distLockManager);
+
+ /**
+ * Performs bootstrapping for the manager. Implementation do not need to guarantee
+ * thread safety so callers should employ proper synchronization when calling this method.
+ */
+ virtual void startUp() = 0;
+
+ /**
+ * Cleanup the manager's resources. Implementations do not need to guarantee thread safety
+ * so callers should employ proper synchronization when calling this method.
+ */
+ virtual void shutDown(OperationContext* opCtx) = 0;
+
+ /**
+ * Returns the process ID for this DistLockManager.
+ */
+ virtual std::string getProcessID() = 0;
+
+ /**
+ * Tries multiple times to lock, using the specified lock try interval, until
+ * a certain amount of time has passed or when any error that is not LockBusy
+ * occurred.
+ *
+ * waitFor = 0 indicates there should only be one attempt to acquire the lock, and
+ * no waiting.
+ * waitFor = -1 indicates we should retry indefinitely.
+ *
+ * Returns OK if the lock was successfully acquired.
+ * Returns ErrorCodes::DistributedClockSkewed when a clock skew is detected.
+ * Returns ErrorCodes::LockBusy if the lock is being held.
+ */
+ StatusWith<ScopedDistLock> lock(OperationContext* opCtx,
+ StringData name,
+ StringData whyMessage,
+ Milliseconds waitFor);
+
+ /**
+ * Same behavior as lock(...) above, except takes a specific lock session ID "lockSessionID"
+ * instead of randomly generating one internally.
+ *
+ * This is useful for a process running on the config primary after a failover. A lock can be
+ * immediately reacquired if "lockSessionID" matches that of the lock, rather than waiting for
+ * the inactive lock to expire.
+ */
+ virtual StatusWith<DistLockHandle> lockWithSessionID(OperationContext* opCtx,
+ StringData name,
+ StringData whyMessage,
+ const OID& lockSessionID,
+ Milliseconds waitFor) = 0;
+
+ /**
+ * Specialized locking method, which only succeeds if the specified lock name is not held by
+ * anyone. Uses local write concern and does not attempt to overtake the lock or check whether
+ * the lock lease has expired.
+ */
+ virtual StatusWith<DistLockHandle> tryLockWithLocalWriteConcern(OperationContext* opCtx,
+ StringData name,
+ StringData whyMessage,
+ const OID& lockSessionID) = 0;
+
+ /**
+ * Unlocks the given lockHandle. Will attempt to retry again later if the config
+ * server is not reachable.
+ */
+ virtual void unlock(OperationContext* opCtx, const DistLockHandle& lockHandle) = 0;
+
+ /**
+ * Unlocks the lock specified by "lockHandle" and "name". Will attempt to retry again later if
+ * the config server is not reachable.
+ */
+ virtual void unlock(OperationContext* opCtx,
+ const DistLockHandle& lockHandle,
+ StringData name) = 0;
+
+ /**
+ * Makes a best-effort attempt to unlock all locks owned by the given processID.
+ */
+ virtual void unlockAll(OperationContext* opCtx, const std::string& processID) = 0;
+
+private:
+ /**
+ * Checks if the lockHandle still exists in the config server.
+ */
+ virtual Status checkStatus(OperationContext* opCtx, const DistLockHandle& lockHandle) = 0;
+};
+
+} // namespace mongo