// 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 .
//-----------------------------------------------------------------------------
// includes
//-----------------------------------------------------------------------------
// game share
#include "game_share/utils.h"
#include "game_share/file_description_container.h"
// local
#include "repository.h"
//-------------------------------------------------------------------------------------------------
// namespaces
//-------------------------------------------------------------------------------------------------
using namespace std;
using namespace NLMISC;
//-------------------------------------------------------------------------------------------------
// constants & utilities
//-------------------------------------------------------------------------------------------------
NLMISC::CSString getRepositoryIndexFileName(const NLMISC::CSString& repositoryName)
{
return "repository_"+repositoryName+".idx";
}
//-----------------------------------------------------------------------------
// methods CRepository
//-----------------------------------------------------------------------------
bool CRepository::init(const NLMISC::CSString& name,const NLMISC::CSString& directory,const NLMISC::CSString& filespec,const NLMISC::CSString& lockFilespecs)
{
_Name= name.unquoteIfQuoted();
_TargetDirectory= NLMISC::CPath::standardizePath(directory.unquoteIfQuoted());
filespec.splitBySeparator('|',_Filespec);
if (_Filespec.empty()) _Filespec.push_back("*");
lockFilespecs.splitBySeparator('|',_LockFilespecs);
nldebug("Repository %s: %s",_Name.c_str(),_TargetDirectory.c_str());
nldebug("- filespec: %s",NLMISC::CSString().join(_Filespec,';').c_str());
nldebug("- avoid filespec: %s",NLMISC::CSString().join(_LockFilespecs,';').c_str());
// check whether the target directory exists
if (!NLMISC::CFile::isDirectory(_TargetDirectory))
{
// the directory didn't exist so try to create it...
NLMISC::CFile::createDirectoryTree(_TargetDirectory);
DROP_IF(!NLMISC::CFile::isDirectory(_TargetDirectory),"Failed to create target directory: \""+_TargetDirectory+"\"",return false);
}
// if we have a saved file that gives timestamp / size / checksum correspondances then load it
NLMISC::CSString index;
if (NLMISC::CFile::fileExists(_TargetDirectory+getRepositoryIndexFileName(_Name)))
{
index.readFromFile(_TargetDirectory+getRepositoryIndexFileName(_Name));
}
if (!index.empty())
{
nlinfo("GUSREP_Reading index file: %s",(_TargetDirectory+getRepositoryIndexFileName(_Name)).c_str());
NLMISC::CVectorSString lines;
index.splitLines(lines);
for (uint32 i=0;isecond.FileSize= NLMISC::CFile::getFileSize(_TargetDirectory+fileName);
fileIt->second.FileTime= NLMISC::CFile::getFileModificationDate(_TargetDirectory+fileName);
fileIt->second.Checksum= NLMISC::getMD5(_TargetDirectory+fileName);
}
void CRepository::addFileStub(NLMISC::CSString fileName)
{
nldebug(("Adding repository stub for file: '"+fileName+"'").c_str());
// if the name of the file that has changed contains the target directory name then crop it
if (fileName.left(_TargetDirectory.size())==_TargetDirectory)
{
fileName=fileName.leftCrop(_TargetDirectory.size());
}
// make sure the file didn't already exist in the map
TFiles::iterator fileIt= _Files.end();
fileIt=_Files.find(fileName);
BOMB_IF(fileIt!= _Files.end(),"Failed to add stub for file that already exists: '"+fileName+"'",return);
// create the new map entry and set properties to 0
_Files[fileName].FileSize= 0;
_Files[fileName].FileTime= 0;
}
uint32 CRepository::update()
{
// setup a variable to hold our return value
uint32 result= 0;
// make sure there are no 'avoid' files about
CFileDescriptionContainer fdc;
for (uint32 i=0;i<_LockFilespecs.size();++i)
{
fdc.addFileSpec(_LockFilespecs[i]);
}
if (!fdc.empty())
{
// some avoid files have been found so build a list of them
NLMISC::CSString s;
for (uint32 i=0;isecond.FileSize,it->second.FileTime,it->second.Checksum.toString().c_str(),it->first.c_str());
}
fileIndex.writeToFile(_TargetDirectory+getRepositoryIndexFileName(_Name));
}
uint32 CRepository::size() const
{
return _Files.size();
}
const CRepository::CFilesMapEntry& CRepository::operator[](const NLMISC::CSString& key) const
{
return const_cast(this)->_Files[key];
}
CRepository::iterator CRepository::find(const NLMISC::CSString& key)
{
return _Files.find(key);
}
CRepository::const_iterator CRepository::find(const NLMISC::CSString& key) const
{
return _Files.find(key);
}
CRepository::iterator CRepository::begin()
{
return _Files.begin();
}
CRepository::const_iterator CRepository::begin() const
{
return _Files.begin();
}
CRepository::iterator CRepository::end()
{
return _Files.end();
}
CRepository::const_iterator CRepository::end() const
{
return _Files.end();
}
void CRepository::fillShortList(std::vector &files) const
{
// start by clearing out any previous contents in the files vector
files.clear();
// iterate over the repository adding files to the files vector
const_iterator it= _Files.begin();
const_iterator itEnd= _Files.end();
for (;it!=itEnd;++it)
{
// append a new entry to the vector
vectAppend(files);
// setup data for the (new) back vector entry
files.back().setFileName(it->first);
files.back().setChecksum(it->second.Checksum);
nlinfo("sending info on file: '%s'",files.back().getFileName().c_str());
}
}