static void durThread() { Client::initThread("journal"); bool samePartition = true; try { const std::string dbpathDir = boost::filesystem::path(storageGlobalParams.dbpath).string(); samePartition = onSamePartition(getJournalDir().string(), dbpathDir); } catch(...) { } while (shutdownRequested.loadRelaxed() == 0) { unsigned ms = storageGlobalParams.journalCommitInterval; if( ms == 0 ) { ms = samePartition ? 100 : 30; } unsigned oneThird = (ms / 3) + 1; // +1 so never zero try { stats.rotate(); boost::mutex::scoped_lock lock(flushMutex); // commit sooner if one or more getLastError j:true is pending for (unsigned i = 0; i <= 2; i++) { if (flushRequested.timed_wait(lock, Milliseconds(oneThird))) { // Someone forced a flush break; } if (commitJob._notify.nWaiting()) break; if (commitJob.bytes() > UncommittedBytesLimit / 2) break; } OperationContextImpl txn; // Waits for all active operations to drain and won't let new ones start. This // should be optimized to allow readers in (see SERVER-15262). AutoAcquireFlushLockForMMAPV1Commit flushLock(txn.lockState()); groupCommit(); remapPrivateView(); } catch(std::exception& e) { log() << "exception in durThread causing immediate shutdown: " << e.what() << endl; mongoAbort("exception in durThread"); } catch (...) { log() << "unhandled exception in durThread causing immediate shutdown" << endl; mongoAbort("unhandled exception in durThread"); } } cc().shutdown(); }
void go() { verify( options["r"].trueValue() || options["w"].trueValue() ); recSizeKB = options["recSizeKB"].numberInt(); if( recSizeKB == 0 ) recSizeKB = 4; verify( recSizeKB <= 64000 && recSizeKB > 0 ); MemoryMappedFile f; cout << "creating test file size:"; len = options["fileSizeMB"].numberLong(); if( len == 0 ) len = 1; cout << len << "MB ..." << endl; if( 0 && len > 2000 && !options["mmf"].trueValue() ) { // todo make tests use 64 bit offsets in their i/o -- i.e. adjust LogFile::writeAt and such cout << "\nsizes > 2GB not yet supported with mmf:false" << endl; return; } len *= 1024 * 1024; const char *fname = "./mongoperf__testfile__tmp"; try { boost::filesystem::remove(fname); } catch(...) { cout << "error deleting file " << fname << endl; return; } lf = new LogFile(fname,true); const unsigned sz = 1024 * 1024 * 32; // needs to be big as we are using synchronousAppend. if we used a regular MongoFile it wouldn't have to be char *buf = (char*) mongoMalloc(sz+4096); const char *p = round(buf); for( unsigned long long i = 0; i < len; i += sz ) { lf->synchronousAppend(p, sz); if( i % (1024ULL*1024*1024) == 0 && i ) { cout << i / (1024ULL*1024*1024) << "GB..." << endl; } } BSONObj& o = options; if( o["mmf"].trueValue() ) { delete lf; lf = 0; mmfFile = new MemoryMappedFile(); mmf = (char *) mmfFile->map(fname); verify( mmf ); syncDelaySecs = options["syncDelay"].numberInt(); if( syncDelaySecs ) { boost::thread t(syncThread); } } cout << "testing..."<< endl; cout << "options:" << o.toString() << endl; unsigned wthr = 1; if( !o["nThreads"].eoo() ) { wthr = (unsigned) o["nThreads"].Int(); } cout << "wthr " << wthr << endl; if( wthr < 1 ) { cout << "bad threads field value" << endl; return; } unsigned i = 0; unsigned d = 1; unsigned &nthr = nThreadsRunning; while( 1 ) { if( i++ % 8 == 0 ) { if( nthr < wthr ) { while( nthr < wthr && nthr < d ) { nthr++; boost::thread w(workerThread); } cout << "new thread, total running : " << nthr << endl; d *= 2; } } sleepsecs(1); unsigned long long w = iops.loadRelaxed(); iops.store(0); w /= 1; // 1 secs cout << w << " ops/sec "; if( mmf == 0 ) // only writing 4 bytes with mmf so we don't say this cout << (w * PG / 1024 / 1024) << " MB/sec"; cout << endl; } }