summaryrefslogtreecommitdiff
path: root/src/mongo/db/concurrency/lock_stats.cpp
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-01-08 13:02:32 -0500
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2015-01-12 17:49:13 -0500
commit249e4c59f4e6b98a6109225f953639de4743bf6c (patch)
tree5c4c82afa2d1021327792faf3c12d9112e2bc669 /src/mongo/db/concurrency/lock_stats.cpp
parent7596d9d7cb2e0e53d4f4adb38f613dd35862eb0a (diff)
downloadmongo-249e4c59f4e6b98a6109225f953639de4743bf6c.tar.gz
SERVER-15614 Lock statistics for db.serverStatus.locks
Diffstat (limited to 'src/mongo/db/concurrency/lock_stats.cpp')
-rw-r--r--src/mongo/db/concurrency/lock_stats.cpp168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/mongo/db/concurrency/lock_stats.cpp b/src/mongo/db/concurrency/lock_stats.cpp
new file mode 100644
index 00000000000..ec6e597c608
--- /dev/null
+++ b/src/mongo/db/concurrency/lock_stats.cpp
@@ -0,0 +1,168 @@
+/**
+ * Copyright (C) 2014 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * 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
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * 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 GNU Affero General 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.
+ */
+
+#include "mongo/platform/basic.h"
+
+#include "mongo/bson/bsonobjbuilder.h"
+#include "mongo/db/concurrency/lock_stats.h"
+
+namespace mongo {
+
+ LockStats::LockStats() {
+
+ }
+
+ void LockStats::recordAcquisition(ResourceId resId, LockMode mode) {
+ PerModeAtomicLockStats& stat = get(resId);
+ stat.stats[mode].numAcquisitions.addAndFetch(1);
+ }
+
+ void LockStats::recordWait(ResourceId resId, LockMode mode) {
+ PerModeAtomicLockStats& stat = get(resId);
+ stat.stats[mode].numWaits.addAndFetch(1);
+ }
+
+ void LockStats::recordWaitTime(ResourceId resId, LockMode mode, uint64_t waitMicros) {
+ PerModeAtomicLockStats& stat = get(resId);
+ stat.stats[mode].combinedWaitTimeMicros.addAndFetch(waitMicros);
+ }
+
+ void LockStats::append(const LockStats& other) {
+ // Append all lock stats
+ for (int i = 0; i < ResourceTypesCount; i++) {
+ for (int mode = 0; mode < LockModesCount; mode++) {
+ const AtomicLockStats& otherStats = other._stats[i].stats[mode];
+
+ AtomicLockStats& thisStats = _stats[i].stats[mode];
+ thisStats.append(otherStats);
+ }
+ }
+
+ // Append the oplog stats
+ for (int mode = 0; mode < LockModesCount; mode++) {
+ const AtomicLockStats& otherStats = other._oplogStats.stats[mode];
+
+ AtomicLockStats& thisStats = _oplogStats.stats[mode];
+ thisStats.append(otherStats);
+ }
+ }
+
+ void LockStats::report(BSONObjBuilder* builder) const {
+ // All indexing below starts from offset 1, because we do not want to report/account
+ // position 0, which is a sentinel value for invalid resource/no lock.
+
+ for (int i = 1; i < ResourceTypesCount; i++) {
+ BSONObjBuilder resBuilder(builder->subobjStart(
+ resourceTypeName(static_cast<ResourceType>(i))));
+
+ _report(&resBuilder, _stats[i]);
+
+ resBuilder.done();
+ }
+
+ BSONObjBuilder resBuilder(builder->subobjStart("oplog"));
+ _report(&resBuilder, _oplogStats);
+ resBuilder.done();
+ }
+
+ void LockStats::_report(BSONObjBuilder* builder,
+ const PerModeAtomicLockStats& stat) const {
+
+ // All indexing below starts from offset 1, because we do not want to report/account
+ // position 0, which is a sentinel value for invalid resource/no lock.
+
+ // Num acquires
+ {
+ BSONObjBuilder numAcquires(builder->subobjStart("acquireCount"));
+ for (int mode = 1; mode < LockModesCount; mode++) {
+ numAcquires.append(legacyModeName(static_cast<LockMode>(mode)),
+ stat.stats[mode].numAcquisitions.load());
+ }
+ numAcquires.done();
+ }
+
+ // Num waits
+ {
+ BSONObjBuilder numWaits(builder->subobjStart("acquireWaitCount"));
+ for (int mode = 1; mode < LockModesCount; mode++) {
+ numWaits.append(legacyModeName(static_cast<LockMode>(mode)),
+ stat.stats[mode].numWaits.load());
+ }
+ numWaits.done();
+ }
+
+ // Total time waiting
+ {
+ BSONObjBuilder timeAcquiring(builder->subobjStart("timeAcquiringMicros"));
+ for (int mode = 1; mode < LockModesCount; mode++) {
+ timeAcquiring.append(legacyModeName(static_cast<LockMode>(mode)),
+ stat.stats[mode].combinedWaitTimeMicros.load());
+ }
+ timeAcquiring.done();
+ }
+ }
+
+ void LockStats::reset() {
+ for (int i = 0; i < ResourceTypesCount; i++) {
+ for (int mode = 0; mode < LockModesCount; mode++) {
+ _stats[i].stats[mode].reset();
+ }
+ }
+
+ for (int mode = 0; mode < LockModesCount; mode++) {
+ _oplogStats.stats[mode].reset();
+ }
+ }
+
+ LockStats::PerModeAtomicLockStats& LockStats::get(ResourceId resId) {
+ if (resId == resourceIdOplog) {
+ return _oplogStats;
+ }
+ else {
+ return _stats[resId.getType()];
+ }
+ }
+
+
+ //
+ // AtomicLockStats
+ //
+
+ void LockStats::AtomicLockStats::append(const AtomicLockStats& other) {
+ numAcquisitions.addAndFetch(other.numAcquisitions.load());
+ numWaits.addAndFetch(other.numWaits.load());
+ combinedWaitTimeMicros.addAndFetch(other.combinedWaitTimeMicros.load());
+ }
+
+ void LockStats::AtomicLockStats::reset() {
+ numAcquisitions.store(0);
+ numWaits.store(0);
+ combinedWaitTimeMicros.store(0);
+ }
+
+} // namespace mongo