summaryrefslogtreecommitdiff
path: root/util/file_allocator.cpp
diff options
context:
space:
mode:
authorAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
committerAntonin Kral <a.kral@bobek.cz>2011-09-14 17:08:06 +0200
commit5d342a758c6095b4d30aba0750b54f13b8916f51 (patch)
tree762e9aa84781f5e3b96db2c02d356c29cf0217c0 /util/file_allocator.cpp
parentcbe2d992e9cd1ea66af9fa91df006106775d3073 (diff)
downloadmongodb-5d342a758c6095b4d30aba0750b54f13b8916f51.tar.gz
Imported Upstream version 2.0.0
Diffstat (limited to 'util/file_allocator.cpp')
-rw-r--r--util/file_allocator.cpp73
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;
}
{