Files
mongo/db/storage.cpp

149 lines
4.1 KiB
C++
Raw Normal View History

2009-02-02 18:18:22 -05:00
// storage.cpp
#include "stdafx.h"
#include "pdfile.h"
#include "reccache.h"
#include "rec.h"
#include "db.h"
namespace mongo {
BasicRecStore RecCache::tempStore;
RecCache BasicCached_RecStore::rc(BucketSize);
/*static void storeThread() {
2009-02-03 17:39:44 -05:00
massert("not using", false);
2009-02-02 18:18:22 -05:00
while( 1 ) {
2009-02-03 17:39:44 -05:00
sleepsecs(100);
2009-02-02 18:18:22 -05:00
dblock lk;
BasicCached_RecStore::rc.writeDirty();
RecCache::tempStore.flush();
}
}*/
2009-02-02 18:18:22 -05:00
// Currently only called on program exit.
2009-02-02 18:18:22 -05:00
void recCacheCloseAll() {
#if defined(_RECSTORE)
2009-02-04 13:53:08 -05:00
assert( dbMutexInfo.isLocked() );
(cout << "TEMP: writing dirty pages...\n").flush();
BasicCached_RecStore::rc.writeDirty( true );
2009-02-02 18:18:22 -05:00
RecCache::tempStore.flush();
2009-02-04 13:53:08 -05:00
(cout << "TEMP: write dirty done\n").flush();
#endif
2009-02-02 18:18:22 -05:00
}
void BasicRecStore::init(const char *fn, unsigned recsize)
{
massert( "compile packing problem recstore?", sizeof(RecStoreHeader) == 8192);
unsigned flags = ios::binary | ios::in | ios::out;
if( boost::filesystem::exists(fn) )
flags |= ios::ate;
else
flags |= ios::trunc;
f.open(fn, (ios_base::openmode) flags);
uassert( string("couldn't open file:")+fn, f.is_open() );
len = f.tellg();
if( len == 0 ) {
log() << "creating recstore file " << fn << '\n';
h.recsize = recsize;
len = sizeof(RecStoreHeader);
f.seekp(0);
f.write((const char *) &h, sizeof(RecStoreHeader));
}
else {
f.seekg(0);
f.read((char *) &h, sizeof(RecStoreHeader));
massert(string("recstore recsize mismatch, file:")+fn, h.recsize == recsize);
massert(string("bad recstore [1], file:")+fn, (h.leof-sizeof(RecStoreHeader)) % recsize == 0);
2009-02-04 11:26:51 -05:00
if( h.leof > len ) {
stringstream ss;
ss << "bad recstore, file:" << fn << " leof:" << h.leof << " len:" << len;
massert(ss.str(), false);
}
2009-02-02 18:18:22 -05:00
if( h.cleanShutdown )
log() << "warning: non-clean shutdown for file " << fn << '\n';
h.cleanShutdown = 2;
writeHeader();
}
f.flush();
2009-02-03 17:39:44 -05:00
// boost::thread t(storeThread);
2009-02-02 18:18:22 -05:00
}
2009-02-04 11:26:51 -05:00
/* -------------------------------------------------------- */
2009-02-04 13:53:08 -05:00
int ndirtywritten;
2009-02-02 18:18:22 -05:00
inline void RecCache::writeIfDirty(Node *n) {
if( n->dirty ) {
2009-02-04 13:53:08 -05:00
ndirtywritten++;
2009-02-02 18:18:22 -05:00
n->dirty = false;
tempStore.update(fileOfs(n->loc), n->data, recsize);
}
}
2009-02-03 17:39:44 -05:00
/* note that this is written in order, as much as possible, given that dirtyl is of type set. */
void RecCache::writeDirty( bool rawLog ) {
2009-02-02 18:18:22 -05:00
try {
2009-02-04 13:53:08 -05:00
ndirtywritten=0;
2009-02-03 17:39:44 -05:00
for( set<DiskLoc>::iterator i = dirtyl.begin(); i != dirtyl.end(); i++ ) {
2009-02-02 18:18:22 -05:00
map<DiskLoc, Node*>::iterator j = m.find(*i);
if( j != m.end() )
writeIfDirty(j->second);
}
2009-02-04 13:53:08 -05:00
out() << "TEMP: ndirtywritten: " << ndirtywritten << endl;
2009-02-02 18:18:22 -05:00
}
catch(...) {
const char *message = "Problem: bad() in RecCache::writeDirty, file io error\n";
if ( rawLog )
rawOut( message );
else
( log() << message ).flush();
2009-02-02 18:18:22 -05:00
}
dirtyl.clear();
}
2009-02-03 17:39:44 -05:00
// 100k * 8KB = 800MB
const unsigned RECCACHELIMIT = 150000;
2009-02-04 11:26:51 -05:00
//const unsigned RECCACHELIMIT = 25;
2009-02-02 18:18:22 -05:00
inline void RecCache::ejectOld() {
if( nnodes <= RECCACHELIMIT )
2009-02-02 18:18:22 -05:00
return;
Node *n = oldest;
while( 1 ) {
2009-02-04 11:26:51 -05:00
if( nnodes <= RECCACHELIMIT - 4 ) {
2009-02-02 18:18:22 -05:00
n->older = 0;
oldest = n;
2009-02-04 11:26:51 -05:00
assert( oldest ) ;
2009-02-02 18:18:22 -05:00
break;
}
nnodes--;
assert(n);
2009-02-04 11:26:51 -05:00
Node *nxt = n->newer;
2009-02-02 18:18:22 -05:00
writeIfDirty(n);
m.erase(n->loc);
delete n;
n = nxt;
}
}
2009-02-04 11:26:51 -05:00
void RecCache::dump() {
Node *n = oldest;
Node *last = 0;
while( n ) {
assert( n->older == last );
last = n;
// cout << n << ' ' << n->older << ' ' << n->newer << '\n';
n=n->newer;
}
assert( newest == last );
// cout << endl;
}
void dbunlocking() {
assert( dbMutexInfo.isLocked() );
2009-02-02 18:18:22 -05:00
BasicCached_RecStore::rc.ejectOld();
}
}