diff options
-rw-r--r-- | db/database.h | 1 | ||||
-rw-r--r-- | db/rec.h | 9 | ||||
-rw-r--r-- | db/reccache.cpp | 40 | ||||
-rw-r--r-- | db/reccache.h | 8 | ||||
-rw-r--r-- | db/reci.h | 3 | ||||
-rw-r--r-- | jstests/recstore.js | 24 |
6 files changed, 79 insertions, 6 deletions
diff --git a/db/database.h b/db/database.h index f71200fbd3b..4090917f008 100644 --- a/db/database.h +++ b/db/database.h @@ -49,6 +49,7 @@ namespace mongo { profileName = name + ".system.profile"; } ~Database() { + btreeStore->closeFiles(name, path); int n = files.size(); for ( int i = 0; i < n; i++ ) delete files[i]; @@ -34,6 +34,15 @@ public: virtual void drop(const char *ns) { dropNS(ns); } + + /* close datafiles associated with the db specified. */ + virtual void closeFiles(string dbname, string path) { + /* as this is only used for indexes so far, and we are in the same + PDFiles as the nonindex data, we just rely on them having been closed + at the same time. one day this may need to change. + */ + } + }; /* An in memory RecStoreInterface implementation ---------------------------- diff --git a/db/reccache.cpp b/db/reccache.cpp index 667bad83b34..dd6b281bcdc 100644 --- a/db/reccache.cpp +++ b/db/reccache.cpp @@ -213,6 +213,28 @@ inline void RecCache::writeIfDirty(Node *n) { }
}
+void RecCache::closeFiles(string dbname, string path) {
+ dassert( dbMutexInfo.isLocked() );
+ boostlock lk(rcmutex);
+
+ // first we write all dirty pages. it is not easy to check which Nodes are for a particular
+ // db, so we just write them all.
+ writeDirty( dirtyl.begin(), true );
+
+ string key = path + dbname + '.';
+ unsigned sz = key.size();
+ for( map<string, BasicRecStore*>::iterator i = storesByNsKey.begin(); i != storesByNsKey.end(); i++ ) {
+ map<string, BasicRecStore*>::iterator j = i;
+ i++;
+ if( strncmp(j->first.c_str(), key.c_str(), sz) == 0 ) {
+ assert( stores[j->second->fileNumber] != 0 );
+ stores[j->second->fileNumber] = 0;
+ delete j->second;
+ storesByNsKey.erase(j);
+ }
+ }
+}
+
void RecCache::closing() {
boostlock lk(rcmutex);
(cout << "TEMP: recCacheCloseAll() writing dirty pages...\n").flush();
@@ -312,6 +334,9 @@ void RecCache::dump() { // cout << endl;
}
+/* cleans up everything EXCEPT storesByNsKey.
+ note this function is slow should not be invoked often
+*/
void RecCache::closeStore(BasicRecStore *rs) {
int n = rs->fileNumber + Base;
for( set<DiskLoc>::iterator i = dirtyl.begin(); i != dirtyl.end(); ) {
@@ -327,12 +352,15 @@ void RecCache::closeStore(BasicRecStore *rs) { m.erase(k);
}
+ assert( stores[rs->fileNumber] != 0 );
+ stores[rs->fileNumber] = 0;
+/*
for( unsigned i = 0; i < stores.size(); i++ ) {
if( stores[i] == rs ) {
stores[i] = 0;
break;
}
- }
+ }*/
delete rs; // closes file
}
@@ -340,12 +368,12 @@ void RecCache::drop(const char *_ns) { // todo: test with a non clean shutdown file
boostlock lk(rcmutex);
- BasicRecStore *&rs = storesByNsKey[mknskey(_ns)];
+ map<string, BasicRecStore*>::iterator it = storesByNsKey.find(mknskey(_ns));
string fname;
- if( rs ) {
- fname = rs->filename;
- closeStore(rs);
- rs = 0;
+ if( it != storesByNsKey.end() ) {
+ fname = it->second->filename;
+ closeStore(it->second); // cleans up stores[] etc.
+ storesByNsKey.erase(it);
}
else {
bool found;
diff --git a/db/reccache.h b/db/reccache.h index 157548a5476..3e12a6fab85 100644 --- a/db/reccache.h +++ b/db/reccache.h @@ -181,6 +181,9 @@ public: return d;
}
+ void closeFiles(string dbname, string path);
+
+ // at termination: write dirty pages and close all files
void closing();
};
@@ -204,6 +207,11 @@ public: virtual void drop(const char *ns) { theRecCache.drop(ns); } + + /* close datafiles associated with the db specified. */ + virtual void closeFiles(string dbname, string path) { + theRecCache.closeFiles(dbname, dbpath); + } }; } /*namespace*/
diff --git a/db/reci.h b/db/reci.h index a93aed7e24a..4c870f6c434 100644 --- a/db/reci.h +++ b/db/reci.h @@ -27,6 +27,9 @@ public: /* drop the collection */ virtual void drop(const char *ns) = 0; + /* close datafiles associated with the db specified. */ + virtual void closeFiles(string dbname, string path) = 0; + /* todo add: closeFiles(dbname) eraseFiles(dbname) diff --git a/jstests/recstore.js b/jstests/recstore.js new file mode 100644 index 00000000000..f2e78e20731 --- /dev/null +++ b/jstests/recstore.js @@ -0,0 +1,24 @@ +// recstore.js +// this is a simple test for new recstores (see reci.h) +// it is probably redundant with other tests but is a convenient starting point +// for testing such things. + +t = db.storetest; + +t.drop(); + +t.save({z:3}); +t.save({z:2}); + +t.ensureIndex({z:1}); +t.ensureIndex({q:1}); +assert( t.find().sort({z:1})[0].z == 2 ); + +t.dropIndexes(); + +assert( t.find().sort({z:1})[0].z == 2 ); + +t.ensureIndex({z:1}); +t.ensureIndex({q:1}); + +db.getSisterDB('admin').$cmd.findOne({closeAllDatabases:1}); |