summaryrefslogtreecommitdiff
path: root/src/mongo/db/background.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2014-04-18 15:28:50 -0400
committerEric Milkie <milkie@10gen.com>2014-04-21 11:17:37 -0400
commit001b2c1ee301f814c4b9128b2f0ef1ee1354a4f1 (patch)
treeaae749fbf8554a03c2cc334c05b7815dfb7f48bc /src/mongo/db/background.cpp
parent9be380c23afdad4ab7c4b09762f2f3d95caf674f (diff)
downloadmongo-001b2c1ee301f814c4b9128b2f0ef1ee1354a4f1.tar.gz
SERVER-13620 Refactor background.h/cpp; add awaitNoBgOp methods.
(cherry picked from commit 9ad97ac9fd08cf56d4e6c4bdb5c1b10085b9040c)
Diffstat (limited to 'src/mongo/db/background.cpp')
-rw-r--r--src/mongo/db/background.cpp143
1 files changed, 116 insertions, 27 deletions
diff --git a/src/mongo/db/background.cpp b/src/mongo/db/background.cpp
index ecfd756542d..98965289f6a 100644
--- a/src/mongo/db/background.cpp
+++ b/src/mongo/db/background.cpp
@@ -28,63 +28,152 @@
* it in the license file.
*/
+#include "mongo/platform/basic.h"
+
#include "mongo/db/background.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <iostream>
+#include <string>
+
+#include "mongo/base/disallow_copying.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/map_util.h"
+#include "mongo/util/mongoutils/str.h"
+#include "mongo/util/string_map.h"
+
namespace mongo {
- SimpleMutex BackgroundOperation::m("bg");
- std::map<std::string, unsigned> BackgroundOperation::dbsInProg;
- std::set<std::string> BackgroundOperation::nsInProg;
+namespace {
+
+ class BgInfo {
+ MONGO_DISALLOW_COPYING(BgInfo);
+ public:
+ BgInfo() : _opsInProgCount(0) {}
+
+ void recordBegin();
+ int recordEnd();
+ void awaitNoBgOps(boost::unique_lock<boost::mutex>& lk);
+
+ int getOpsInProgCount() const { return _opsInProgCount; }
+
+ private:
+ int _opsInProgCount;
+ boost::condition_variable _noOpsInProg;
+ };
+
+ typedef StringMap<boost::shared_ptr<BgInfo> > BgInfoMap;
+ typedef BgInfoMap::const_iterator BgInfoMapIterator;
+
+ boost::mutex m;
+ BgInfoMap dbsInProg;
+ BgInfoMap nsInProg;
+
+ void BgInfo::recordBegin() {
+ ++_opsInProgCount;
+ }
+
+ int BgInfo::recordEnd() {
+ dassert(_opsInProgCount > 0);
+ --_opsInProgCount;
+ if (0 == _opsInProgCount) {
+ _noOpsInProg.notify_all();
+ }
+ return _opsInProgCount;
+ }
+
+ void BgInfo::awaitNoBgOps(boost::unique_lock<boost::mutex>& lk) {
+ while (_opsInProgCount > 0)
+ _noOpsInProg.wait(lk);
+ }
+ void recordBeginAndInsert(BgInfoMap* bgiMap, const StringData& key) {
+ boost::shared_ptr<BgInfo>& bgInfo = bgiMap->get(key);
+ if (!bgInfo)
+ bgInfo.reset(new BgInfo);
+ bgInfo->recordBegin();
+ }
+
+ void recordEndAndRemove(BgInfoMap* bgiMap, const StringData& key) {
+ BgInfoMapIterator iter = bgiMap->find(key);
+ fassert(0, iter != bgiMap->end());
+ if (0 == iter->second->recordEnd()) {
+ bgiMap->erase(iter);
+ }
+ }
+
+ void awaitNoBgOps(
+ boost::unique_lock<boost::mutex>& lk,
+ BgInfoMap* bgiMap,
+ const StringData& key) {
+
+ boost::shared_ptr<BgInfo> bgInfo = mapFindWithDefault(
+ *bgiMap, key, boost::shared_ptr<BgInfo>());
+ if (!bgInfo)
+ return;
+ bgInfo->awaitNoBgOps(lk);
+ }
+
+} // namespace
bool BackgroundOperation::inProgForDb(const StringData& db) {
- SimpleMutex::scoped_lock lk(m);
- return dbsInProg[db.toString()] > 0;
+ boost::mutex::scoped_lock lk(m);
+ return dbsInProg.find(db) != dbsInProg.end();
}
bool BackgroundOperation::inProgForNs(const StringData& ns) {
- SimpleMutex::scoped_lock lk(m);
- return nsInProg.count(ns.toString()) > 0;
+ boost::mutex::scoped_lock lk(m);
+ return nsInProg.find(ns) != nsInProg.end();
}
void BackgroundOperation::assertNoBgOpInProgForDb(const StringData& db) {
- uassert(12586,
- "cannot perform operation: a background operation is currently running for this database",
+ uassert(ErrorCodes::BackgroundOperationInProgressForDatabase, mongoutils::str::stream() <<
+ "cannot perform operation: a background operation is currently running for "
+ "database " << db,
!inProgForDb(db));
}
void BackgroundOperation::assertNoBgOpInProgForNs(const StringData& ns) {
- uassert(12587,
- "cannot perform operation: a background operation is currently running for this collection",
+ uassert(ErrorCodes::BackgroundOperationInProgressForNamespace, mongoutils::str::stream() <<
+ "cannot perform operation: a background operation is currently running for "
+ "collection" << ns,
!inProgForNs(ns));
}
+ void BackgroundOperation::awaitNoBgOpInProgForDb(const StringData& db) {
+ boost::unique_lock<boost::mutex> lk(m);
+ awaitNoBgOps(lk, &dbsInProg, db);
+ }
+
+ void BackgroundOperation::awaitNoBgOpInProgForNs(const StringData& ns) {
+ boost::unique_lock<boost::mutex> lk(m);
+ awaitNoBgOps(lk, &nsInProg, ns);
+ }
+
BackgroundOperation::BackgroundOperation(const StringData& ns) : _ns(ns) {
- SimpleMutex::scoped_lock lk(m);
- dbsInProg[_ns.db().toString()]++;
- nsInProg.insert(_ns.ns());
+ boost::mutex::scoped_lock lk(m);
+ recordBeginAndInsert(&dbsInProg, _ns.db());
+ recordBeginAndInsert(&nsInProg, _ns.ns());
}
BackgroundOperation::~BackgroundOperation() {
- SimpleMutex::scoped_lock lk(m);
- dbsInProg[_ns.db().toString()]--;
- nsInProg.erase(_ns.ns());
+ boost::mutex::scoped_lock lk(m);
+ recordEndAndRemove(&dbsInProg, _ns.db());
+ recordEndAndRemove(&nsInProg, _ns.ns());
}
- void BackgroundOperation::dump(std::stringstream& ss) {
- SimpleMutex::scoped_lock lk(m);
+ void BackgroundOperation::dump(std::ostream& ss) {
+ boost::mutex::scoped_lock lk(m);
if( nsInProg.size() ) {
ss << "\n<b>Background Jobs in Progress</b>\n";
- for( std::set<std::string>::iterator i = nsInProg.begin(); i != nsInProg.end(); i++ )
- ss << " " << *i << '\n';
+ for( BgInfoMapIterator i = nsInProg.begin(); i != nsInProg.end(); ++i )
+ ss << " " << i->first << '\n';
}
- for( std::map<std::string,unsigned>::iterator i = dbsInProg.begin(); i != dbsInProg.end(); i++ ) {
- if( i->second )
- ss << "database " << i->first << ": " << i->second << '\n';
+ for( BgInfoMapIterator i = dbsInProg.begin(); i != dbsInProg.end(); ++i ) {
+ if( i->second->getOpsInProgCount() )
+ ss << "database " << i->first << ": " << i->second->getOpsInProgCount() << '\n';
}
}
-
-
-
} // namespace mongo