Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / backup_service_interface.cpp
blob6ee5fe5f2a47b1fb74857b282d0ecca9ad1b595c
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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 //-------------------------------------------------------------------------------------------------
18 // includes
19 //-------------------------------------------------------------------------------------------------
21 #include "stdpch.h"
22 #include "_backup_service_interface_singleton.h"
23 #include "utils.h"
26 //-------------------------------------------------------------------------------------------------
27 // namespaces
28 //-------------------------------------------------------------------------------------------------
30 using namespace std;
31 using namespace NLNET;
32 using namespace NLMISC;
35 //-------------------------------------------------------------------------------------------------
36 // const FileNameValidator
37 //-------------------------------------------------------------------------------------------------
39 // little class designed to test validity of file names in a reasonably rapid manor
40 class CFileNameValidator
42 public:
43 // setup the set of valid characters for the file name
44 CFileNameValidator()
46 memset(&_Data,0,sizeof(_Data));
47 for (uint32 i='A'; i<='Z';++i) _Data[i]= true;
48 for (uint32 i='a'; i<='z';++i) _Data[i]= true;
49 for (uint32 i='0'; i<='9';++i) _Data[i]= true;
50 _Data[(uint32)'/']= true;
51 _Data[(uint32)'.']= true;
52 _Data[(uint32)'_']= true;
53 _Data[(uint32)' ']= true;
56 // lookup a character to determine whether it's valid or not
57 bool operator[](char c) const
59 return _Data[(uint8)c];
62 // check all of the characters in a file name to ensure that it is valid
63 // return true if the file name is ok, otherwise false
64 bool checkFileName(const std::string& fileName) const
66 for (uint32 i=(uint32)fileName.size();i--;)
68 if (operator[](fileName[i])==true)
69 continue;
71 nlwarning("FileNameValidator: refusing character '%c' (%u) in file name: %s",fileName[i],fileName[i],fileName.c_str());
72 return false;
74 return true;
77 private:
78 // private data
79 bool _Data[256];
82 // a constant instance of the validator class
83 static const CFileNameValidator FileNameValidator;
86 //-------------------------------------------------------------------------------------------------
87 // methods & globals CBackupMsgSaveFile
88 //-------------------------------------------------------------------------------------------------
90 CBackupMsgSaveFile::CBackupMsgSaveFile( const std::string& filename, TBackupMsgSaveFileType msgType, const CBackupServiceInterface& itf )
92 //DataMsg.setType( getConversionTable().toString( msgType ) );
93 DataMsg.setType( _TypesStr[msgType] );
94 string pathFilename = itf.getRemotePath() + filename;
95 DataMsg.serial( pathFilename );
97 FileName = filename; // the filename with no heading remote path
98 _MsgType = msgType;
101 const char *CBackupMsgSaveFile::_TypesStr [CBackupMsgSaveFile::NbTypes] =
103 "save_file",
104 "SAVE_CHECK_FILE",
105 "append_file",
106 "append_file_check",
110 //-------------------------------------------------------------------------------------------------
111 // methods CBackupServiceInterface
112 //-------------------------------------------------------------------------------------------------
114 void CBackupServiceInterface::init(const std::string& bsiname)
116 _Name= bsiname;
119 void CBackupServiceInterface::setRemotePath( const std::string& remotePath )
121 _RemotePath = CPath::standardizePath( remotePath );
124 void CBackupServiceInterface::setLocalPath( const std::string& localPath )
126 _LocalPath = CPath::standardizePath( localPath );
129 void CBackupServiceInterface::requestFile(const std::string& fileName, NLMISC::CSmartPtr<IBackupFileReceiveCallback> cb)
131 H_AUTO(BSIF_RequestFile);
133 // check that the file name is valid
134 BOMB_IF(!FileNameValidator.checkFileName(fileName),"Failed to send get file request "+CSString(fileName).quote()+" due to invalid characters in file name",return);
136 // if there's no BS connected then complain and queue the file for loading later
137 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
139 BOMB( ("Failed to request file "+CSString(fileName).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
142 // create a log message...
143 // nldebug("BSIF: requestFile(): FileName: %s",fileName.quote().c_str(),msg.DataMsg.length());
145 // store away the callback for this action and retrieve the associated request id
146 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushFileCallback(cb, this);
148 // dispatch the request
149 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchRequestFile(_Name, requestId, _RemotePath+fileName);
152 // load a file synchronously
153 void CBackupServiceInterface::syncLoadFile(const std::string& fileName, NLMISC::CSmartPtr<IBackupFileReceiveCallback> cb)
155 H_AUTO(BSIF_RequestFile);
157 // check that the file name is valid
158 BOMB_IF(!FileNameValidator.checkFileName(fileName),"Failed to send sync load file "+CSString(fileName).quote()+" due to invalid characters in file name",return);
160 // store away the callback for this action and retrieve the associated request id
161 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushFileCallback(cb, this);
163 // dispatch the request
164 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchSyncLoadFile(_Name, requestId, _RemotePath+fileName, false);
167 // load a set of file synchronously
168 void CBackupServiceInterface::syncLoadFiles(const std::vector<std::string>& fileNames, NLMISC::CSmartPtr<IBackupFileReceiveCallback> cb)
170 H_AUTO(BSIF_RequestFile);
172 // for each file, send a request request to the BS
173 for (uint i=0; i<fileNames.size(); ++i)
175 const string &fileName = fileNames[i];
176 // check that the file name is valid
177 BOMB_IF(!FileNameValidator.checkFileName(fileName),"Failed to send sync load file "+CSString(fileName).quote()+" due to invalid characters in file name",continue);
179 // store away the callback for this action and retrieve the associated request id
180 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushFileCallback(cb, this);
182 // dispatch the request (not blocking)
183 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchSyncLoadFile(_Name, requestId, _RemotePath+fileName, true);
186 // block until all files are loaded
187 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->terminateSyncLoads();
191 void CBackupServiceInterface::sendFile(CBackupMsgSaveFile& msg, NLMISC::CSmartPtr<IBackupGenericAckCallback> cb)
193 H_AUTO(BSIF_SendFile);
195 // check that the file name is valid
196 BOMB_IF(!FileNameValidator.checkFileName(msg.FileName),"Failed to send save file request "+CSString(msg.FileName).quote()+" due to invalid characters in file name",return);
198 // if there's no BS connected then complain and queue the file for saving later
199 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
201 BOMB( ("Failed to send file "+CSString(msg.FileName).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
204 // create a log message...
205 // nldebug("BSIF: sendFile(): FileName: \"%s\", Size: %d bytes",msg.FileName.c_str(),msg.DataMsg.length());
207 // store away the callback for this action and retrieve the associated request id
208 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushGenericAckCallback(cb, this);
210 // dispatch the request
211 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchSendFile(_Name,requestId,msg);
214 // Append a data stream to a file
215 void CBackupServiceInterface::append(CBackupMsgSaveFile& msg, NLMISC::CSmartPtr<IBackupGenericAckCallback> cb)
217 H_AUTO(BSIF_AppendFile);
219 // check that the file name is valid
220 BOMB_IF(!FileNameValidator.checkFileName(msg.FileName),"Failed to send append request "+CSString(msg.FileName).quote()+" due to invalid characters in file name",return);
222 // if there's no BS connected then complain and queue the file for saving later
223 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
225 BOMB( ("Failed to append to file "+CSString(msg.FileName).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
228 // create a log message...
229 // nldebug("BSIF: append(): FileName: \"%s\", Size: %d bytes",msg.FileName.c_str(),msg.DataMsg.length());
231 // store away the callback for this action and retrieve the associated request id
232 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushGenericAckCallback(cb, this);
234 // dispatch the request
235 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchAppendData(_Name,requestId,msg);
238 // Append a line to a file
239 void CBackupServiceInterface::append(const std::string& filename, const std::string& line, NLMISC::CSmartPtr<IBackupGenericAckCallback> cb)
241 H_AUTO(BSIF_AppendText);
243 // check that the file name is valid
244 BOMB_IF(!FileNameValidator.checkFileName(filename),"Failed to send append file request "+CSString(filename).quote()+" due to invalid characters in file name",return);
246 // if there's no BS connected then complain and queue the file for saving later
247 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
249 BOMB( ("Failed to append to file "+CSString(filename).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
253 // create a log message...
254 // nldebug("BSIF: append(): FileName: %s, %s",filename.quote().c_str(),line.quote().c_str());
256 // store away the callback for this action and retrieve the associated request id
257 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushGenericAckCallback(cb, this);
259 // dispatch the request
260 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchAppendText(_Name,requestId,_RemotePath+filename,line);
263 // request for a file to be deleted (WARNING: no archiving of the file)
264 void CBackupServiceInterface::deleteFile(const std::string& fileName, bool keepBackupOfFile, NLMISC::CSmartPtr<IBackupGenericAckCallback> cb)
266 H_AUTO(BSIF_DeleteFile);
268 // check that the file name is valid
269 BOMB_IF(!FileNameValidator.checkFileName(fileName),"Failed to send delete request "+CSString(fileName).quote()+" due to invalid characters in file name",return);
271 // if there's no BS connected then complain and queue the file for deleting later
272 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
274 BOMB( ("Failed to delete file "+CSString(fileName).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
277 // create a log message...
278 // nldebug("BSIF: deleteFile(): FileName: \"%s\", KeepBackup: %s",fileName.c_str(), keepBackupOfFile ? "true" : "false");
280 // store away the callback for this action and retrieve the associated request id
281 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushGenericAckCallback(cb, this);
283 // dispatch the request
284 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchDeleteFile(_Name,requestId,_RemotePath+fileName,keepBackupOfFile);
288 // request BS sends me files matching the given file classes
289 void CBackupServiceInterface::requestFileClass(const std::string& directory, const std::vector<CBackupFileClass>& classes, NLMISC::CSmartPtr<IBackupFileClassReceiveCallback> cb)
291 H_AUTO(BSIF_RequestFileClass);
293 // if there's no BS connected then complain and queue the file for retrieving later
294 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
296 BOMB( ("Failed to request file class in directory "+CSString(directory).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
299 // create a log message...
300 // NLMISC::CSString patterns;
301 // for (uint32 j=0;j<classes.size();++j)
302 // {
303 // for (uint32 i=0;i<classes[j].Patterns.size();++i)
304 // patterns+= classes[j].Patterns[i]+';';
305 // patterns= patterns.rightCrop(1)+'|';
306 // }
307 // nldebug("BSIF: requestFileClass(): Directory: \"%s\", Pattern: \"%s\", RequestId: %d",directory.c_str(),patterns.rightCrop(1).c_str(),msg.RequestId);
309 // store away the callback for this action and retrieve the associated request id
310 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushFileClassCallback(cb, this);
312 // dispatch the request
313 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchRequestFileClass(_Name,requestId,_RemotePath+directory,classes);
316 // request BS sends me files matching the given file classes
317 void CBackupServiceInterface::syncLoadFileClass(const std::string& directory, const std::vector<CBackupFileClass>& classes, NLMISC::CSmartPtr<IBackupFileClassReceiveCallback> cb)
319 H_AUTO(BSIF_syncLoadFileClass);
321 // if there's no BS connected then complain and queue the file for retrieving later
322 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
324 BOMB( ("Failed to request file class in directory "+CSString(directory).quote()+" because the backup services are all down!").c_str() , nlSleep(5000); exit(0) );
327 // create a log message...
328 // NLMISC::CSString patterns;
329 // for (uint32 j=0;j<classes.size();++j)
330 // {
331 // for (uint32 i=0;i<classes[j].Patterns.size();++i)
332 // patterns+= classes[j].Patterns[i]+';';
333 // patterns= patterns.rightCrop(1)+'|';
334 // }
335 // nldebug("BSIF: requestFileClass(): Directory: \"%s\", Pattern: \"%s\", RequestId: %d",directory.c_str(),patterns.rightCrop(1).c_str(),msg.RequestId);
337 // store away the callback for this action and retrieve the associated request id
338 uint32 requestId= CBackupInterfaceSingleton::getInstance()->pushFileClassCallback(cb, this);
340 // dispatch the request
341 CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->dispatchSyncLoadFileClass(_Name,requestId,_RemotePath+directory,classes);
345 NLMISC::TTime CBackupServiceInterface::getLastAckTime() const
347 // if there's no BS connected then give up
348 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
350 return 0;
353 // delegate...
354 return CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->getLastAckTime();
357 NLMISC::TTime CBackupServiceInterface::getLastAckDelay() const
359 // if there's no BS connected then give up
360 if (!CBackupInterfaceSingleton::getInstance()->isConnected())
362 // return 64 bit signed maxint (a very big number)
363 return uint64(sint64(-1))>>1;
366 // delegate...
367 return CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->getLastAckDelay();