Add infos into target window
[ryzomcore.git] / ryzom / server / src / general_utilities_service / saves_unit.cpp
blob5c48d53863459481fbf714771624df78e95f00c3
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 //-----------------------------------------------------------------------------
21 // includes
22 //-----------------------------------------------------------------------------
24 // game share
25 #include "game_share/utils.h"
27 // local
28 #include "gus_utils.h"
29 #include "saves_unit.h"
32 //-------------------------------------------------------------------------------------------------
33 // namespaces
34 //-------------------------------------------------------------------------------------------------
36 using namespace std;
37 using namespace NLMISC;
38 using namespace GUS;
41 //-----------------------------------------------------------------------------
42 // SAVES namespace
43 //-----------------------------------------------------------------------------
45 namespace SAVES
47 //-----------------------------------------------------------------------------
48 // class CSavesUnitFileList
49 //-----------------------------------------------------------------------------
51 class CSavesUnitFileList: public ISavesUnitElement
53 public:
54 CSavesUnitFileList(const CSString& parentPath,const CSString& directoryName,const CSString& fileSpec);
55 bool update(ISavesCallbackHandler* parent);
56 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
58 protected:
59 CSString _Path;
60 CSString _Name;
61 CSString _FileSpec;
62 typedef map<CSString,CFileDescription> TFileDescriptions;
63 TFileDescriptions _FileDescriptions;
67 //-----------------------------------------------------------------------------
68 // class CShardRootDirectory
69 //-----------------------------------------------------------------------------
71 class CShardRootDirectory: public ISavesUnitElement
73 public:
74 CShardRootDirectory(const CSString& path);
75 bool update(ISavesCallbackHandler* parent);
76 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
78 private:
79 CSString _Path;
81 typedef vector<CSString> TRequiredFiles;
82 TRequiredFiles _RequiredFiles;
84 typedef map<CSString,TSavesUnitElementPtr> TRequiredDirectories;
85 TRequiredDirectories _RequiredDirectories;
87 typedef map<CSString,CFileDescription> TFiles;
88 TFiles _Files;
92 //-----------------------------------------------------------------------------
93 // class CShardCharacterDirectory
94 //-----------------------------------------------------------------------------
96 class CShardCharacterDirectory: public CSavesUnitFileList
98 public:
99 CShardCharacterDirectory(const CSString& parentPath,const CSString& directoryName);
103 //-----------------------------------------------------------------------------
104 // class CShardOfflineCommandsDirectory
105 //-----------------------------------------------------------------------------
107 class CShardOfflineCommandsDirectory: public CSavesUnitFileList
109 public:
110 CShardOfflineCommandsDirectory(const CSString& parentPath,const CSString& directoryName);
114 //-----------------------------------------------------------------------------
115 // class CShardGuildDirectory
116 //-----------------------------------------------------------------------------
118 class CShardGuildDirectory: public CSavesUnitFileList, public ISavesCallbackHandler
120 public:
121 CShardGuildDirectory(const CSString& parentPath,const CSString& directoryName);
122 bool update(ISavesCallbackHandler* parent);
123 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
125 void addNew(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size);
126 void addChange(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size);
127 void addDeleted(const NLMISC::CSString& fileName);
128 void addElement(ISavesUnitElement* newChild);
130 private:
131 ISavesCallbackHandler* _Parent;
135 //-----------------------------------------------------------------------------
136 // class CShardGuildFile
137 //-----------------------------------------------------------------------------
139 class CShardGuildFile: public ISavesUnitElement
141 public:
142 CShardGuildFile(const CSString& path);
143 bool update(ISavesCallbackHandler* parent);
144 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
146 private:
147 CSString _Path;
148 uint64 _Checksum;
149 uint32 _FileSize;
150 uint32 _TimeStamp;
154 //-----------------------------------------------------------------------------
155 // class CBakRootDirectory
156 //-----------------------------------------------------------------------------
158 class CBakRootDirectory: public ISavesUnitElement
160 public:
161 CBakRootDirectory(const CSString& path);
162 bool update(ISavesCallbackHandler* parent);
163 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
165 private:
166 CSString _Path;
167 typedef set<CSString> TChildren;
168 TChildren _Children;
172 //-----------------------------------------------------------------------------
173 // class CWwwRootDirectory
174 //-----------------------------------------------------------------------------
176 class CWwwRootDirectory: public ISavesUnitElement
178 public:
179 CWwwRootDirectory(const CSString& path);
180 bool update(ISavesCallbackHandler* parent);
181 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
183 private:
184 CSString _Path;
185 typedef set<CSString> TChildren;
186 TChildren _Children;
190 //-----------------------------------------------------------------------------
191 // class CWwwGroupDirectory
192 //-----------------------------------------------------------------------------
194 class CWwwGroupDirectory: public ISavesUnitElement
196 public:
197 CWwwGroupDirectory(const CSString& parentPath,const CSString& directoryName);
198 bool update(ISavesCallbackHandler* parent);
199 void appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const;
201 private:
202 CSString _Path;
203 CSString _Name;
204 typedef set<CSString> TChildren;
205 TChildren _Children;
209 //-----------------------------------------------------------------------------
210 // class CWwwChildDirectory
211 //-----------------------------------------------------------------------------
213 class CWwwChildDirectory: public CSavesUnitFileList
215 public:
216 CWwwChildDirectory(const CSString& parentPath,const CSString& directoryName);
220 //-----------------------------------------------------------------------------
221 // methods CSavesUnitFileList
222 //-----------------------------------------------------------------------------
224 CSavesUnitFileList::CSavesUnitFileList(const CSString& parentPath,const CSString& directoryName,const CSString& fileSpec)
226 _Path= parentPath+directoryName+"/";
227 _Name= directoryName;
228 _FileSpec= fileSpec;
231 void CSavesUnitFileList::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
233 // iterate over our file index, appending file descriptions to the fdc
234 for (TFileDescriptions::const_iterator it=_FileDescriptions.begin();it!=_FileDescriptions.end();++it)
236 BOMB_IF(path!=it->second.FileName.left(path.size()),"Skipping file because path doesn't match ("+path+"): "+it->second.FileName,continue);
237 fdc.addFile(it->second.FileName.leftCrop(path.size()),it->second.FileTimeStamp,it->second.FileSize);
241 bool CSavesUnitFileList::update(ISavesCallbackHandler* parent)
243 // if the directory no longer exists then signal all of its children as deleted
244 if (!NLMISC::CFile::isDirectory(_Path))
246 for (TFileDescriptions::iterator it=_FileDescriptions.begin();it!=_FileDescriptions.end();++it)
248 parent->addDeleted(_Path+it->first);
250 return false;
253 // scan the directory for files
254 CFileDescriptionContainer fdc;
255 fdc.addFileSpec(_Path+_FileSpec);
257 // a little set that we'll use to check for deleted files at the end...
258 set<CSString> recentFiles;
260 // run through the files looking for entries that don't match the previous scan
261 for (uint32 i=0;i<fdc.size();++i)
263 // get hold of the file name
264 const CFileDescription& fd= fdc[i];
265 const CSString& fileName= fd.FileName;
267 // mark this file as existing in the most recent scan
268 recentFiles.insert(fileName);
270 // lookup the file name in our file index...
271 TFileDescriptions::iterator it= _FileDescriptions.find(fileName);
273 // do we have a new file?
274 if (it==_FileDescriptions.end())
276 parent->addNew(fileName,fd.FileTimeStamp,fd.FileSize);
277 _FileDescriptions[fileName]=fdc[i];
278 continue;
281 // has the file changed?
282 if (it->second.FileTimeStamp!=fd.FileTimeStamp || it->second.FileSize!=fd.FileSize)
284 parent->addChange(fileName,fd.FileTimeStamp,fd.FileSize);
285 it->second=fdc[i];
286 continue;
290 // look for deleted files
291 vector<CSString> deadFiles;
292 for (TFileDescriptions::iterator it=_FileDescriptions.begin();it!=_FileDescriptions.end();++it)
294 if (recentFiles.find(it->first)==recentFiles.end())
296 deadFiles.push_back(it->first);
300 // deal with the dead files that we found
301 for (uint32 i=deadFiles.size();i--;)
303 parent->addDeleted(deadFiles[i]);
304 _FileDescriptions.erase(deadFiles[i]);
307 return true;
311 //-----------------------------------------------------------------------------
312 // methods CShardRootDirectory
313 //-----------------------------------------------------------------------------
315 CShardRootDirectory::CShardRootDirectory(const CSString& path)
317 _Path= cleanPath(path,true);
319 _RequiredFiles.push_back("account_names.txt");
320 _RequiredFiles.push_back("character_names.txt");
322 _RequiredDirectories["characters"]= new CShardCharacterDirectory(_Path,"characters");
323 _RequiredDirectories["characters_offline_commands"]= new CShardOfflineCommandsDirectory(_Path,"characters_offline_commands");
324 _RequiredDirectories["guilds"]= new CShardGuildDirectory(_Path,"guilds");
327 void CShardRootDirectory::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
329 for (TFiles::const_iterator it=_Files.begin();it!=_Files.end();++it)
331 fdc.addFile(CFile::getFilename(it->second.FileName),it->second.FileTimeStamp,it->second.FileSize);
335 bool CShardRootDirectory::update(ISavesCallbackHandler* parent)
337 // make sure that our own directory exists
338 if (!CFile::isDirectory(_Path))
339 return false;
341 // scan for the required files...
342 CFileDescriptionContainer fdc;
343 for (uint32 i=0;i<_RequiredFiles.size();++i)
345 // is the file missing ?
346 if (!CFile::fileExists(_Path+_RequiredFiles[i]))
348 // lookup the file name in our '_Files' map
349 TFiles::iterator it= _Files.find(fdc[i].FileName);
351 // check whether the file existed previously
352 if (it!=_Files.end())
354 parent->addDeleted(it->first);
355 _Files.erase(it);
357 continue;
360 // reestablish the file time and size info
361 fdc.addFile(_Path+_RequiredFiles[i]);
364 // run through the found files checking whether they're new or have changed
365 for (uint32 i=0;i<fdc.size();++i)
367 // lookup the file name in our '_Files' map
368 TFiles::iterator it= _Files.find(fdc[i].FileName);
370 // is the file new?
371 if (it==_Files.end())
373 parent->addNew(fdc[i].FileName,fdc[i].FileTimeStamp,fdc[i].FileSize);
374 _Files[fdc[i].FileName]= fdc[i];
375 continue;
378 // has the file changed ?
379 if (fdc[i].FileSize!=it->second.FileSize || fdc[i].FileTimeStamp!=it->second.FileTimeStamp)
381 parent->addChange(fdc[i].FileName,fdc[i].FileTimeStamp,fdc[i].FileSize);
382 it->second= fdc[i];
386 // run through the required directories to check that they're all active and OK
387 for (TRequiredDirectories::iterator it= _RequiredDirectories.begin(); it!=_RequiredDirectories.end();++it)
389 // if the required directory unit isn't active and the directory physically exists
390 // then activate it and add it to the parent object
391 if (!it->second->isActive() && CFile::isDirectory(_Path+it->first))
393 parent->addElement(it->second);
397 return true;
401 //-----------------------------------------------------------------------------
402 // methods CShardCharacterDirectory
403 //-----------------------------------------------------------------------------
405 CShardCharacterDirectory::CShardCharacterDirectory(const CSString& parentPath,const CSString& directoryName):
406 CSavesUnitFileList(parentPath,directoryName,"*_pdr.bin")
411 //-----------------------------------------------------------------------------
412 // methods CShardOfflineCommandsDirectory
413 //-----------------------------------------------------------------------------
415 CShardOfflineCommandsDirectory::CShardOfflineCommandsDirectory(const CSString& parentPath,const CSString& directoryName):
416 CSavesUnitFileList(parentPath,directoryName,"*.offline_commands")
421 //-----------------------------------------------------------------------------
422 // methods CShardGuildDirectory
423 //-----------------------------------------------------------------------------
425 CShardGuildDirectory::CShardGuildDirectory(const CSString& parentPath,const CSString& directoryName):
426 CSavesUnitFileList(parentPath,directoryName,"guild_*.bin")
428 _Parent=NULL;
431 void CShardGuildDirectory::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
433 // nothing to do... this element only contains sub dirctories and not files
436 bool CShardGuildDirectory::update(ISavesCallbackHandler* parent)
438 // take a copy of the _Parent and assign it a new value (basically performs a stacking operation)
439 ISavesCallbackHandler* hold=_Parent;
440 _Parent= parent;
442 // transfer to inheritted update() method
443 bool result=CSavesUnitFileList::update(this);
445 // return parent to previous value and return the result
446 _Parent=hold;
447 return result;
450 void CShardGuildDirectory::addNew(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size)
452 nlassert(_Parent!=NULL);
454 // a new file added ... need to add a new GuildFile element to the parent to represent it
455 _Parent->addElement(new CShardGuildFile(fileName));
457 // nothing to do - we let the guild file manage it's own existance
460 void CShardGuildDirectory::addChange(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size)
462 nlassert(_Parent!=NULL);
464 // nothing to do... guild files change all the time for no good reason
467 void CShardGuildDirectory::addDeleted(const NLMISC::CSString& fileName)
469 nlassert(_Parent!=NULL);
471 // nothing to do - we let the guild file manage it's own existance
474 void CShardGuildDirectory::addElement(ISavesUnitElement* newChild)
476 // pass the 'new element' up to the parent
477 _Parent->addElement(newChild);
481 //-----------------------------------------------------------------------------
482 // methods CShardGuildFile
483 //-----------------------------------------------------------------------------
485 CShardGuildFile::CShardGuildFile(const CSString& path)
487 _Path= path;
488 _Checksum= 0;
489 _FileSize= 0;
490 _TimeStamp= 0;
493 bool CShardGuildFile::update(ISavesCallbackHandler* parent)
495 // check whether the file still exists
496 if (!CFile::fileExists(_Path))
498 parent->addDeleted(_Path);
499 _Checksum= 0;
500 _FileSize= 0;
501 _TimeStamp= 0;
502 return false;
505 // get the up to date file size
506 uint32 fileSize= CFile::getFileSize(_Path);
508 // calculate the current checksum...
510 // setup a buffer and read the file data into it
511 CSString fileBody;
512 fileBody.readFromFile(_Path);
514 // pad the buffer to a multiple of 8 characters
515 fileBody+=CSString("01234567").left(8-(fileBody.size()&7));
516 nlassert( (fileBody.size()&7)==0 && fileBody.size()>7 );
518 // run through the buffer performing a very simple shift and xor checksum (good enough for our purposes)
519 // note that we could have used an MD5 but his is much much much faster (less strain on the CPU)
520 uint64 checksum = 0;
521 for (uint32 i=fileBody.size()/8;i--;)
523 checksum= ((checksum<<1)|(checksum>>63))^((uint64*)&fileBody[0])[i];
526 // see whether we have a new file
527 if (_Checksum==0 && _FileSize==0)
529 _TimeStamp= CFile::getFileModificationDate(_Path);
530 parent->addNew(_Path,_TimeStamp,fileSize);
532 else
534 // see if we have a change to our file
535 if (_Checksum!=checksum || _FileSize!=fileSize)
537 _TimeStamp= CFile::getFileModificationDate(_Path);
538 parent->addChange(_Path,_TimeStamp,fileSize);
542 // record our new values for next time round
543 _Checksum= checksum;
544 _FileSize= fileSize;
546 return true;
549 void CShardGuildFile::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
551 if (_Checksum!=0 || _FileSize!=0)
553 BOMB_IF(path!=_Path.left(path.size()),"Skipping file because path doesn't match ("+path+"): "+_Path,return);
554 fdc.addFile(_Path.leftCrop(path.size()),_TimeStamp,_FileSize);
559 //-----------------------------------------------------------------------------
560 // methods CBakRootDirectory
561 //-----------------------------------------------------------------------------
563 CBakRootDirectory::CBakRootDirectory(const CSString& path)
565 _Path= cleanPath(path,true);
568 void CBakRootDirectory::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
570 // nothing to do... this element only contains sub dirctories and not files
573 bool CBakRootDirectory::update(ISavesCallbackHandler* parent)
575 // scan the root directory for -inc, -day and refference sub directories
576 std::vector<std::string> subDirectories;
577 NLMISC::CPath::getPathContent(_Path,false,true,false,subDirectories);
578 for (uint32 i=0;i<subDirectories.size();++i)
580 CSString name= subDirectories[i];
582 // if directory name isn't one of the one's we're after then skip it
583 if (name.right(5)!="-inc/" && name.right(5)!="-day/" && name!="refference/")
584 continue;
586 // if the sub directory didn't previously exist then create it
587 if (_Children.find(name)==_Children.end())
589 _Children.insert(name);
590 parent->addElement(new CShardRootDirectory(name));
594 return true;
598 //-----------------------------------------------------------------------------
599 // methods CWwwRootDirectory
600 //-----------------------------------------------------------------------------
602 CWwwRootDirectory::CWwwRootDirectory(const CSString& path)
604 _Path= cleanPath(path,true);
607 void CWwwRootDirectory::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
609 // nothing to do... this element only contains sub dirctories and not files
612 bool CWwwRootDirectory::update(ISavesCallbackHandler* parent)
614 // scan the root directory for 2 letter sub directories
615 std::vector<std::string> subDirectories;
616 NLMISC::CPath::getPathContent(_Path,false,true,false,subDirectories);
617 for (uint32 i=0;i<subDirectories.size();++i)
619 // if directory name is not 2 letters then skip it
620 if (subDirectories[i].size()!=2)
621 continue;
623 // if the sub directory didn't previously exist then create it
624 if (_Children.find(subDirectories[i])==_Children.end())
626 _Children.insert(subDirectories[i]);
627 parent->addElement(new CWwwGroupDirectory(_Path,subDirectories[i]));
631 return true;
635 //-----------------------------------------------------------------------------
636 // methods CWwwGroupDirectory
637 //-----------------------------------------------------------------------------
639 CWwwGroupDirectory::CWwwGroupDirectory(const CSString& parentPath,const CSString& directoryName)
641 _Path= parentPath+directoryName+"/";
642 _Name= directoryName;
645 void CWwwGroupDirectory::appendFileListToFdc(const NLMISC::CSString& path,CFileDescriptionContainer &fdc) const
647 // nothing to do... this element only contains sub dirctories and not files
650 bool CWwwGroupDirectory::update(ISavesCallbackHandler* parent)
652 // make sure the directory hasn't been deleted
653 if (!NLMISC::CFile::isDirectory(_Path))
654 return false;
656 // scan the directory for sub directories starting with same first 2 letters
657 std::vector<std::string> subDirectories;
658 NLMISC::CPath::getPathContent(_Path,false,true,false,subDirectories);
659 for (uint32 i=0;i<subDirectories.size();++i)
661 // if directory name is not 2 letters then skip it
662 if (CSString(subDirectories[i]).left(2)!=_Name)
663 continue;
665 // if the sub directory didn't previously exist then create it
666 if (_Children.find(subDirectories[i])==_Children.end())
668 _Children.insert(subDirectories[i]);
669 parent->addElement(new CWwwChildDirectory(_Path,subDirectories[i]));
673 return true;
677 //-----------------------------------------------------------------------------
678 // methods CWwwChildDirectory
679 //-----------------------------------------------------------------------------
681 CWwwChildDirectory::CWwwChildDirectory(const CSString& parentPath,const CSString& directoryName):
682 CSavesUnitFileList(parentPath,directoryName,"*")
687 //-----------------------------------------------------------------------------
688 // methods CSavesUnit
689 //-----------------------------------------------------------------------------
691 CSavesUnit::CSavesUnit()
693 _IsInitialised= false;
694 _IsFirstScan= true;
695 _ChangeMsg= new CMsgRSUpdate;
698 void CSavesUnit::init(const CSString& directoryName,TType type)
700 // setup our properties
701 _IsFirstScan= true;
702 _IsInitialised= true;
703 _Children.clear();
704 _Path= cleanPath(directoryName,true);
706 // add the root elements to the children container
707 switch(type)
709 case SHARD:
710 _Children.push_back(new CShardRootDirectory(_Path));
711 _Children.back()->setActive(true);
712 break;
714 case BAK:
715 _Children.push_back(new CBakRootDirectory(_Path));
716 _Children.back()->setActive(true);
717 break;
719 case WWW:
720 _Children.push_back(new CWwwRootDirectory(_Path));
721 _Children.back()->setActive(true);
722 break;
724 default:
725 nlerror("Invalid saves module type");
728 // setup the children iterator to start at the first element
729 _IterationIndex= 0;
732 void CSavesUnit::update()
734 nlassert(_IsInitialised);
735 if (_IterationIndex>=_Children.size())
737 // reset the update iterator
738 _IterationIndex= 0;
740 // clear the 'first scan' flag meaning that we've now scanned the entire directory tree at least once
741 _IsFirstScan= false;
743 else
745 // update the next directory
746 if (_Children[_IterationIndex]->update(this)==false)
748 // the update returned false meaning the directory doesn't exist any more...
750 // mark the child object as inactive
751 _Children[_IterationIndex]->setActive(false);
753 // drop the object from our chilren container
754 _Children[_IterationIndex]= _Children.back();
755 _Children.pop_back();
757 else
759 // move the iterator on for the next update
760 ++_IterationIndex;
765 bool CSavesUnit::ready() const
767 nlassert(_IsInitialised);
768 return !_IsFirstScan;
771 void CSavesUnit::getFileList(CFileDescriptionContainer &result) const
773 // clear out the result container before we begin
774 result.clear();
776 // iterate over children getting each off them to add their files to the result...
777 for (uint32 i=0;i<_Children.size();++i)
779 _Children[i]->appendFileListToFdc(_Path,result);
783 void CSavesUnit::addElement(ISavesUnitElement* newChild)
785 // add the element to out children container
786 _Children.push_back(newChild);
788 // mark the element as 'active'
789 newChild->setActive(true);
792 TMsgRSUpdatePtr CSavesUnit::popNextChangeSet()
794 // setup a smart pointer to avoid premature destruction of our return object
795 TMsgRSUpdatePtr result= _ChangeMsg;
797 // create a new message to hold future changes
798 _ChangeMsg= new CMsgRSUpdate;
800 // return the current change set
801 return result;
804 void CSavesUnit::addNew(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size)
806 // if there's an active '_ChangeMsg' message object then add our new entry to it
807 if (_ChangeMsg!=NULL)
809 BOMB_IF(_Path!=fileName.left(_Path.size()),"addNew() FAILED: Skipping file because path doesn't match ("+_Path+"): "+fileName,return);
810 _ChangeMsg->addNew(fileName.leftCrop(_Path.size()),timeStamp,size);
814 void CSavesUnit::addChange(const NLMISC::CSString& fileName,uint32 timeStamp,uint32 size)
816 // if there's an active '_ChangeMsg' message object then add our new entry to it
817 if (_ChangeMsg!=NULL)
819 BOMB_IF(_Path!=fileName.left(_Path.size()),"addChange() FAILED: Skipping file because path doesn't match ("+_Path+"): "+fileName,return);
820 _ChangeMsg->addChange(fileName.leftCrop(_Path.size()),timeStamp,size);
824 void CSavesUnit::addDeleted(const NLMISC::CSString& fileName)
826 // if there's an active '_ChangeMsg' message object then add our new entry to it
827 if (_ChangeMsg!=NULL)
829 BOMB_IF(_Path!=fileName.left(_Path.size()),"addDeleted() FAILED: Skipping file because path doesn't match ("+_Path+"): "+fileName,return);
830 _ChangeMsg->addDeleted(fileName.leftCrop(_Path.size()));
835 //-----------------------------------------------------------------------------
836 // methods ISavesUnitElement
837 //-----------------------------------------------------------------------------
839 ISavesUnitElement::ISavesUnitElement()
841 _ActivationCounter=0;
844 bool ISavesUnitElement::isActive() const
846 return (_ActivationCounter!=0);
849 void ISavesUnitElement::setActive(bool value)
851 if (value)
853 ++_ActivationCounter;
855 else
857 nlassert(_ActivationCounter>0);
858 --_ActivationCounter;