diff options
author | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
---|---|---|
committer | Antonin Kral <a.kral@bobek.cz> | 2011-09-14 17:08:06 +0200 |
commit | 5d342a758c6095b4d30aba0750b54f13b8916f51 (patch) | |
tree | 762e9aa84781f5e3b96db2c02d356c29cf0217c0 /util/file_allocator.cpp | |
parent | cbe2d992e9cd1ea66af9fa91df006106775d3073 (diff) | |
download | mongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz |
Imported Upstream version 2.0.0
Diffstat (limited to 'util/file_allocator.cpp')
-rw-r--r-- | util/file_allocator.cpp | 73 |
1 files changed, 60 insertions, 13 deletions
diff --git a/util/file_allocator.cpp b/util/file_allocator.cpp index 54590ed..b0572f9 100644 --- a/util/file_allocator.cpp +++ b/util/file_allocator.cpp @@ -32,19 +32,22 @@ using namespace mongoutils; #endif #include "file_allocator.h" +#include "paths.h" namespace mongo { - void ensureParentDirCreated(const boost::filesystem::path& p){ + boost::filesystem::path ensureParentDirCreated(const boost::filesystem::path& p){ const boost::filesystem::path parent = p.branch_path(); - + if (! boost::filesystem::exists(parent)){ ensureParentDirCreated(parent); log() << "creating directory " << parent.string() << endl; boost::filesystem::create_directory(parent); + flushMyDirectory(parent); // flushes grandparent to ensure parent exists after crash } - + assert(boost::filesystem::is_directory(parent)); + return parent; } #if defined(_WIN32) @@ -74,6 +77,10 @@ namespace mongo { // TODO : we should to avoid fragmentation } + bool FileAllocator::hasFailed() const { + return false; + } + #else FileAllocator::FileAllocator() @@ -174,6 +181,10 @@ namespace mongo { } } + bool FileAllocator::hasFailed() const { + return _failed; + } + void FileAllocator::checkFailure() { if (_failed) { // we want to log the problem (diskfull.js expects it) but we do not want to dump a stack tracke @@ -197,6 +208,19 @@ namespace mongo { return false; } + string makeTempFileName( path root ) { + while( 1 ) { + path p = root / "_tmp"; + stringstream ss; + ss << (unsigned) rand(); + p /= ss.str(); + string fn = p.string(); + if( !boost::filesystem::exists(p) ) + return fn; + } + return ""; + } + void FileAllocator::run( FileAllocator * fa ) { setThreadName( "FileAllocator" ); while( 1 ) { @@ -215,19 +239,25 @@ namespace mongo { name = fa->_pending.front(); size = fa->_pendingSize[ name ]; } + + string tmp; + long fd = 0; try { log() << "allocating new datafile " << name << ", filling with zeroes..." << endl; - ensureParentDirCreated(name); - long fd = open(name.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR); + + boost::filesystem::path parent = ensureParentDirCreated(name); + tmp = makeTempFileName( parent ); + ensureParentDirCreated(tmp); + + fd = open(tmp.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR); if ( fd <= 0 ) { - stringstream ss; - ss << "FileAllocator: couldn't open " << name << ' ' << errnoWithDescription(); - uassert( 10439 , ss.str(), fd <= 0 ); + log() << "FileAllocator: couldn't create " << name << " (" << tmp << ") " << errnoWithDescription() << endl; + uasserted(10439, ""); } #if defined(POSIX_FADV_DONTNEED) if( posix_fadvise(fd, 0, size, POSIX_FADV_DONTNEED) ) { - log() << "warning: posix_fadvise fails " << name << ' ' << errnoWithDescription() << endl; + log() << "warning: posix_fadvise fails " << name << " (" << tmp << ") " << errnoWithDescription() << endl; } #endif @@ -236,18 +266,32 @@ namespace mongo { /* make sure the file is the full desired length */ ensureLength( fd , size ); + close( fd ); + fd = 0; + + if( rename(tmp.c_str(), name.c_str()) ) { + log() << "error: couldn't rename " << tmp << " to " << name << ' ' << errnoWithDescription() << endl; + uasserted(13653, ""); + } + flushMyDirectory(name); + log() << "done allocating datafile " << name << ", " << "size: " << size/1024/1024 << "MB, " << " took " << ((double)t.millis())/1000.0 << " secs" << endl; - close( fd ); - + // no longer in a failed state. allow new writers. + fa->_failed = false; } catch ( ... ) { + if ( fd > 0 ) + close( fd ); log() << "error failed to allocate new file: " << name - << " size: " << size << ' ' << errnoWithDescription() << endl; + << " size: " << size << ' ' << errnoWithDescription() << warnings; + log() << " will try again in 10 seconds" << endl; // not going to warning logs try { + if ( tmp.size() ) + BOOST_CHECK_EXCEPTION( boost::filesystem::remove( tmp ) ); BOOST_CHECK_EXCEPTION( boost::filesystem::remove( name ) ); } catch ( ... ) { @@ -256,7 +300,10 @@ namespace mongo { fa->_failed = true; // not erasing from pending fa->_pendingUpdated.notify_all(); - return; // no more allocation + + + sleepsecs(10); + continue; } { |