// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // 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 . #ifndef FILE_MANAGER_H #define FILE_MANAGER_H //----------------------------------------------------------------------------- // includes //----------------------------------------------------------------------------- // nel #include "nel/misc/singleton.h" #include "nel/misc/sstring.h" #include "nel/misc/md5.h" #include "nel/misc/smart_ptr.h" #include "nel/net/module.h" //----------------------------------------------------------------------------- // namespace PATCHMAN //----------------------------------------------------------------------------- namespace PATCHMAN { //----------------------------------------------------------------------------- // forward class declarations //----------------------------------------------------------------------------- struct SFileInfo; class CFileSpec; class IFileRequestValidator; class IFileInfoUpdateListener; class CRepositoryDirectory; class CFileManager; //----------------------------------------------------------------------------- // struct SFileInfo //----------------------------------------------------------------------------- struct SFileInfo { NLMISC::CSString FileName; // this name includes the directory name uint32 FileSize; uint32 FileTime; NLMISC::CHashKeyMD5 Checksum; SFileInfo(): FileSize(0), FileTime(0) {} void clear() { FileName.clear(); FileSize=0; FileTime=0; Checksum.clear(); } void serial(NLMISC::IStream& stream) { stream.serial(FileName); stream.serial(FileSize); stream.serial(FileTime); stream.serial(Checksum); } // a '<' operator for use in STL containers and algorithms bool operator<(const SFileInfo& other) const { // compare file names if (FileName TFileInfoVector; typedef std::map TFileInfoMap; //----------------------------------------------------------------------------- // class CFileSpec //----------------------------------------------------------------------------- // This class encapsulates a filespec description // The file name and path sections of the spec are treated separately // eg: // toto/*tata - will match all files matching '*tata' in directory toto // toto*/tata - will match files called 'tata' in directories 'toto/', // 'toto_to/', 'toto/to/', etc //----------------------------------------------------------------------------- class CFileSpec { public: // ctors CFileSpec(); CFileSpec(const NLMISC::CSString& fileSpec); // test a complete match (filename and path) bool matches(const NLMISC::CSString& fullFileName) const; // test whether the given file name matches the filename part of the filespec // note - the supplied filename should already have been stripped of its path bool nameMatches(const NLMISC::CSString& fileName) const; // test whether the given path matches the path part of the filespec // note - the supplied path should not have an attached file name bool pathMatches(const NLMISC::CSString& path) const; // retrieve the filespec as a single string (for serialising, etc) NLMISC::CSString toString() const; // accessors const NLMISC::CSString& nameSpec() const; const NLMISC::CSString& pathSpec() const; bool isWild() const; bool nameIsWild() const; bool pathIsWild() const; private: NLMISC::CSString _NameSpec; NLMISC::CSString _PathSpec; bool _NameIsWild; // true if _NameSpec contains wildcards ('*' or '?') bool _PathIsWild; // true if _PathSpec contains wildcards ('*' or '?') bool _AcceptAllNames; bool _AcceptAllPaths; }; //----------------------------------------------------------------------------- // class IFileRequestValidator //----------------------------------------------------------------------------- // a callback interface to be implemented by classes who want to // validate getFile() and getFileInfo() requests //----------------------------------------------------------------------------- class IFileRequestValidator { public: // overloadable callback methods virtual bool cbValidateDownloadRequest(const NLNET::IModuleProxy *sender,const std::string &fileName) { return true; } virtual bool cbValidateFileInfoRequest(const NLNET::IModuleProxy *sender,const std::string &fileName) { return true; } }; //----------------------------------------------------------------------------- // class IFileInfoUpdateListener //----------------------------------------------------------------------------- // a callback interface to be implemented by classes who want to // receive update notification for finle info changes //----------------------------------------------------------------------------- class IFileInfoUpdateListener { public: // overloadable callback methods virtual void cbFileInfoRescanning(const NLMISC::CSString& fileName,uint32 fileSize) {} // called at start of rescan operation virtual void cbFileInfoUpdate(const SFileInfo& fileInfo) {} // called at end of rescan virtual void cbFileInfoErased(const NLMISC::CSString& fileName) {} // }; //----------------------------------------------------------------------------- // class CRepositoryDirectory //----------------------------------------------------------------------------- class CRepositoryDirectory: public NLMISC::CRefCount { public: // handy types typedef std::map TDirectoryTree; // update methods void clear(); void rescanFull(IFileInfoUpdateListener* updateListener); void rescanPartial(IFileInfoUpdateListener* updateListener); void updateFile(const NLMISC::CSString& fileName,SFileInfo::TUpdateMethod updateMethod, IFileInfoUpdateListener* updateListener); // query methods void getFileInfo(const NLMISC::CSString& fileSpec,TFileInfoVector& result,IFileRequestValidator* validator,const NLNET::IModuleProxy *sender=NULL) const; void getFile(const NLMISC::CSString& fileName,NLMISC::CSString& resultData,IFileRequestValidator* validator,const NLNET::IModuleProxy *sender=NULL) const; // accessors const NLMISC::CSString &getRootDirectory() const; // persistence methods bool readIndex(); bool writeIndex() const; private: // ctor is private because only CFileManager singleton has the right to create us friend class CFileManager; // ctor and init CRepositoryDirectory(const NLMISC::CSString& path); private: // private methods void _rescanDirectory(const NLMISC::CSString& directoryName, bool recurse, IFileInfoUpdateListener* updateListener); // private data NLMISC::CSString _Root; // The root directory from which we are working TDirectoryTree _DirectoryTree; // The set of files that we know (note, directories are mapped directly here) NLMISC::CSString _LastRescan; // The name of the directory that we last rescanned mutable bool _IndexFileIsUpToDate; // Is the index file on disk up to date (or does it need to be rewritten) }; typedef NLMISC::CSmartPtr TRepositoryDirectoryPtr; typedef NLMISC::CRefPtr TRepositoryDirectoryRefPtr; //----------------------------------------------------------------------------- // class CFileManager //----------------------------------------------------------------------------- class CFileManager: public NLMISC::CSingleton { public: // -------------------------------------------------------- // public interface // loading file data bool load(const NLMISC::CSString& fileName, uint32 startOffset, uint32 numBytes, NLMISC::CSString& result); // saving files bool save(const NLMISC::CSString& fileName, const NLMISC::CMemStream& data); // accessing basic info about files uint32 getFileSize(const NLMISC::CSString& fileName); // get hold of a smart pointer to a repository directory object, creating a new one if need be // or sharing an object that already exists TRepositoryDirectoryPtr getRepositoryDirectory(const NLMISC::CSString& path); private: // -------------------------------------------------------- // private data for the file cache std::vector _CacheBuffer; struct SCacheFileEntry { NLMISC::CSString FileName; uint32 StartOffset; uint32 FileSize; uint32 FileTime; }; typedef std::list TCacheFiles; TCacheFiles _CacheFiles; // -------------------------------------------------------- // private data for managing the set of repository directories typedef std::map TRepositoryDirectories; TRepositoryDirectories _RepositoryDirectories; }; } // end of namespace //----------------------------------------------------------------------------- #endif