示例#1
0
    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;
    }
示例#2
0
        void FileCreatedOp::replay() {
            // i believe the code assumes new files are filled with zeros.  thus we have to recreate the file,
            // or rewrite at least, even if it were the right length.  perhaps one day we should change that
            // although easier to avoid defects if we assume it is zeros perhaps.
            string full = _p.asFullPath();
            if( boost::filesystem::exists(full) ) {
                try {
                    boost::filesystem::remove(full);
                }
                catch(std::exception& e) {
                    LOG(1) << "recover info FileCreateOp::replay unlink " << e.what() << endl;
                }
            }

            log() << "recover create file " << full << ' ' << _len/1024.0/1024.0 << "MB" << endl;
            if( boost::filesystem::exists(full) ) {
                // first delete if exists.
                try {
                    boost::filesystem::remove(full);
                }
                catch(...) {
                    log() << "warning could not delete file " << full << endl;
                }
            }
            ensureParentDirCreated(full);
            File f;
            f.open(full.c_str());
            massert(13547, str::stream() << "recover couldn't create file " << full, f.is_open());
            unsigned long long left = _len;
            const unsigned blksz = 64 * 1024;
            scoped_array<char> v( new char[blksz] );
            memset( v.get(), 0, blksz );
            fileofs ofs = 0;
            while( left ) {
                unsigned long long w = left < blksz ? left : blksz;
                f.write(ofs, v.get(), (unsigned) w);
                left -= w;
                ofs += w;
            }
            f.fsync();
            flushMyDirectory(full);
            massert(13628, str::stream() << "recover failure writing file " << full, !f.bad() );
        }
示例#3
0
    void FileAllocator::run( FileAllocator * fa ) {
        setThreadName( "FileAllocator" );
        while( 1 ) {
            {
                scoped_lock lk( fa->_pendingMutex );
                if ( fa->_pending.size() == 0 )
                    fa->_pendingUpdated.wait( lk.boost() );
            }
            while( 1 ) {
                string name;
                long size;
                {
                    scoped_lock lk( fa->_pendingMutex );
                    if ( fa->_pending.size() == 0 )
                        break;
                    name = fa->_pending.front();
                    size = fa->_pendingSize[ name ];
                }

                string tmp;
                long fd = 0;
                try {
                    log() << "allocating new datafile " << name << ", filling with zeroes..." << endl;
                    
                    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 ) {
                        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 << " (" << tmp << ") " << errnoWithDescription() << endl;
                    }
#endif

                    Timer t;

                    /* 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;

                    // 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() << warnings;
                    log() << "    will try again in 10 seconds" << endl; // not going to warning logs
                    try {
                        if ( tmp.size() )
                            MONGO_ASSERT_ON_EXCEPTION( boost::filesystem::remove( tmp ) );
                        MONGO_ASSERT_ON_EXCEPTION( boost::filesystem::remove( name ) );
                    }
                    catch ( ... ) {
                    }
                    scoped_lock lk( fa->_pendingMutex );
                    fa->_failed = true;
                    // not erasing from pending
                    fa->_pendingUpdated.notify_all();
                    
                    
                    sleepsecs(10);
                    continue;
                }

                {
                    scoped_lock lk( fa->_pendingMutex );
                    fa->_pendingSize.erase( name );
                    fa->_pending.pop_front();
                    fa->_pendingUpdated.notify_all();
                }
            }
        }
    }
示例#4
0
    void FileAllocator::run( FileAllocator * fa ) {
        setThreadName( "FileAllocator" );
        {
            // initialize unique temporary file name counter
            // TODO: SERVER-6055 -- Unify temporary file name selection
            SimpleMutex::scoped_lock lk(_uniqueNumberMutex);
            _uniqueNumber = curTimeMicros64();
        }
        while( 1 ) {
            {
                scoped_lock lk( fa->_pendingMutex );
                if ( fa->_pending.size() == 0 )
                    fa->_pendingUpdated.wait( lk.boost() );
            }
            while( 1 ) {
                string name;
                long size = 0;
                {
                    scoped_lock lk( fa->_pendingMutex );
                    if ( fa->_pending.size() == 0 )
                        break;
                    name = fa->_pending.front();
                    size = fa->_pendingSize[ name ];
                }

                string tmp;
                long fd = 0;
                try {
                    log() << "allocating new datafile " << name << ", filling with zeroes..." << endl;
                    
                    boost::filesystem::path parent = ensureParentDirCreated(name);
                    tmp = fa->makeTempFileName( parent );
                    ensureParentDirCreated(tmp);

#if defined(_WIN32)
                    fd = _open( tmp.c_str(), _O_RDWR | _O_CREAT | O_NOATIME, _S_IREAD | _S_IWRITE );
#else
                    fd = open(tmp.c_str(), O_CREAT | O_RDWR | O_NOATIME, S_IRUSR | S_IWUSR);
#endif
                    if ( 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 << " (" << tmp << ") " << errnoWithDescription() << endl;
                    }
#endif

                    Timer t;

                    /* make sure the file is the full desired length */
                    ensureLength( fd , size );

                    close( fd );
                    fd = 0;

                    if( rename(tmp.c_str(), name.c_str()) ) {
                        const string& errStr = errnoWithDescription();
                        const string& errMessage = str::stream()
                                << "error: couldn't rename " << tmp
                                << " to " << name << ' ' << errStr;
                        msgasserted(13653, errMessage);
                    }
                    flushMyDirectory(name);

                    log() << "done allocating datafile " << name << ", "
                          << "size: " << size/1024/1024 << "MB, "
                          << " took " << ((double)t.millis())/1000.0 << " secs"
                          << endl;

                    // no longer in a failed state. allow new writers.
                    fa->_failed = false;
                }
                catch ( const std::exception& e ) {
                    log() << "error: failed to allocate new file: " << name
                          << " size: " << size << ' ' << e.what()
                          << ".  will try again in 10 seconds" << endl;
                    if ( fd > 0 )
                        close( fd );
                    try {
                        if ( ! tmp.empty() )
                            boost::filesystem::remove( tmp );
                        boost::filesystem::remove( name );
                    } catch ( const std::exception& e ) {
                        log() << "error removing files: " << e.what() << endl;
                    }
                    scoped_lock lk( fa->_pendingMutex );
                    fa->_failed = true;
                    // not erasing from pending
                    fa->_pendingUpdated.notify_all();
                    
                    
                    sleepsecs(10);
                    continue;
                }

                {
                    scoped_lock lk( fa->_pendingMutex );
                    fa->_pendingSize.erase( name );
                    fa->_pending.pop_front();
                    fa->_pendingUpdated.notify_all();
                }
            }
        }
    }