summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeert Bosch <geert@mongodb.com>2016-12-26 21:42:22 -0500
committerGeert Bosch <geert@mongodb.com>2016-12-27 09:44:18 -0500
commitc4e1e4bbcc1a6fc1f9ca4e3cbf524e6c9c99ce1a (patch)
tree77e01675dd32900725747abec53027913cf68fea
parent67257272a057635640318842ea05b28e8499f71a (diff)
downloadmongo-c4e1e4bbcc1a6fc1f9ca4e3cbf524e6c9c99ce1a.tar.gz
Revert "SERVER-26126 Remove broken LockState caching"
-rw-r--r--src/mongo/db/concurrency/lock_state.cpp19
-rw-r--r--src/mongo/db/concurrency/lock_state.h2
-rw-r--r--src/mongo/db/concurrency/locker.h7
-rw-r--r--src/mongo/db/concurrency/locker_noop.h4
-rw-r--r--src/mongo/db/operation_context_impl.cpp23
-rw-r--r--src/mongo/db/operation_context_impl.h2
6 files changed, 49 insertions, 8 deletions
diff --git a/src/mongo/db/concurrency/lock_state.cpp b/src/mongo/db/concurrency/lock_state.cpp
index 9235f56bbb4..898f9cd462e 100644
--- a/src/mongo/db/concurrency/lock_state.cpp
+++ b/src/mongo/db/concurrency/lock_state.cpp
@@ -191,6 +191,17 @@ bool LockerImpl<IsForMMAPV1>::isReadLocked() const {
}
template <bool IsForMMAPV1>
+void LockerImpl<IsForMMAPV1>::assertEmptyAndReset() {
+ invariant(!inAWriteUnitOfWork());
+ invariant(_resourcesToUnlockAtEndOfUnitOfWork.empty());
+ invariant(_requests.empty());
+ invariant(_modeForTicket == MODE_NONE);
+
+ // Reset the locking statistics so the object can be reused
+ _stats.reset();
+}
+
+template <bool IsForMMAPV1>
void LockerImpl<IsForMMAPV1>::dump() const {
StringBuilder ss;
ss << "Locker id " << _id << " status: ";
@@ -272,13 +283,7 @@ LockerImpl<IsForMMAPV1>::~LockerImpl() {
// Cannot delete the Locker while there are still outstanding requests, because the
// LockManager may attempt to access deleted memory. Besides it is probably incorrect
// to delete with unaccounted locks anyways.
- invariant(!inAWriteUnitOfWork());
- invariant(_resourcesToUnlockAtEndOfUnitOfWork.empty());
- invariant(_requests.empty());
- invariant(_modeForTicket == MODE_NONE);
-
- // Reset the locking statistics so the object can be reused
- _stats.reset();
+ assertEmptyAndReset();
}
template <bool IsForMMAPV1>
diff --git a/src/mongo/db/concurrency/lock_state.h b/src/mongo/db/concurrency/lock_state.h
index e4bdded0bdf..79f348d4ac6 100644
--- a/src/mongo/db/concurrency/lock_state.h
+++ b/src/mongo/db/concurrency/lock_state.h
@@ -244,6 +244,8 @@ public:
virtual bool isWriteLocked() const;
virtual bool isReadLocked() const;
+ virtual void assertEmptyAndReset();
+
virtual bool hasLockPending() const {
return getWaitingResource().isValid();
}
diff --git a/src/mongo/db/concurrency/locker.h b/src/mongo/db/concurrency/locker.h
index 6dacd299e65..e00882a498d 100644
--- a/src/mongo/db/concurrency/locker.h
+++ b/src/mongo/db/concurrency/locker.h
@@ -309,6 +309,13 @@ public:
virtual bool isReadLocked() const = 0;
/**
+ * Asserts that the Locker is effectively not in use and resets the locking statistics.
+ * This means, there should be no locks on it, no WUOW, etc, so it would be safe to call
+ * the destructor or reuse the Locker.
+ */
+ virtual void assertEmptyAndReset() = 0;
+
+ /**
* Pending means we are currently trying to get a lock (could be the parallel batch writer
* lock).
*/
diff --git a/src/mongo/db/concurrency/locker_noop.h b/src/mongo/db/concurrency/locker_noop.h
index ff252243964..24450ceeecc 100644
--- a/src/mongo/db/concurrency/locker_noop.h
+++ b/src/mongo/db/concurrency/locker_noop.h
@@ -160,6 +160,10 @@ public:
invariant(false);
}
+ virtual void assertEmptyAndReset() {
+ invariant(false);
+ }
+
virtual bool hasLockPending() const {
invariant(false);
}
diff --git a/src/mongo/db/operation_context_impl.cpp b/src/mongo/db/operation_context_impl.cpp
index 0ccdbbbfbef..7fae6cfa4a7 100644
--- a/src/mongo/db/operation_context_impl.cpp
+++ b/src/mongo/db/operation_context_impl.cpp
@@ -47,17 +47,38 @@ std::unique_ptr<Locker> newLocker() {
return stdx::make_unique<MMAPV1LockerImpl>();
return stdx::make_unique<DefaultLockerImpl>();
}
+
+class ClientOperationInfo {
+public:
+ std::unique_ptr<Locker>& locker() {
+ if (!_locker) {
+ _locker = newLocker();
+ }
+ return _locker;
+ }
+
+private:
+ std::unique_ptr<Locker> _locker;
+};
+
+const auto clientOperationInfoDecoration = Client::declareDecoration<ClientOperationInfo>();
+
} // namespace
using std::string;
OperationContextImpl::OperationContextImpl(Client* client, unsigned opId)
: OperationContext(client, opId) {
- setLockState(newLocker());
+ setLockState(std::move(clientOperationInfoDecoration(client).locker()));
StorageEngine* storageEngine = getServiceContext()->getGlobalStorageEngine();
setRecoveryUnit(storageEngine->newRecoveryUnit(), kNotInUnitOfWork);
}
+OperationContextImpl::~OperationContextImpl() {
+ lockState()->assertEmptyAndReset();
+ clientOperationInfoDecoration(getClient()).locker() = releaseLockState();
+}
+
ProgressMeter* OperationContextImpl::setMessage_inlock(const char* msg,
const std::string& name,
unsigned long long progressMeterTotal,
diff --git a/src/mongo/db/operation_context_impl.h b/src/mongo/db/operation_context_impl.h
index bc23dcbb089..c6069f01e8b 100644
--- a/src/mongo/db/operation_context_impl.h
+++ b/src/mongo/db/operation_context_impl.h
@@ -35,6 +35,8 @@ namespace mongo {
class OperationContextImpl final : public OperationContext {
public:
+ virtual ~OperationContextImpl();
+
virtual ProgressMeter* setMessage_inlock(const char* msg,
const std::string& name,
unsigned long long progressMeterTotal,