// @file file_allocator.h /* Copyright 2009 10gen Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute * linked combinations including the program with the OpenSSL library. You * must comply with the GNU Affero General Public License in all respects * for all of the code used other than as permitted herein. If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. If you do not * wish to do so, delete this exception statement from your version. If you * delete this exception statement from all source files in the program, * then also delete it in the license file. */ #include "mongo/pch.h" #include #include #include #include "mongo/util/concurrency/mutex.h" namespace mongo { /* * Handles allocation of contiguous files on disk. Allocation may be * requested asynchronously or synchronously. * singleton */ class FileAllocator : boost::noncopyable { /* * The public functions may not be called concurrently. The allocation * functions may be called multiple times per file, but only the first * size specified per file will be used. */ public: void start(); /** * May be called if file exists. If file exists, or its allocation has * been requested, size is updated to match existing file size. */ void requestAllocation( const string &name, long &size ); /** * Returns when file has been allocated. If file exists, size is * updated to match existing file size. */ void allocateAsap( const string &name, unsigned long long &size ); void waitUntilFinished() const; bool hasFailed() const; static void ensureLength(int fd, long size); /** @return the singleton */ static FileAllocator * get(); private: FileAllocator(); void checkFailure(); // caller must hold pendingMutex_ lock. Returns size if allocated or // allocation requested, -1 otherwise. long prevSize( const string &name ) const; // caller must hold pendingMutex_ lock. bool inProgress( const string &name ) const; /** called from the worked thread */ static void run( FileAllocator * fa ); // generate a unique name for temporary files string makeTempFileName( boost::filesystem::path root ); mutable mongo::mutex _pendingMutex; mutable boost::condition _pendingUpdated; std::list< string > _pending; mutable map< string, long > _pendingSize; // unique number for temporary files static unsigned long long _uniqueNumber; bool _failed; static FileAllocator* _instance; }; } // namespace mongo