// 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; }