/** * @file llvfs.h * @brief Definition of virtual file system * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLVFS_H #define LL_LLVFS_H #include <deque> #include "lluuid.h" #include "linked_lists.h" #include "llassettype.h" #include "llthread.h" enum EVFSValid { VFSVALID_UNKNOWN = 0, VFSVALID_OK = 1, VFSVALID_BAD_CORRUPT = 2, VFSVALID_BAD_CANNOT_OPEN_READONLY = 3, VFSVALID_BAD_CANNOT_CREATE = 4 }; // Lock types for open vfiles, pending async reads, and pending async appends // (There are no async normal writes, currently) enum EVFSLock { VFSLOCK_OPEN = 0, VFSLOCK_READ = 1, VFSLOCK_APPEND = 2, VFSLOCK_COUNT = 3 }; // internal classes class LLVFSBlock; class LLVFSFileBlock; class LLVFSFileSpecifier { public: LLVFSFileSpecifier(); LLVFSFileSpecifier(const LLUUID &file_id, const LLAssetType::EType file_type); bool operator<(const LLVFSFileSpecifier &rhs) const; bool operator==(const LLVFSFileSpecifier &rhs) const; public: LLUUID mFileID; LLAssetType::EType mFileType; }; class LLVFS { private: // Use createLLVFS() to open a VFS file // Pass 0 to not presize LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash); public: ~LLVFS(); // Use this function normally to create LLVFS files // Pass 0 to not presize static LLVFS * createLLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash); BOOL isValid() const { return (VFSVALID_OK == mValid); } EVFSValid getValidState() const { return mValid; } // ---------- The following fucntions lock/unlock mDataMutex ---------- BOOL getExists(const LLUUID &file_id, const LLAssetType::EType file_type); S32 getSize(const LLUUID &file_id, const LLAssetType::EType file_type); BOOL checkAvailable(S32 max_size); S32 getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type); BOOL setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size); void renameFile(const LLUUID &file_id, const LLAssetType::EType file_type, const LLUUID &new_id, const LLAssetType::EType &new_type); void removeFile(const LLUUID &file_id, const LLAssetType::EType file_type); S32 getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8 *buffer, S32 location, S32 length); S32 storeData(const LLUUID &file_id, const LLAssetType::EType file_type, const U8 *buffer, S32 location, S32 length); void incLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock); void decLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock); BOOL isLocked(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock); // ---------------------------------------------------------------- // Used to trigger evil WinXP behavior of "preloading" entire file into memory. void pokeFiles(); // Verify that the index file contents match the in-memory file structure // Very slow, do not call routinely. JC void audit(); // Check for uninitialized blocks. Slow, do not call in release. JC void checkMem(); // for debugging, prints a map of the vfs void dumpMap(); void dumpLockCounts(); void dumpStatistics(); void listFiles(); void dumpFiles(); protected: void removeFileBlock(LLVFSFileBlock *fileblock); void eraseBlockLength(LLVFSBlock *block); void eraseBlock(LLVFSBlock *block); void addFreeBlock(LLVFSBlock *block); //void mergeFreeBlocks(); void useFreeSpace(LLVFSBlock *free_block, S32 length); void sync(LLVFSFileBlock *block, BOOL remove = FALSE); void presizeDataFile(const U32 size); static LLFILE *openAndLock(const std::string& filename, const char* mode, BOOL read_lock); static void unlockAndClose(FILE *fp); // Can initiate LRU-based file removal to make space. // The immune file block will not be removed. LLVFSBlock *findFreeBlock(S32 size, LLVFSFileBlock *immune = NULL); // lock/unlock data mutex (mDataMutex) void lockData() { mDataMutex->lock(); } void unlockData() { mDataMutex->unlock(); } protected: LLMutex* mDataMutex; typedef std::map<LLVFSFileSpecifier, LLVFSFileBlock*> fileblock_map; fileblock_map mFileBlocks; typedef std::multimap<S32, LLVFSBlock*> blocks_length_map_t; blocks_length_map_t mFreeBlocksByLength; typedef std::multimap<U32, LLVFSBlock*> blocks_location_map_t; blocks_location_map_t mFreeBlocksByLocation; LLFILE *mDataFP; LLFILE *mIndexFP; std::deque<S32> mIndexHoles; std::string mIndexFilename; std::string mDataFilename; BOOL mReadOnly; EVFSValid mValid; S32 mLockCounts[VFSLOCK_COUNT]; BOOL mRemoveAfterCrash; }; extern LLVFS *gVFS; #endif