summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--db/database.h1
-rw-r--r--db/rec.h9
-rw-r--r--db/reccache.cpp40
-rw-r--r--db/reccache.h8
-rw-r--r--db/reci.h3
-rw-r--r--jstests/recstore.js24
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];
diff --git a/db/rec.h b/db/rec.h
index ce5a5331753..2f506534621 100644
--- a/db/rec.h
+++ b/db/rec.h
@@ -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});