Storage Engine API
lock_state.h
Go to the documentation of this file.
1 
29 #pragma once
30 
31 #include <queue>
32 
35 #include "mongo/db/operation_context.h"
36 #include "mongo/platform/atomic_word.h"
37 #include "mongo/util/concurrency/spin_lock.h"
38 
39 namespace mongo {
40 
47 
48 public:
50 
54  void clear();
55 
61  LockResult wait(Milliseconds timeout);
62 
70  LockResult wait(OperationContext* opCtx, Milliseconds timeout);
71 
72 private:
73  virtual void notify(ResourceId resId, LockResult result);
74 
75  // These two go together to implement the conditional variable pattern.
76  stdx::mutex _mutex;
77  stdx::condition_variable _cond;
78 
79  // Result from the last call to notify
81 };
82 
83 
95 template <bool IsForMMAPV1>
96 class LockerImpl : public Locker {
97 public:
102  LockerImpl();
103 
104  virtual ~LockerImpl();
105 
106  virtual ClientState getClientState() const;
107 
108  virtual LockerId getId() const {
109  return _id;
110  }
111 
112  stdx::thread::id getThreadId() const override;
113 
114  void updateThreadIdToCurrentThread() override;
115  void unsetThreadId() override;
116 
117  void setSharedLocksShouldTwoPhaseLock(bool sharedLocksShouldTwoPhaseLock) override {
118  _sharedLocksShouldTwoPhaseLock = sharedLocksShouldTwoPhaseLock;
119  }
120 
121  void setMaxLockTimeout(Milliseconds maxTimeout) override {
122  _maxLockTimeout = maxTimeout;
123  }
124 
125  bool hasMaxLockTimeout() override {
126  return static_cast<bool>(_maxLockTimeout);
127  }
128 
129  void unsetMaxLockTimeout() override {
130  _maxLockTimeout = boost::none;
131  }
132 
133  virtual LockResult lockGlobal(OperationContext* opCtx, LockMode mode);
135  return lockGlobal(nullptr, mode);
136  }
137  virtual LockResult lockGlobalBegin(OperationContext* opCtx, LockMode mode, Date_t deadline) {
138  return _lockGlobalBegin(opCtx, mode, deadline);
139  }
140  virtual LockResult lockGlobalBegin(LockMode mode, Date_t deadline) {
141  return _lockGlobalBegin(nullptr, mode, deadline);
142  }
143  virtual LockResult lockGlobalComplete(OperationContext* opCtx, Date_t deadline);
144  virtual LockResult lockGlobalComplete(Date_t deadline) {
145  return lockGlobalComplete(nullptr, deadline);
146  }
147  virtual void lockMMAPV1Flush();
148 
149  virtual void downgradeGlobalXtoSForMMAPV1();
150  virtual bool unlockGlobal();
151 
152  virtual void beginWriteUnitOfWork();
153  virtual void endWriteUnitOfWork();
154 
155  virtual bool inAWriteUnitOfWork() const {
156  return _wuowNestingLevel > 0;
157  }
158 
165  virtual LockResult lock(OperationContext* opCtx,
166  ResourceId resId,
167  LockMode mode,
168  Date_t deadline = Date_t::max(),
169  bool checkDeadlock = false);
170 
171  virtual LockResult lock(ResourceId resId,
172  LockMode mode,
173  Date_t deadline = Date_t::max(),
174  bool checkDeadlock = false) {
175  return lock(nullptr, resId, mode, deadline, checkDeadlock);
176  }
177 
178  virtual void downgrade(ResourceId resId, LockMode newMode);
179 
180  virtual bool unlock(ResourceId resId);
181 
182  virtual LockMode getLockMode(ResourceId resId) const;
183  virtual bool isLockHeldForMode(ResourceId resId, LockMode mode) const;
184  virtual bool isDbLockedForMode(StringData dbName, LockMode mode) const;
185  virtual bool isCollectionLockedForMode(StringData ns, LockMode mode) const;
186 
187  virtual ResourceId getWaitingResource() const;
188 
189  virtual void getLockerInfo(LockerInfo* lockerInfo) const;
190  virtual boost::optional<LockerInfo> getLockerInfo() const final;
191 
192  virtual bool saveLockStateAndUnlock(LockSnapshot* stateOut);
193 
194  virtual void restoreLockState(OperationContext* opCtx, const LockSnapshot& stateToRestore);
195  virtual void restoreLockState(const LockSnapshot& stateToRestore) {
196  restoreLockState(nullptr, stateToRestore);
197  }
198 
199  virtual void releaseTicket();
200  virtual void reacquireTicket(OperationContext* opCtx);
201 
227  LockResult lockBegin(OperationContext* opCtx, ResourceId resId, LockMode mode);
228 
241  LockResult lockComplete(OperationContext* opCtx,
242  ResourceId resId,
243  LockMode mode,
244  Date_t deadline,
245  bool checkDeadlock);
246 
247  LockResult lockComplete(ResourceId resId, LockMode mode, Date_t deadline, bool checkDeadlock) {
248  return lockComplete(nullptr, resId, mode, deadline, checkDeadlock);
249  }
250 
255  scoped_spinlock scopedLock(_lock);
256  return _requests;
257  }
258 
259 private:
261 
263 
267  LockResult _lockGlobalBegin(OperationContext* opCtx, LockMode, Date_t deadline);
268 
275 
282 
295  bool _shouldDelayUnlock(ResourceId resId, LockMode mode) const;
296 
300  void _releaseTicket();
301 
306  LockResult _acquireTicket(OperationContext* opCtx, LockMode mode, Date_t deadline);
307 
308  // Used to disambiguate different lockers
309  const LockerId _id;
310 
311  // The only reason we have this spin lock here is for the diagnostic tools, which could
312  // iterate through the LockRequestsMap on a separate thread and need it to be stable.
313  // Apart from that, all accesses to the LockerImpl are always from a single thread.
314  //
315  // This has to be locked inside const methods, hence the mutable.
316  mutable SpinLock _lock;
317  // Note: this data structure must always guarantee the continued validity of pointers/references
318  // to its contents (LockRequests). The LockManager maintains a LockRequestList of pointers to
319  // the LockRequests managed by this data structure.
321 
322  // Reuse the notification object across requests so we don't have to create a new mutex
323  // and condition variable every time.
325 
326  // Per-locker locking statistics. Reported in the slow-query log message and through
327  // db.currentOp. Complementary to the per-instance locking statistics.
329 
330  // Delays release of exclusive/intent-exclusive locked resources until the write unit of
331  // work completes. Value of 0 means we are not inside a write unit of work.
333 
334  // Mode for which the Locker acquired a ticket, or MODE_NONE if no ticket was acquired.
336 
337  // Indicates whether the client is active reader/writer or is queued.
338  AtomicWord<ClientState> _clientState{kInactive};
339 
340  // Track the thread who owns the lock for debugging purposes
341  stdx::thread::id _threadId;
342 
343  // If true, shared locks will participate in two-phase locking.
345 
346  // If this is set, dictates the max number of milliseconds that we will wait for lock
347  // acquisition. Effectively resets lock acquisition deadlines to time out sooner. If set to 0,
348  // for example, lock attempts will time out immediately if the lock is not immediately
349  // available.
350  boost::optional<Milliseconds> _maxLockTimeout;
351 
353  //
354  // Methods merged from LockState, which should eventually be removed or changed to methods
355  // on the LockerImpl interface.
356  //
357 
358 public:
359  virtual void dump() const;
360 
361  virtual bool isW() const;
362  virtual bool isR() const;
363 
364  virtual bool isLocked() const;
365  virtual bool isWriteLocked() const;
366  virtual bool isReadLocked() const;
367  bool isGlobalLockedRecursively() override;
368 
369  virtual bool hasLockPending() const {
370  return getWaitingResource().isValid();
371  }
372 };
373 
376 
377 
386 public:
389 
390 private:
392 };
393 
394 
418 public:
421 
426 
432  void release();
433 
434 private:
435  Locker* const _locker;
436  bool _released;
437 };
438 
439 
444 
445 } // namespace mongo
LockMode _modeForTicket
Definition: lock_state.h:335
virtual void notify(ResourceId resId, LockResult result)
This method is invoked at most once for each lock request and indicates the outcome of the lock acqui...
Definition: lock_state.cpp:236
virtual void downgrade(ResourceId resId, LockMode newMode)
Downgrades the specified resource's lock mode without changing the reference count.
Definition: lock_state.cpp:504
LockManager * getGlobalLockManager()
Retrieves the global lock manager instance.
Definition: lock_state.cpp:1096
Interface for acquiring locks.
Definition: locker.h:47
Entry point for the lock manager scheduling functionality.
Definition: lock_manager.h:53
virtual void downgradeGlobalXtoSForMMAPV1()
This is only necessary for the MMAP V1 engine and in particular, the fsyncLock command which needs to...
Definition: lock_state.cpp:401
Collection *const const NamespaceString & ns
Definition: collection_info_cache_impl.cpp:53
virtual bool unlock(ResourceId resId)
Releases a lock previously acquired through a lock call.
Definition: lock_state.cpp:510
Interface on which granted lock requests will be notified.
Definition: lock_manager_defs.h:289
~AutoAcquireFlushLockForMMAPV1Commit()
Definition: lock_state.cpp:1067
void _releaseTicket()
Releases the ticket for the Locker.
Definition: lock_state.cpp:942
Copyright (C) 2014 MongoDB Inc.
Definition: bson_collection_catalog_entry.cpp:38
virtual ResourceId getWaitingResource() const
Returns the resource that this locker is waiting/blocked on (if any).
Definition: lock_state.cpp:596
SingleThreadedLockStats _stats
Definition: lock_state.h:328
MMAPV1LockerImpl *const _locker
Definition: lock_state.h:391
FastMapNoAlloc< ResourceId, LockRequest > getRequestsForTest() const
This function is for unit testing only.
Definition: lock_state.h:254
uint64_t LockerId
Definition: lock_manager_defs.h:259
bool _released
Definition: lock_state.h:436
LockerImpl< true > MMAPV1LockerImpl
Definition: lock_state.h:375
void unsetMaxLockTimeout() override
Clears the max lock timeout override set by setMaxLockTimeout() above.
Definition: lock_state.h:129
virtual bool saveLockStateAndUnlock(LockSnapshot *stateOut)
Retrieves all locks held by this transaction, other than RESOURCE_MUTEX locks, and what mode they're ...
Definition: lock_state.cpp:647
virtual bool unlockGlobal()
Decrements the reference count on the global lock.
Definition: lock_state.cpp:424
void updateThreadIdToCurrentThread() override
Updates any cached thread id values to represent the current thread.
Definition: lock_state.cpp:270
SpinLock _lock
Definition: lock_state.h:316
const LockerId _id
Definition: lock_state.h:309
void unsetThreadId() override
Clears any cached thread id values.
Definition: lock_state.cpp:275
void setMaxLockTimeout(Milliseconds maxTimeout) override
This is useful to ensure that potential deadlocks do not occur.
Definition: lock_state.h:121
AutoYieldFlushLockForMMAPV1Commit(Locker *locker)
Definition: lock_state.cpp:1001
virtual bool isReadLocked() const
Definition: lock_state.cpp:185
virtual bool isLocked() const
Definition: lock_state.cpp:175
virtual void lockMMAPV1Flush()
This method is used only in the MMAP V1 storage engine, otherwise it is a no-op.
Definition: lock_state.cpp:385
LockMode _getModeForMMAPV1FlushLock() const
MMAP V1 locking code yields and re-acquires the flush lock occasionally in order to allow the flush t...
Definition: lock_state.cpp:974
bool isGlobalLockedRecursively() override
Definition: lock_state.cpp:992
LockResult lockComplete(ResourceId resId, LockMode mode, Date_t deadline, bool checkDeadlock)
Definition: lock_state.h:247
virtual void reacquireTicket(OperationContext *opCtx)
Reacquires a ticket for the Locker.
Definition: lock_state.cpp:320
virtual bool hasLockPending() const
Pending means we are currently trying to get a lock (could be the parallel batch writer lock).
Definition: lock_state.h:369
bool _unlockImpl(LockRequestsMap::Iterator *it)
The main functionality of the unlock method, except accepts iterator in order to avoid additional loo...
Definition: lock_state.cpp:951
FastMapNoAlloc< ResourceId, LockRequest > LockRequestsMap
Definition: lock_state.h:262
stdx::thread::id getThreadId() const override
Get a platform-specific thread identifier of the thread which owns the this locker for tracing purpos...
Definition: lock_state.cpp:265
Uniquely identifies a lockable resource.
Definition: lock_manager_defs.h:189
virtual void dump() const
Definition: lock_state.cpp:190
stdx::mutex _mutex
Definition: lock_state.h:76
This explains how the MMAP V1 durability system is implemented.
Definition: lock_state.h:417
virtual void beginWriteUnitOfWork()
beginWriteUnitOfWork/endWriteUnitOfWork are called at the start and end of WriteUnitOfWorks.
Definition: lock_state.cpp:447
Notfication callback, which stores the last notification result and signals a condition variable,...
Definition: lock_state.h:45
void setSharedLocksShouldTwoPhaseLock(bool sharedLocksShouldTwoPhaseLock) override
Indicate that shared locks should participate in two-phase locking for this Locker instance.
Definition: lock_state.h:117
virtual bool isDbLockedForMode(StringData dbName, LockMode mode) const
Definition: lock_state.cpp:547
virtual ~LockerImpl()
Definition: lock_state.cpp:280
void clear()
Clears the object so it can be reused.
Definition: lock_state.cpp:215
Locker *const _locker
Definition: lock_state.h:435
virtual bool isCollectionLockedForMode(StringData ns, LockMode mode) const
Definition: lock_state.cpp:560
LockResult _result
Definition: lock_state.h:80
virtual LockMode getLockMode(ResourceId resId) const
Retrieves the mode in which a lock is held or checks whether the lock held for a particular resource ...
Definition: lock_state.cpp:531
IndexSet::const_iterator it
Definition: ephemeral_for_test_btree_impl.cpp:458
CondVarLockGrantNotification _notify
Definition: lock_state.h:324
virtual void restoreLockState(OperationContext *opCtx, const LockSnapshot &stateToRestore)
Re-locks all locks whose state was stored in 'stateToRestore'.
Definition: lock_state.cpp:707
bool hasMaxLockTimeout() override
Returns whether this Locker has a maximum lock timeout set.
Definition: lock_state.h:125
LockResult
Return values for the locking functions of the lock manager.
Definition: lock_manager_defs.h:108
void release()
Allows the acquired flush lock to be prematurely released.
Definition: lock_state.cpp:1060
Interface for acquiring locks.
Definition: lock_state.h:96
LockMode
LockMode compatibility matrix.
Definition: lock_manager_defs.h:61
~AutoYieldFlushLockForMMAPV1Commit()
Definition: lock_state.cpp:1012
virtual LockResult lockGlobal(LockMode mode)
Definition: lock_state.h:134
LockRequestsMap _requests
Definition: lock_state.h:320
ClientState
State for reporting the number of active and queued reader and writer clients.
Definition: locker.h:79
LockResult wait(Milliseconds timeout)
Uninterruptible blocking method, which waits for the notification to fire.
Definition: lock_state.cpp:219
stdx::thread::id _threadId
Definition: lock_state.h:341
std::array< DefaultLockerImpl, kMaxPerfThreads > locker
Definition: d_concurrency_bm.cpp:66
virtual void endWriteUnitOfWork()
Definition: lock_state.cpp:456
bool _sharedLocksShouldTwoPhaseLock
Definition: lock_state.h:344
Definition: locker.h:79
virtual LockResult lock(OperationContext *opCtx, ResourceId resId, LockMode mode, Date_t deadline=Date_t::max(), bool checkDeadlock=false)
Requests a lock for resource 'resId' with mode 'mode'.
Definition: lock_state.cpp:487
virtual bool isWriteLocked() const
Definition: lock_state.cpp:180
LockResult lockBegin(OperationContext *opCtx, ResourceId resId, LockMode mode)
Allows for lock requests to be requested in a non-blocking way.
Definition: lock_state.cpp:734
stdx::condition_variable _cond
Definition: lock_state.h:77
CondVarLockGrantNotification()
Definition: lock_state.cpp:211
virtual boost::optional< LockerInfo > getLockerInfo() const final
Returns boost::none if this is an instance of LockerNoop, or a populated LockerInfo otherwise.
Definition: lock_state.cpp:640
bool _shouldDelayUnlock(ResourceId resId, LockMode mode) const
Whether we should use two phase locking.
Definition: lock_state.cpp:132
boost::optional< Milliseconds > _maxLockTimeout
Definition: lock_state.h:350
None.
Definition: lock_manager_defs.h:63
IteratorImpl< FastMapNoAlloc< ResourceId, LockRequest >, LockRequest, map_iterator > Iterator
Definition: fast_map_noalloc.h:196
virtual LockResult lockGlobalBegin(OperationContext *opCtx, LockMode mode, Date_t deadline)
Requests the global lock to be acquired in the specified mode.
Definition: lock_state.h:137
void upgradeFlushLockToExclusive()
We need the exclusive lock in order to do the shared view remap.
Definition: lock_state.cpp:1049
At global synchronization points, such as drop database we are running under a global exclusive lock ...
Definition: lock_state.h:385
MONGO_DISALLOW_COPYING(CondVarLockGrantNotification)
virtual bool isR() const
Definition: lock_state.cpp:170
virtual ClientState getClientState() const
Return whether client is holding any locks (active), or is queued on any locks or waiting for a ticke...
Definition: lock_state.cpp:294
virtual LockResult lockGlobal(OperationContext *opCtx, LockMode mode)
This should be the first method invoked for a particular Locker object.
Definition: lock_state.cpp:305
LockResult lockComplete(OperationContext *opCtx, ResourceId resId, LockMode mode, Date_t deadline, bool checkDeadlock)
Waits for the completion of a lock, previously requested through lockBegin or lockGlobalBegin.
Definition: lock_state.cpp:817
virtual bool inAWriteUnitOfWork() const
Definition: lock_state.h:155
LockResult _acquireTicket(OperationContext *opCtx, LockMode mode, Date_t deadline)
Acquires a ticket for the Locker under 'mode'.
Definition: lock_state.cpp:327
virtual LockResult lockGlobalComplete(OperationContext *opCtx, Date_t deadline)
Calling lockGlobalComplete without an OperationContext does not allow the lock acquisition to be inte...
Definition: lock_state.cpp:380
LockSnapshot captures the state of all resources that are locked, what modes they're locked in,...
Definition: locker.h:342
LockResult _lockGlobalBegin(OperationContext *opCtx, LockMode, Date_t deadline)
Like lockGlobalBegin, but accepts a deadline for acquiring a ticket.
Definition: lock_state.cpp:349
AtomicWord< ClientState > _clientState
Definition: lock_state.h:338
virtual LockResult lockGlobalComplete(Date_t deadline)
Definition: lock_state.h:144
virtual bool isLockHeldForMode(ResourceId resId, LockMode mode) const
Definition: lock_state.cpp:542
AutoAcquireFlushLockForMMAPV1Commit(Locker *locker)
Definition: lock_state.cpp:1020
Collection *const OperationContext *const opCtx
Definition: collection_impl.cpp:80
virtual LockResult lockGlobalBegin(LockMode mode, Date_t deadline)
Definition: lock_state.h:140
LockerImpl()
Instantiates new locker.
Definition: lock_state.cpp:261
int _wuowNestingLevel
Definition: lock_state.h:332
virtual LockResult lock(ResourceId resId, LockMode mode, Date_t deadline=Date_t::max(), bool checkDeadlock=false)
Calling lock without an OperationContext does not allow LOCK_WAITING states to be interrupted.
Definition: lock_state.h:171
LockerImpl< false > DefaultLockerImpl
Definition: lock_state.h:374
virtual LockerId getId() const
Definition: lock_state.h:108
bool isValid() const
Definition: lock_manager_defs.h:211
virtual void releaseTicket()
Releases the ticket associated with the Locker.
Definition: lock_state.cpp:936
virtual bool isW() const
Definition: lock_state.cpp:165