1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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 //-----------------------------------------------------------------------------
22 //-----------------------------------------------------------------------------
25 #include "game_share/utils.h"
28 #include "gus_utils.h"
29 #include "saves_unit.h"
32 //-------------------------------------------------------------------------------------------------
34 //-------------------------------------------------------------------------------------------------
37 using namespace NLMISC
;
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
47 //-----------------------------------------------------------------------------
48 // class CSavesUnitFileList
49 //-----------------------------------------------------------------------------
51 class CSavesUnitFileList
: public ISavesUnitElement
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;
62 typedef map
<CSString
,CFileDescription
> TFileDescriptions
;
63 TFileDescriptions _FileDescriptions
;
67 //-----------------------------------------------------------------------------
68 // class CShardRootDirectory
69 //-----------------------------------------------------------------------------
71 class CShardRootDirectory
: public ISavesUnitElement
74 CShardRootDirectory(const CSString
& path
);
75 bool update(ISavesCallbackHandler
* parent
);
76 void appendFileListToFdc(const NLMISC::CSString
& path
,CFileDescriptionContainer
&fdc
) const;
81 typedef vector
<CSString
> TRequiredFiles
;
82 TRequiredFiles _RequiredFiles
;
84 typedef map
<CSString
,TSavesUnitElementPtr
> TRequiredDirectories
;
85 TRequiredDirectories _RequiredDirectories
;
87 typedef map
<CSString
,CFileDescription
> TFiles
;
92 //-----------------------------------------------------------------------------
93 // class CShardCharacterDirectory
94 //-----------------------------------------------------------------------------
96 class CShardCharacterDirectory
: public CSavesUnitFileList
99 CShardCharacterDirectory(const CSString
& parentPath
,const CSString
& directoryName
);
103 //-----------------------------------------------------------------------------
104 // class CShardOfflineCommandsDirectory
105 //-----------------------------------------------------------------------------
107 class CShardOfflineCommandsDirectory
: public CSavesUnitFileList
110 CShardOfflineCommandsDirectory(const CSString
& parentPath
,const CSString
& directoryName
);
114 //-----------------------------------------------------------------------------
115 // class CShardGuildDirectory
116 //-----------------------------------------------------------------------------
118 class CShardGuildDirectory
: public CSavesUnitFileList
, public ISavesCallbackHandler
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
);
131 ISavesCallbackHandler
* _Parent
;
135 //-----------------------------------------------------------------------------
136 // class CShardGuildFile
137 //-----------------------------------------------------------------------------
139 class CShardGuildFile
: public ISavesUnitElement
142 CShardGuildFile(const CSString
& path
);
143 bool update(ISavesCallbackHandler
* parent
);
144 void appendFileListToFdc(const NLMISC::CSString
& path
,CFileDescriptionContainer
&fdc
) const;
154 //-----------------------------------------------------------------------------
155 // class CBakRootDirectory
156 //-----------------------------------------------------------------------------
158 class CBakRootDirectory
: public ISavesUnitElement
161 CBakRootDirectory(const CSString
& path
);
162 bool update(ISavesCallbackHandler
* parent
);
163 void appendFileListToFdc(const NLMISC::CSString
& path
,CFileDescriptionContainer
&fdc
) const;
167 typedef set
<CSString
> TChildren
;
172 //-----------------------------------------------------------------------------
173 // class CWwwRootDirectory
174 //-----------------------------------------------------------------------------
176 class CWwwRootDirectory
: public ISavesUnitElement
179 CWwwRootDirectory(const CSString
& path
);
180 bool update(ISavesCallbackHandler
* parent
);
181 void appendFileListToFdc(const NLMISC::CSString
& path
,CFileDescriptionContainer
&fdc
) const;
185 typedef set
<CSString
> TChildren
;
190 //-----------------------------------------------------------------------------
191 // class CWwwGroupDirectory
192 //-----------------------------------------------------------------------------
194 class CWwwGroupDirectory
: public ISavesUnitElement
197 CWwwGroupDirectory(const CSString
& parentPath
,const CSString
& directoryName
);
198 bool update(ISavesCallbackHandler
* parent
);
199 void appendFileListToFdc(const NLMISC::CSString
& path
,CFileDescriptionContainer
&fdc
) const;
204 typedef set
<CSString
> TChildren
;
209 //-----------------------------------------------------------------------------
210 // class CWwwChildDirectory
211 //-----------------------------------------------------------------------------
213 class CWwwChildDirectory
: public CSavesUnitFileList
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
;
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
);
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
];
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
);
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
]);
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
))
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
);
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
);
371 if (it
==_Files
.end())
373 parent
->addNew(fdc
[i
].FileName
,fdc
[i
].FileTimeStamp
,fdc
[i
].FileSize
);
374 _Files
[fdc
[i
].FileName
]= fdc
[i
];
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
);
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
);
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")
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
;
442 // transfer to inheritted update() method
443 bool result
=CSavesUnitFileList::update(this);
445 // return parent to previous value and return the 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
)
493 bool CShardGuildFile::update(ISavesCallbackHandler
* parent
)
495 // check whether the file still exists
496 if (!CFile::fileExists(_Path
))
498 parent
->addDeleted(_Path
);
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
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)
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
);
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
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/")
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
));
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)
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
]));
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
))
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
)
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
]));
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;
695 _ChangeMsg
= new CMsgRSUpdate
;
698 void CSavesUnit::init(const CSString
& directoryName
,TType type
)
700 // setup our properties
702 _IsInitialised
= true;
704 _Path
= cleanPath(directoryName
,true);
706 // add the root elements to the children container
710 _Children
.push_back(new CShardRootDirectory(_Path
));
711 _Children
.back()->setActive(true);
715 _Children
.push_back(new CBakRootDirectory(_Path
));
716 _Children
.back()->setActive(true);
720 _Children
.push_back(new CWwwRootDirectory(_Path
));
721 _Children
.back()->setActive(true);
725 nlerror("Invalid saves module type");
728 // setup the children iterator to start at the first element
732 void CSavesUnit::update()
734 nlassert(_IsInitialised
);
735 if (_IterationIndex
>=_Children
.size())
737 // reset the update iterator
740 // clear the 'first scan' flag meaning that we've now scanned the entire directory tree at least once
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();
759 // move the iterator on for the next update
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
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
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
)
853 ++_ActivationCounter
;
857 nlassert(_ActivationCounter
>0);
858 --_ActivationCounter
;