// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
#ifndef FILE_RECEIVER_H
#define FILE_RECEIVER_H
//-----------------------------------------------------------------------------
// includes
//-----------------------------------------------------------------------------
// game share
#include "game_share/deployment_configuration.h"
// local
#include "module_admin_itf.h"
#include "administered_module.h"
//-----------------------------------------------------------------------------
// namespace PATCHMAN
//-----------------------------------------------------------------------------
namespace PATCHMAN
{
//-----------------------------------------------------------------------------
// class CFileReceiver
//-----------------------------------------------------------------------------
class CFileReceiver:
public PATCHMAN::CFileReceiverSkel
{
public:
// stuff for the derived class to hook up ---------------------------------
// ctor & init
CFileReceiver();
void init(NLNET::IModule* parent,const std::string& fileSpec="*/*");
// CModuleBase specialisation implementation
void onModuleUp(NLNET::IModuleProxy *module);
void onModuleDown(NLNET::IModuleProxy *module);
void onModuleUpdate();
const std::string &getModuleManifest() const;
public:
// handy types ------------------------------------------------------------
typedef NLNET::IModuleProxy* TProxyPtr;
typedef std::map TFileRequestMatches;
// remaining public interface ---------------------------------------------
// send off a request for a file... the request will come back via the callbacks below
void requestFile(const std::string &fileName);
// lookup info on a particular file
bool getSingleFileInfo(const std::string &fileName,SFileInfo& fileInfo) const;
// lookup info on all files matching a given file spec
void getFileInfo(const std::string &fileSpec,TFileInfoVector& result) const;
// status info accessors
bool haveIdleProxies() const;
// a handy status dump method
void dump(NLMISC::CLog& log) const;
// a handy method to dump the set of files matching a given spec to the given log
void dumpFileInfo(const std::string &fileSpec,NLMISC::CLog& log) const;
// overloadable callback methods ------------------------------------------
// The following method is called to allow user to invalidate matches for
// a file request that they have made
// entries can simply be erased from the requestMatches container
// it is valid for the container to be empty on exit
virtual void cbValidateRequestMatches(TFileRequestMatches& requestMatches) {}
// the following callback is called after a file has been successfully downloaded
virtual void cbFileDownloadSuccess(const NLMISC::CSString& fileName,const NLMISC::CMemStream& data) {}
// the following callback is called after a file download has failed
// note that the system will not try re-downloading from the same emitter
// unless the emitter sends us a file update at a later date re-iterating
// the valisdity of their file (we assume the file has been deleted)
// if another emitter claims to be able to deliver the file then the
// system will retry automatically (no need for an extra retry request
// to be generated here)
virtual void cbRetryAfterFileDownloadFailure(const NLMISC::CSString& fileName) {}
// the following callback is called after a new information record is recieved for a file
// the information change may be either addition, deletion or info change for the given file from a given proxy
// this can be the addition of an extra proxy providing the same info as other existing proxies
virtual void cbFileInfoChange(const NLMISC::CSString& fileName) {}
protected:
// protected methods - for treating incoming messages ---------------------
void setupSubscriptions(NLNET::IModuleProxy *sender);
void cbFileInfo(NLNET::IModuleProxy *sender, const TFileInfoVector &files);
void cbFileData(NLNET::IModuleProxy *sender, const std::string &fileName, uint32 startOffset, const NLNET::TBinBuffer &data);
void cbFileDataFailure(NLNET::IModuleProxy *sender, const std::string &fileName);
private:
// private data -----------------------------------------------------------
NLNET::IModule* _Parent;
NLMISC::CSString _FileSpec;
CAdministeredModuleWrapper _AdministeredModuleWrapper;
// some handy data types
struct SFileRequest: public NLMISC::CRefCount
{
NLMISC::CSString FileName;
NLMISC::CSString DataSoFar;
TProxyPtr Emitter;
uint32 ExpectedFileSize;
uint32 TotalDataRequested;
SFileRequest(): Emitter(NULL), ExpectedFileSize(0), TotalDataRequested(0) {}
};
typedef NLMISC::CSmartPtr TFileRequestPtr;
typedef std::list TFileRequests;
// queued file requests
TFileRequests _FileRequests; // vector of files that need to be downloaded from RE module
// connected proxies
struct SProxyInfo
{
TProxyPtr Proxy; // the proxy id
TFileInfoMap FileInfo; // the set of files reported by the proxy
TFileRequestPtr CurrentRequest; // the request that the proxy is treating right now
};
typedef std::map TProxies;
TProxies _Proxies;
// private methods --------------------------------------------------------
void _log(const NLMISC::CSString& msg) const;
void _logError(const NLMISC::CSString& msg) const;
void _logState(const NLMISC::CSString& state) const;
void _downloadLog(const NLMISC::CSString& fileName,uint32 bytesSoFar, uint32 bytesExpected) const;
void _clearDownloadLog(const NLMISC::CSString& fileName) const;
void _requestFile(TFileRequestPtr theRequest);
void _treatBrokenFileRequest(TFileRequestPtr theRequest);
void _dealWithReceivedFile(TProxyPtr sender,TFileRequestPtr theRequest,const NLNET::TBinBuffer& data);
void _lookForNewJob(SProxyInfo& theProxy);
};
} // end of namespace
//-----------------------------------------------------------------------------
#endif