summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2014-04-18 15:28:50 -0400
committerAndy Schwerin <schwerin@mongodb.com>2014-04-18 17:33:29 -0400
commit9ad97ac9fd08cf56d4e6c4bdb5c1b10085b9040c (patch)
treea0cce7eee8486969a2a7ea4372c0d0e0543b1ff3
parentd4b1e9e2e5097ff777b69543183088fa1fbb0129 (diff)
downloadmongo-9ad97ac9fd08cf56d4e6c4bdb5c1b10085b9040c.tar.gz
SERVER-13620 Refactor background.h/cpp; add awaitNoBgOp methods.
-rw-r--r--src/mongo/db/background.cpp143
-rw-r--r--src/mongo/db/background.h15
2 files changed, 123 insertions, 35 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
diff --git a/src/mongo/db/background.h b/src/mongo/db/background.h
index 7cde9ffa8de..3db4767f95a 100644
--- a/src/mongo/db/background.h
+++ b/src/mongo/db/background.h
@@ -35,12 +35,11 @@
#include <map>
#include <set>
-#include <string>
-#include <sstream>
+#include <iosfwd>
+#include "mongo/base/disallow_copying.h"
#include "mongo/base/string_data.h"
#include "mongo/db/namespace_string.h"
-#include "mongo/util/concurrency/mutex.h"
namespace mongo {
@@ -54,13 +53,16 @@ namespace mongo {
It's assumed this is not for super-high RPS things, so we don't do
anything special in the implementation here to be fast.
*/
- class BackgroundOperation : public boost::noncopyable {
+ class BackgroundOperation {
+ MONGO_DISALLOW_COPYING(BackgroundOperation);
public:
static bool inProgForDb(const StringData& db);
static bool inProgForNs(const StringData& ns);
static void assertNoBgOpInProgForDb(const StringData& db);
static void assertNoBgOpInProgForNs(const StringData& ns);
- static void dump(std::stringstream&);
+ static void awaitNoBgOpInProgForDb(const StringData& db);
+ static void awaitNoBgOpInProgForNs(const StringData& ns);
+ static void dump(std::ostream&);
/* check for in progress before instantiating */
BackgroundOperation(const StringData& ns);
@@ -69,9 +71,6 @@ namespace mongo {
private:
NamespaceString _ns;
- static std::map<std::string, unsigned> dbsInProg;
- static std::set<std::string> nsInProg;
- static SimpleMutex m;
};
} // namespace mongo