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 //-------------------------------------------------------------------------------------------------
19 //-------------------------------------------------------------------------------------------------
22 #include "_backup_service_interface_singleton.h"
26 //-------------------------------------------------------------------------------------------------
28 //-------------------------------------------------------------------------------------------------
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
43 // setup the set of valid characters for the file name
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)
71 nlwarning("FileNameValidator: refusing character '%c' (%u) in file name: %s",fileName
[i
],fileName
[i
],fileName
.c_str());
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
101 const char *CBackupMsgSaveFile::_TypesStr
[CBackupMsgSaveFile::NbTypes
] =
110 //-------------------------------------------------------------------------------------------------
111 // methods CBackupServiceInterface
112 //-------------------------------------------------------------------------------------------------
114 void CBackupServiceInterface::init(const std::string
& 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)
303 // for (uint32 i=0;i<classes[j].Patterns.size();++i)
304 // patterns+= classes[j].Patterns[i]+';';
305 // patterns= patterns.rightCrop(1)+'|';
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)
331 // for (uint32 i=0;i<classes[j].Patterns.size();++i)
332 // patterns+= classes[j].Patterns[i]+';';
333 // patterns= patterns.rightCrop(1)+'|';
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())
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;
367 return CBackupInterfaceSingleton::getInstance()->getBSIImplementation()->getLastAckDelay();