// 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 .
#include "nel/misc/types_nl.h"
#include "nel/misc/command.h"
#include "nel/misc/path.h"
#include "nel/misc/file.h"
#include "nel/misc/md5.h"
#include "backup_service.h"
#include "game_share/persistent_data.h"
using namespace std;
using namespace NLMISC;
using namespace NLNET;
CDirectoryRateStat DirStats;
extern CVariable SaveShardRoot;
NLMISC_COMMAND(displayFileStats, "display file read/write stats for the last minute", "")
{
DirStats.display(log);
return true;
}
NLMISC_DYNVARIABLE(string, FileReadStat, "mean file read in bytes per seconds for the last minute")
{
if (get)
*pointer = bytesToHumanReadable(DirStats.getMeanReadRate());
return;
}
NLMISC_DYNVARIABLE(string, FileWriteStat, "mean file write in bytes per seconds for the last minute")
{
if (get)
*pointer = bytesToHumanReadable(DirStats.getMeanWriteRate());
return;
}
NLMISC_COMMAND ( resumeBackupService, "reset stall mode for resume backup process", "no params")
{
CBackupService::getInstance()->setStall( false );
CMessage msgOut("RESUME_SHARD");
CUnifiedNetwork::getInstance()->send("EGS", msgOut );
return true;
}
NLMISC_COMMAND ( stallBackupService, "set backup service un stall mode", "no params")
{
CBackupService::getInstance()->stallShard( std::string("Stalled by admin command") );
return true;
}
NLMISC_COMMAND ( dumpCharacterFile, "dump the content of the save file for a character. Invoke with no param to display a list of available shardId.", " [|listTokens]")
{
if (args.size() == 0)
{
// just output the list of available shard id
vector shards;
CPath::getPathContent(SaveShardRoot, false, true, false, shards);
log.displayNL("Listing %u available shard id in path '%s':", shards.size(), SaveShardRoot.c_str());
for (uint i=0; i tokens;
string::size_type pos = 0;
pos = xml.find("<");
while (pos != string::npos)
{
++pos;
string token;
while (xml[pos] != ' ' && xml[pos] != '\t' && xml[pos] != '/' && xml[pos] != '>')
token += xml[pos++];
tokens.insert(token);
pos = xml.find("<", pos);
}
// output the result
log.displayNL("Displaying %u tokens in characters file :", tokens.size());
string line;
set::iterator first(tokens.begin()), last(tokens.end());
for (; first != last; ++first)
{
line += *first+" ";
if (line.size() > 80)
{
log.displayNL("%s", line.c_str());
line = "";
}
}
if (!line.empty())
log.displayNL("%s", line.c_str());
log.displayNL("End of token list");
return true;
}
// ok, now display the data
vector lines;
explode(xml, string("\n"), lines);
bool logOn = !useFilter;
for (uint i=0; i") != string::npos)
))
logOn = false;
}
}
return true;
}
static char base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static uint8 base64Revert[256];
static bool base64Init = false;
static void base64Encode(const std::vector& buffer, std::string& encoded)
{
encoded.clear();
encoded.reserve(buffer.size()*4/3+3);
uint i;
for (i=0; i> 18) & 0x3f];
if (i < buffer.size())
{
b |= (buffer[i++] << 8);
encoded += base64Table[(b >> 12) & 0x3f];
if (i < buffer.size())
{
b |= buffer[i++];
encoded += base64Table[(b >> 6) & 0x3f];
encoded += base64Table[b & 0x3f];
}
else
{
encoded += base64Table[(b >> 6) & 0x3f];
encoded += '=';
}
}
else
{
encoded += base64Table[(b >> 12) & 0x3f];
encoded += '=';
encoded += '=';
}
}
}
static void base64Decode(std::vector& buffer, const std::string& encoded)
{
uint i;
if (!base64Init)
{
for (i=0; i<256; ++i)
base64Revert[i] = 255;
for (i=0; i leave
if (encoded[i] == '=')
break;
// unknown char? -> skip
if (base64Revert[(uint8)encoded[i]] == 255)
continue;
bitbuffer = (bitbuffer << 6) | base64Revert[(uint8)encoded[i]];
inbits += 6;
if (inbits >= 8)
{
buffer.push_back((uint8)(bitbuffer >> (inbits-8)));
inbits -= 8;
}
}
}
NLMISC_COMMAND ( stallShard, "stall backup service and connected shards (via EGS)", "")
{
CBackupService::getInstance()->FileManager.setMode(CFileAccessManager::Stalled, "MANUAL BS STALL");
return true;
}
NLMISC_COMMAND ( resumeShard, "resume backup service and connected shards (via EGS)", "")
{
CBackupService::getInstance()->FileManager.setMode(CFileAccessManager::Normal, "MANUAL BS RESUME");
return true;
}
NLMISC_COMMAND ( removeFileAccess, "remove a file access from file access manager (see displayFileAccesses)", "")
{
if (args.size() != 1)
return false;
IFileAccess* access = NULL;
sscanf(args[0].c_str(), "%p", &access);
CBackupService::getInstance()->FileManager.removeFileAccess(access);
return true;
}
NLMISC_COMMAND ( displayFileAccesses, "display stacked file accesses", "")
{
CBackupService::getInstance()->FileManager.displayFileAccesses(log);
return true;
}
NLMISC_COMMAND (getFileBase64Content, "dump file content in Base64 encoded form", "")
{
if (args.size() != 1)
{
log.displayRawNL("file INVALIDFILE lines 0 size 0");
return true;
}
CIFile f;
if (!CFile::fileExists(args[0]) || CFile::getFileSize(args[0]) == 0 || !f.open(args[0]))
{
log.displayRawNL("file %s lines 0 size 0", args[0].c_str());
return true;
}
uint filesize = f.getFileSize();
std::vector buffer;
buffer.resize(filesize);
f.serialBuffer(&(buffer[0]), filesize);
f.close();
CHashKeyMD5 key = getMD5(&(buffer[0]), filesize);
std::string encoded;
base64Encode(buffer, encoded);
uint numcharperline = 224;
uint numlines = ((uint)encoded.size()+numcharperline-1)/numcharperline;
log.displayRawNL("file %s lines %d size %d haskey %s", args[0].c_str(), numlines, filesize, key.toString().c_str());
uint cpos = 0;
while (cpos < encoded.size())
{
std::string line = encoded.substr(cpos, numcharperline);
log.displayRawNL("%s", line.c_str());
cpos += numcharperline;
}
return true;
}
NLMISC_COMMAND (putFileBase64Content, "fill file with content in Base64 encoded form", " ")
{
if (args.size() < 2)
return false;
COFile f;
if (!f.open(args[0]))
return false;
std::string encoded;
uint i;
for (i=1; i buffer;
base64Decode(buffer, encoded);
f.serialBuffer(&(buffer[0]), (uint)buffer.size());
f.close();
return true;
}