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 
274  bool _unlockImpl(LockRequestsMap::Iterator* it);
275 
281  LockMode _getModeForMMAPV1FlushLock() const;
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.
320  LockRequestsMap _requests;
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.
335  LockMode _modeForTicket = MODE_NONE;
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.
344  bool _sharedLocksShouldTwoPhaseLock = false;
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:
391  MMAPV1LockerImpl* const _locker;
392 };
393 
394 
418 public:
421 
425  void upgradeFlushLockToExclusive();
426 
432  void release();
433 
434 private:
435  Locker* const _locker;
436  bool _released;
437 };
438 
439 
444 
445 } // namespace mongo
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
LockManager * getGlobalLockManager()
Retrieves the global lock manager instance.
Definition: lock_state.cpp:1088
Interface for acquiring locks.
Definition: locker.h:47
Entry point for the lock manager scheduling functionality.
Definition: lock_manager.h:53
Collection *const const NamespaceString & ns
Definition: collection_info_cache_impl.cpp:53
Interface on which granted lock requests will be notified.
Definition: lock_manager_defs.h:276
Copyright (C) 2014 MongoDB Inc.
Definition: bson_collection_catalog_entry.cpp:38
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:246
bool _released
Definition: lock_state.h:436
LockerImpl< true > MMAPV1LockerImpl
Definition: lock_state.h:375
Returns information and locking statistics for this instance of the locker.
Definition: locker.h:319
void unsetMaxLockTimeout() override
Clears the max lock timeout override set by setMaxLockTimeout() above.
Definition: lock_state.h:129
SpinLock _lock
Definition: lock_state.h:316
const LockerId _id
Definition: lock_state.h:309
void setMaxLockTimeout(Milliseconds maxTimeout) override
This is useful to ensure that potential deadlocks do not occur.
Definition: lock_state.h:121
LockResult lockComplete(ResourceId resId, LockMode mode, Date_t deadline, bool checkDeadlock)
Definition: lock_state.h:247
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
FastMapNoAlloc< ResourceId, LockRequest > LockRequestsMap
Definition: lock_state.h:262
Uniquely identifies a lockable resource.
Definition: lock_manager_defs.h:176
stdx::mutex _mutex
Definition: lock_state.h:76
This explains how the MMAP V1 durability system is implemented.
Definition: lock_state.h:417
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
void clear()
Clears the object so it can be reused.
Definition: lock_state.cpp:215
Locker *const _locker
Definition: lock_state.h:435
LockResult _result
Definition: lock_state.h:80
IndexSet::const_iterator it
Definition: ephemeral_for_test_btree_impl.cpp:458
CondVarLockGrantNotification _notify
Definition: lock_state.h:324
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:99
Interface for acquiring locks.
Definition: lock_state.h:96
LockMode
Lock modes.
Definition: lock_manager_defs.h:59
RecordId _id
Definition: wiredtiger_index.cpp:1132
virtual LockResult lockGlobal(LockMode mode)
Definition: lock_state.h:134
LockRequestsMap _requests
Definition: lock_state.h:320
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 restoreLockState(const LockSnapshot &stateToRestore)
Definition: lock_state.h:195
stdx::condition_variable _cond
Definition: lock_state.h:77
CondVarLockGrantNotification()
Definition: lock_state.cpp:211
boost::optional< Milliseconds > _maxLockTimeout
Definition: lock_state.h:350
Definition: lock_manager_defs.h:60
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
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 inAWriteUnitOfWork() const
Definition: lock_state.h:155
LockSnapshot captures the state of all resources that are locked, what modes they&#39;re locked in...
Definition: locker.h:342
virtual LockResult lockGlobalComplete(Date_t deadline)
Definition: lock_state.h:144
Collection *const OperationContext *const opCtx
Definition: collection_impl.cpp:80
virtual LockResult lockGlobalBegin(LockMode mode, Date_t deadline)
Definition: lock_state.h:140
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:198