1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef FILE_MANAGER_H
18 #define FILE_MANAGER_H
21 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
26 #include "nel/misc/singleton.h"
27 #include "nel/misc/sstring.h"
28 #include "nel/misc/md5.h"
29 #include "nel/misc/smart_ptr.h"
30 #include "nel/net/module.h"
33 //-----------------------------------------------------------------------------
35 //-----------------------------------------------------------------------------
40 //-----------------------------------------------------------------------------
41 // forward class declarations
42 //-----------------------------------------------------------------------------
46 class IFileRequestValidator
;
47 class IFileInfoUpdateListener
;
48 class CRepositoryDirectory
;
52 //-----------------------------------------------------------------------------
54 //-----------------------------------------------------------------------------
58 NLMISC::CSString FileName
; // this name includes the directory name
61 NLMISC::CHashKeyMD5 Checksum
;
63 SFileInfo(): FileSize(0), FileTime(0) {}
73 void serial(NLMISC::IStream
& stream
)
75 stream
.serial(FileName
);
76 stream
.serial(FileSize
);
77 stream
.serial(FileTime
);
78 stream
.serial(Checksum
);
81 // a '<' operator for use in STL containers and algorithms
82 bool operator<(const SFileInfo
& other
) const
85 if (FileName
<other
.FileName
) return true;
86 if (other
.FileName
<FileName
) return false;
88 // file names match so compare time stamps
89 if (FileTime
<other
.FileTime
) return true;
90 if (other
.FileTime
<FileTime
) return false;
92 // looks like a match so far so compare sizes
93 if (FileSize
<other
.FileSize
) return true;
94 if (other
.FileSize
<FileSize
) return false;
96 // the entries are identical so compare checksums
97 return Checksum
< other
.Checksum
;
100 // Type used as parameter to updateFileInfo()
101 enum TUpdateMethod
{ DONT_RECALCULATE
, RECALCULATE_IF_CHANGED
, FORCE_RECALCULATE
};
103 // Update the file info by looking at the given file path on the disk
104 // the fileName parameter is simply a label example: updateFileInfo("foo/bar.txt","c:/rootdir/foo/bar.txt")
105 // The update methods determine whether or not to (re)calculate MD5 checksum
106 // - DONT_RECALCULATE - never recalculate
107 // - RECALCULATE_IF_CHANGED - recalculate if either the file time or file size have changed
108 // - FORCE_RECALCULATE - always recalculate
110 // returns true if the record is valid and unchanged, othrwise returns false
112 bool updateFileInfo(const NLMISC::CSString
& fileName
,const NLMISC::CSString
& fullFileName
, TUpdateMethod updateMethod
=RECALCULATE_IF_CHANGED
, IFileInfoUpdateListener
* updateListener
=NULL
);
114 typedef std::vector
<SFileInfo
> TFileInfoVector
;
115 typedef std::map
<NLMISC::CSString
,SFileInfo
> TFileInfoMap
;
118 //-----------------------------------------------------------------------------
120 //-----------------------------------------------------------------------------
121 // This class encapsulates a filespec description
122 // The file name and path sections of the spec are treated separately
124 // toto/*tata - will match all files matching '*tata' in directory toto
125 // toto*/tata - will match files called 'tata' in directories 'toto/',
126 // 'toto_to/', 'toto/to/', etc
127 //-----------------------------------------------------------------------------
134 CFileSpec(const NLMISC::CSString
& fileSpec
);
136 // test a complete match (filename and path)
137 bool matches(const NLMISC::CSString
& fullFileName
) const;
139 // test whether the given file name matches the filename part of the filespec
140 // note - the supplied filename should already have been stripped of its path
141 bool nameMatches(const NLMISC::CSString
& fileName
) const;
143 // test whether the given path matches the path part of the filespec
144 // note - the supplied path should not have an attached file name
145 bool pathMatches(const NLMISC::CSString
& path
) const;
147 // retrieve the filespec as a single string (for serialising, etc)
148 NLMISC::CSString
toString() const;
151 const NLMISC::CSString
& nameSpec() const;
152 const NLMISC::CSString
& pathSpec() const;
154 bool nameIsWild() const;
155 bool pathIsWild() const;
158 NLMISC::CSString _NameSpec
;
159 NLMISC::CSString _PathSpec
;
160 bool _NameIsWild
; // true if _NameSpec contains wildcards ('*' or '?')
161 bool _PathIsWild
; // true if _PathSpec contains wildcards ('*' or '?')
162 bool _AcceptAllNames
;
163 bool _AcceptAllPaths
;
167 //-----------------------------------------------------------------------------
168 // class IFileRequestValidator
169 //-----------------------------------------------------------------------------
170 // a callback interface to be implemented by classes who want to
171 // validate getFile() and getFileInfo() requests
172 //-----------------------------------------------------------------------------
174 class IFileRequestValidator
177 // overloadable callback methods
178 virtual bool cbValidateDownloadRequest(const NLNET::IModuleProxy
*sender
,const std::string
&fileName
) { return true; }
179 virtual bool cbValidateFileInfoRequest(const NLNET::IModuleProxy
*sender
,const std::string
&fileName
) { return true; }
183 //-----------------------------------------------------------------------------
184 // class IFileInfoUpdateListener
185 //-----------------------------------------------------------------------------
186 // a callback interface to be implemented by classes who want to
187 // receive update notification for finle info changes
188 //-----------------------------------------------------------------------------
190 class IFileInfoUpdateListener
193 // overloadable callback methods
194 virtual void cbFileInfoRescanning(const NLMISC::CSString
& fileName
,uint32 fileSize
) {} // called at start of rescan operation
195 virtual void cbFileInfoUpdate(const SFileInfo
& fileInfo
) {} // called at end of rescan
196 virtual void cbFileInfoErased(const NLMISC::CSString
& fileName
) {} //
200 //-----------------------------------------------------------------------------
201 // class CRepositoryDirectory
202 //-----------------------------------------------------------------------------
204 class CRepositoryDirectory
: public NLMISC::CRefCount
208 typedef std::map
<NLMISC::CSString
,TFileInfoMap
> TDirectoryTree
;
212 void rescanFull(IFileInfoUpdateListener
* updateListener
);
213 void rescanPartial(IFileInfoUpdateListener
* updateListener
);
214 void updateFile(const NLMISC::CSString
& fileName
,SFileInfo::TUpdateMethod updateMethod
, IFileInfoUpdateListener
* updateListener
);
217 void getFileInfo(const NLMISC::CSString
& fileSpec
,TFileInfoVector
& result
,IFileRequestValidator
* validator
,const NLNET::IModuleProxy
*sender
=NULL
) const;
218 void getFile(const NLMISC::CSString
& fileName
,NLMISC::CSString
& resultData
,IFileRequestValidator
* validator
,const NLNET::IModuleProxy
*sender
=NULL
) const;
221 const NLMISC::CSString
&getRootDirectory() const;
223 // persistence methods
225 bool writeIndex() const;
229 // ctor is private because only CFileManager singleton has the right to create us
230 friend class CFileManager
;
233 CRepositoryDirectory(const NLMISC::CSString
& path
);
237 void _rescanDirectory(const NLMISC::CSString
& directoryName
, bool recurse
, IFileInfoUpdateListener
* updateListener
);
240 NLMISC::CSString _Root
; // The root directory from which we are working
241 TDirectoryTree _DirectoryTree
; // The set of files that we know (note, directories are mapped directly here)
242 NLMISC::CSString _LastRescan
; // The name of the directory that we last rescanned
243 mutable bool _IndexFileIsUpToDate
; // Is the index file on disk up to date (or does it need to be rewritten)
245 typedef NLMISC::CSmartPtr
<CRepositoryDirectory
> TRepositoryDirectoryPtr
;
246 typedef NLMISC::CRefPtr
<CRepositoryDirectory
> TRepositoryDirectoryRefPtr
;
249 //-----------------------------------------------------------------------------
250 // class CFileManager
251 //-----------------------------------------------------------------------------
253 class CFileManager
: public NLMISC::CSingleton
<CFileManager
>
256 // --------------------------------------------------------
260 bool load(const NLMISC::CSString
& fileName
, uint32 startOffset
, uint32 numBytes
, NLMISC::CSString
& result
);
263 bool save(const NLMISC::CSString
& fileName
, const NLMISC::CMemStream
& data
);
265 // accessing basic info about files
266 uint32
getFileSize(const NLMISC::CSString
& fileName
);
268 // get hold of a smart pointer to a repository directory object, creating a new one if need be
269 // or sharing an object that already exists
270 TRepositoryDirectoryPtr
getRepositoryDirectory(const NLMISC::CSString
& path
);
274 // --------------------------------------------------------
275 // private data for the file cache
276 std::vector
<char> _CacheBuffer
;
278 struct SCacheFileEntry
280 NLMISC::CSString FileName
;
286 typedef std::list
<SCacheFileEntry
> TCacheFiles
;
287 TCacheFiles _CacheFiles
;
289 // --------------------------------------------------------
290 // private data for managing the set of repository directories
291 typedef std::map
<NLMISC::CSString
,TRepositoryDirectoryRefPtr
> TRepositoryDirectories
;
292 TRepositoryDirectories _RepositoryDirectories
;
295 } // end of namespace
297 //-----------------------------------------------------------------------------