New upstream version 8.1.0
This commit is contained in:
273
fsck/source/toolkit/DatabaseTk.cpp
Normal file
273
fsck/source/toolkit/DatabaseTk.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
#include "DatabaseTk.h"
|
||||
|
||||
#include <common/app/log/LogContext.h>
|
||||
#include <common/storage/striping/Raid0Pattern.h>
|
||||
#include <common/toolkit/FsckTk.h>
|
||||
#include <common/toolkit/StringTk.h>
|
||||
#include <database/FsckDB.h>
|
||||
#include <database/FsckDBTable.h>
|
||||
#include <common/storage/Path.h>
|
||||
#include <common/toolkit/StorageTk.h>
|
||||
|
||||
DatabaseTk::DatabaseTk()
|
||||
{
|
||||
}
|
||||
|
||||
DatabaseTk::~DatabaseTk()
|
||||
{
|
||||
}
|
||||
|
||||
FsckDirEntry DatabaseTk::createDummyFsckDirEntry(FsckDirEntryType entryType)
|
||||
{
|
||||
FsckDirEntryList list;
|
||||
createDummyFsckDirEntries(7, 1, &list, entryType);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckDirEntries(uint amount, FsckDirEntryList* outList,
|
||||
FsckDirEntryType entryType)
|
||||
{
|
||||
createDummyFsckDirEntries(0,amount, outList, entryType);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckDirEntries(uint from, uint amount, FsckDirEntryList* outList,
|
||||
FsckDirEntryType entryType)
|
||||
{
|
||||
for ( uint i = from; i < (from+amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
|
||||
std::string id = index + "-1-1";
|
||||
std::string name = "dentryName" + index;
|
||||
std::string parentID = index + "-2-1";
|
||||
NumNodeID entryOwnerNodeID(i + 1000);
|
||||
NumNodeID inodeOwnerNodeID(i + 2000);
|
||||
NumNodeID saveNodeID(i + 3000);
|
||||
int saveDevice = i;
|
||||
uint64_t saveInode = i;
|
||||
|
||||
FsckDirEntry dentry(id, name, parentID, entryOwnerNodeID, inodeOwnerNodeID, entryType, true,
|
||||
saveNodeID, saveDevice, saveInode, false);
|
||||
|
||||
outList->push_back(dentry);
|
||||
}
|
||||
}
|
||||
|
||||
FsckFileInode DatabaseTk::createDummyFsckFileInode()
|
||||
{
|
||||
FsckFileInodeList list;
|
||||
createDummyFsckFileInodes(7, 1, &list);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckFileInodes(uint amount, FsckFileInodeList* outList)
|
||||
{
|
||||
createDummyFsckFileInodes(0,amount,outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckFileInodes(uint from, uint amount, FsckFileInodeList* outList)
|
||||
{
|
||||
for ( uint i = from; i < (from + amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
UInt16Vector targetIDs;
|
||||
while (targetIDs.size() < i)
|
||||
targetIDs.push_back(i + 1000 * (targetIDs.size() + 1) );
|
||||
Raid0Pattern stripePatternIn(1024, targetIDs);
|
||||
|
||||
std::string id = index + "-1-1";
|
||||
std::string parentDirID = index + "-2-1";
|
||||
NumNodeID parentNodeID(i + 1000);
|
||||
|
||||
unsigned userID = 1000;
|
||||
unsigned groupID = 1000;
|
||||
|
||||
uint64_t usedBlocks = 0;
|
||||
int64_t fileSize = usedBlocks*512;
|
||||
unsigned numHardLinks = 1;
|
||||
|
||||
PathInfo pathInfo(userID, parentDirID, PATHINFO_FEATURE_ORIG);
|
||||
|
||||
FsckStripePatternType stripePatternType = FsckTk::stripePatternToFsckStripePattern(
|
||||
&stripePatternIn);
|
||||
unsigned chunkSize = 524288;
|
||||
|
||||
NumNodeID saveNodeID(i + 2000);
|
||||
|
||||
FsckFileInode fileInode(id, parentDirID, parentNodeID, pathInfo, userID, groupID, fileSize,
|
||||
numHardLinks, usedBlocks, targetIDs, stripePatternType, chunkSize, saveNodeID,
|
||||
1000 + i, 42, true, false, true, false);
|
||||
|
||||
outList->push_back(fileInode);
|
||||
}
|
||||
}
|
||||
|
||||
FsckDirInode DatabaseTk::createDummyFsckDirInode()
|
||||
{
|
||||
FsckDirInodeList list;
|
||||
createDummyFsckDirInodes(7, 1, &list);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckDirInodes(uint amount, FsckDirInodeList* outList)
|
||||
{
|
||||
createDummyFsckDirInodes(0, amount, outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckDirInodes(uint from, uint amount, FsckDirInodeList* outList)
|
||||
{
|
||||
for ( uint i = from; i < (from + amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
UInt16Vector targetIDs;
|
||||
Raid0Pattern stripePatternIn(1024, targetIDs);
|
||||
|
||||
std::string id = index + "-1-1";
|
||||
std::string parentDirID = index + "-2-1";
|
||||
NumNodeID parentNodeID(i + 1000);
|
||||
NumNodeID ownerNodeID(i + 2000);
|
||||
|
||||
int64_t size = 10;
|
||||
unsigned numHardLinks = 12;
|
||||
|
||||
FsckStripePatternType stripePatternType = FsckTk::stripePatternToFsckStripePattern(
|
||||
&stripePatternIn);
|
||||
NumNodeID saveNodeID(i + 3000);
|
||||
|
||||
FsckDirInode dirInode(id, parentDirID, parentNodeID, ownerNodeID, size, numHardLinks,
|
||||
targetIDs, stripePatternType, saveNodeID, false, true, false);
|
||||
outList->push_back(dirInode);
|
||||
}
|
||||
}
|
||||
|
||||
FsckChunk DatabaseTk::createDummyFsckChunk()
|
||||
{
|
||||
FsckChunkList list;
|
||||
createDummyFsckChunks(7, 1, &list);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckChunks(uint amount, FsckChunkList* outList)
|
||||
{
|
||||
createDummyFsckChunks(amount, 1, outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckChunks(uint amount, uint numTargets, FsckChunkList* outList)
|
||||
{
|
||||
createDummyFsckChunks(0, amount, numTargets, outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckChunks(uint from, uint amount, uint numTargets,
|
||||
FsckChunkList* outList)
|
||||
{
|
||||
for ( uint i = from; i < (from + amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
|
||||
for ( uint j = 0; j < numTargets; j++ )
|
||||
{
|
||||
std::string id = index + "-1-1";
|
||||
uint16_t targetID = j;
|
||||
|
||||
PathInfo pathInfo(0, META_ROOTDIR_ID_STR, PATHINFO_FEATURE_ORIG);
|
||||
Path chunkDirPath; // ignored!
|
||||
std::string chunkFilePathStr;
|
||||
StorageTk::getChunkDirChunkFilePath(&pathInfo, id, true, chunkDirPath,
|
||||
chunkFilePathStr);
|
||||
Path savedPath(chunkFilePathStr);
|
||||
|
||||
uint64_t usedBlocks = 300;
|
||||
int64_t fileSize = usedBlocks*512;
|
||||
|
||||
FsckChunk chunk(id, targetID, savedPath, fileSize, usedBlocks, 0, 0, 0, 0, 0);
|
||||
outList->push_back(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FsckContDir DatabaseTk::createDummyFsckContDir()
|
||||
{
|
||||
FsckContDirList list;
|
||||
createDummyFsckContDirs(7, 1, &list);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckContDirs(uint amount, FsckContDirList* outList)
|
||||
{
|
||||
createDummyFsckContDirs(0, amount, outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckContDirs(uint from, uint amount, FsckContDirList* outList)
|
||||
{
|
||||
for ( uint i = from; i < (from + amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
|
||||
std::string id = index + "-1-1";
|
||||
NumNodeID saveNodeID(i);
|
||||
|
||||
FsckContDir contDir(id, saveNodeID, false);
|
||||
outList->push_back(contDir);
|
||||
}
|
||||
}
|
||||
|
||||
FsckFsID DatabaseTk::createDummyFsckFsID()
|
||||
{
|
||||
FsckFsIDList list;
|
||||
createDummyFsckFsIDs(7, 1, &list);
|
||||
return list.front();
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckFsIDs(uint amount, FsckFsIDList* outList)
|
||||
{
|
||||
createDummyFsckFsIDs(0, amount, outList);
|
||||
}
|
||||
|
||||
void DatabaseTk::createDummyFsckFsIDs(uint from, uint amount, FsckFsIDList* outList)
|
||||
{
|
||||
for ( uint i = from; i < (from + amount); i++ )
|
||||
{
|
||||
std::string index = StringTk::uintToHexStr(i);
|
||||
|
||||
std::string id = index + "-1-1";
|
||||
std::string parentDirID = index + "-2-1";
|
||||
NumNodeID saveNodeID(i);
|
||||
int saveDevice = i;
|
||||
uint64_t saveInode = i;
|
||||
|
||||
FsckFsID fsID(id, parentDirID, saveNodeID, saveDevice, saveInode, false);
|
||||
outList->push_back(fsID);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DatabaseTk::calculateExpectedChunkPath(std::string entryID, unsigned origParentUID,
|
||||
std::string origParentEntryID, int pathInfoFlags)
|
||||
{
|
||||
std::string resStr;
|
||||
|
||||
bool hasOrigFeature;
|
||||
hasOrigFeature = pathInfoFlags == PATHINFO_FEATURE_ORIG;
|
||||
|
||||
PathInfo pathInfo(origParentUID, origParentEntryID, pathInfoFlags);
|
||||
Path chunkDirPath;
|
||||
std::string chunkFilePath;
|
||||
StorageTk::getChunkDirChunkFilePath(&pathInfo, entryID, hasOrigFeature, chunkDirPath,
|
||||
chunkFilePath);
|
||||
|
||||
if (hasOrigFeature) // we can use the Path chunkDirPath
|
||||
resStr = chunkDirPath.str();
|
||||
else
|
||||
{
|
||||
/* chunk in old format => Path chunkDirPath is not set in getChunkDirChunkFilePath(),
|
||||
* so it is a bit more tricky */
|
||||
|
||||
// we need to strip the filename itself (including the '/')
|
||||
size_t startPos = 0;
|
||||
size_t len = chunkFilePath.find_last_of('/');
|
||||
|
||||
// generate a substring as result
|
||||
resStr = chunkFilePath.substr(startPos, len);
|
||||
}
|
||||
|
||||
return resStr;
|
||||
}
|
||||
62
fsck/source/toolkit/DatabaseTk.h
Normal file
62
fsck/source/toolkit/DatabaseTk.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef DATABASETK_H_
|
||||
#define DATABASETK_H_
|
||||
|
||||
#include <common/fsck/FsckChunk.h>
|
||||
#include <common/fsck/FsckContDir.h>
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <common/fsck/FsckDirInode.h>
|
||||
#include <common/fsck/FsckFileInode.h>
|
||||
#include <common/fsck/FsckFsID.h>
|
||||
#include <common/fsck/FsckModificationEvent.h>
|
||||
#include <common/fsck/FsckTargetID.h>
|
||||
|
||||
#include <database/Chunk.h>
|
||||
#include <database/ContDir.h>
|
||||
#include <database/DirEntry.h>
|
||||
#include <database/DirInode.h>
|
||||
#include <database/FileInode.h>
|
||||
#include <database/FsID.h>
|
||||
|
||||
class FsckDB;
|
||||
|
||||
class DatabaseTk
|
||||
{
|
||||
public:
|
||||
DatabaseTk();
|
||||
virtual ~DatabaseTk();
|
||||
|
||||
static FsckDirEntry createDummyFsckDirEntry(
|
||||
FsckDirEntryType entryType = FsckDirEntryType_REGULARFILE);
|
||||
static void createDummyFsckDirEntries(uint amount, FsckDirEntryList* outList,
|
||||
FsckDirEntryType entryType = FsckDirEntryType_REGULARFILE);
|
||||
static void createDummyFsckDirEntries(uint from, uint amount, FsckDirEntryList* outList,
|
||||
FsckDirEntryType entryType = FsckDirEntryType_REGULARFILE);
|
||||
|
||||
|
||||
static FsckFileInode createDummyFsckFileInode();
|
||||
static void createDummyFsckFileInodes(uint amount, FsckFileInodeList* outList);
|
||||
static void createDummyFsckFileInodes(uint from, uint amount, FsckFileInodeList* outList);
|
||||
|
||||
static FsckDirInode createDummyFsckDirInode();
|
||||
static void createDummyFsckDirInodes(uint amount, FsckDirInodeList* outList);
|
||||
static void createDummyFsckDirInodes(uint from, uint amount, FsckDirInodeList* outList);
|
||||
|
||||
static FsckChunk createDummyFsckChunk();
|
||||
static void createDummyFsckChunks(uint amount, FsckChunkList* outList);
|
||||
static void createDummyFsckChunks(uint amount, uint numTargets, FsckChunkList* outList);
|
||||
static void createDummyFsckChunks(uint from, uint amount, uint numTargets,
|
||||
FsckChunkList* outList);
|
||||
|
||||
static FsckContDir createDummyFsckContDir();
|
||||
static void createDummyFsckContDirs(uint amount, FsckContDirList* outList);
|
||||
static void createDummyFsckContDirs(uint from, uint amount, FsckContDirList* outList);
|
||||
|
||||
static FsckFsID createDummyFsckFsID();
|
||||
static void createDummyFsckFsIDs(uint amount, FsckFsIDList* outList);
|
||||
static void createDummyFsckFsIDs(uint from, uint amount, FsckFsIDList* outList);
|
||||
|
||||
static std::string calculateExpectedChunkPath(std::string entryID, unsigned origParentUID,
|
||||
std::string origParentEntryID, int pathInfoFlags);
|
||||
};
|
||||
|
||||
#endif /* DATABASETK_H_ */
|
||||
2
fsck/source/toolkit/FsckDefinitions.cpp
Normal file
2
fsck/source/toolkit/FsckDefinitions.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "FsckDefinitions.h"
|
||||
|
||||
75
fsck/source/toolkit/FsckDefinitions.h
Normal file
75
fsck/source/toolkit/FsckDefinitions.h
Normal file
@@ -0,0 +1,75 @@
|
||||
#ifndef FSCKDBTYPES_H_
|
||||
#define FSCKDBTYPES_H_
|
||||
|
||||
#include <common/Common.h>
|
||||
#include <common/storage/striping/StripePattern.h>
|
||||
#include <common/storage/StorageDefinitions.h>
|
||||
|
||||
#define TABLE_NAME_DIR_ENTRIES "dirEntries"
|
||||
#define TABLE_NAME_FILE_INODES "fileInodes"
|
||||
#define TABLE_NAME_DIR_INODES "dirInodes"
|
||||
#define TABLE_NAME_CHUNKS "chunks"
|
||||
#define TABLE_NAME_STRIPE_PATTERNS "stripePatterns"
|
||||
#define TABLE_NAME_CONT_DIRS "contDirs"
|
||||
#define TABLE_NAME_FSIDS "fsIDs"
|
||||
#define TABLE_NAME_USED_TARGETS "usedTargets"
|
||||
|
||||
#define TABLE_NAME_MODIFICATION_EVENTS "modificationEvents"
|
||||
|
||||
enum FsckRepairAction
|
||||
{
|
||||
FsckRepairAction_DELETEDENTRY = 0,
|
||||
FsckRepairAction_DELETEFILE = 1,
|
||||
FsckRepairAction_CREATEDEFAULTDIRINODE = 2,
|
||||
FsckRepairAction_CORRECTOWNER = 3,
|
||||
FsckRepairAction_LOSTANDFOUND = 4,
|
||||
FsckRepairAction_CREATECONTDIR = 5,
|
||||
FsckRepairAction_DELETEINODE = 7,
|
||||
FsckRepairAction_DELETECHUNK = 8,
|
||||
FsckRepairAction_DELETECONTDIR = 9,
|
||||
FsckRepairAction_UPDATEATTRIBS = 10,
|
||||
FsckRepairAction_CHANGETARGET = 11,
|
||||
FsckRepairAction_RECREATEFSID = 12,
|
||||
FsckRepairAction_RECREATEDENTRY = 13,
|
||||
FsckRepairAction_FIXPERMISSIONS = 14,
|
||||
FsckRepairAction_MOVECHUNK = 15,
|
||||
FsckRepairAction_REPAIRDUPLICATEINODE = 16,
|
||||
FsckRepairAction_UPDATEOLDTYLEDHARDLINKS = 17,
|
||||
FsckRepairAction_NOTHING = 18,
|
||||
FsckRepairAction_UNDEFINED = 19
|
||||
};
|
||||
|
||||
struct FsckRepairActionElem
|
||||
{
|
||||
const char* actionShortDesc;
|
||||
const char* actionDesc;
|
||||
enum FsckRepairAction action;
|
||||
};
|
||||
|
||||
// Note: Keep in sync with enum FsckErrorCode
|
||||
FsckRepairActionElem const __FsckRepairActions[] =
|
||||
{
|
||||
{"DeleteDentry", "Delete directory entry", FsckRepairAction_DELETEDENTRY},
|
||||
{"DeleteFile", "Delete file", FsckRepairAction_DELETEFILE},
|
||||
{"CreateDefDirInode", "Create a directory inode with default values",
|
||||
FsckRepairAction_CREATEDEFAULTDIRINODE},
|
||||
{"CorrectOwner", "Correct owner node", FsckRepairAction_CORRECTOWNER},
|
||||
{"LostAndFound", "Link to lost+found", FsckRepairAction_LOSTANDFOUND},
|
||||
{"CreateContDir", "Create an empty content directory", FsckRepairAction_CREATECONTDIR},
|
||||
{"DeleteInode", "Delete inodes", FsckRepairAction_DELETEINODE},
|
||||
{"DeleteChunk", "Delete chunk", FsckRepairAction_DELETECHUNK},
|
||||
{"DeleteContDir", "Delete content directory", FsckRepairAction_DELETECONTDIR},
|
||||
{"UpdateAttribs", "Update attributes", FsckRepairAction_UPDATEATTRIBS},
|
||||
{"ChangeTarget", "Change target ID in stripe patterns", FsckRepairAction_CHANGETARGET},
|
||||
{"RecreateFsID", "Recreate dentry-by-id file", FsckRepairAction_RECREATEFSID},
|
||||
{"RecreateDentry", "Recreate directory entry file", FsckRepairAction_RECREATEDENTRY},
|
||||
{"FixPermissions", "Fix permissions", FsckRepairAction_FIXPERMISSIONS},
|
||||
{"MoveChunk", "Move chunk", FsckRepairAction_MOVECHUNK},
|
||||
{"RepairDuplicateInode", "Repair duplicate inode", FsckRepairAction_REPAIRDUPLICATEINODE},
|
||||
{"UpdateOldStyledHardlinks", "Update metadata of old styled hardlinks to new format",
|
||||
FsckRepairAction_UPDATEOLDTYLEDHARDLINKS},
|
||||
{"Nothing", "Do nothing", FsckRepairAction_NOTHING},
|
||||
{0, 0, FsckRepairAction_UNDEFINED}
|
||||
};
|
||||
|
||||
#endif /* FSCKDBTYPES_H_ */
|
||||
16
fsck/source/toolkit/FsckException.h
Normal file
16
fsck/source/toolkit/FsckException.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* FsckException.h
|
||||
*
|
||||
* This exception is intended for things that can happen in fsck, that prevents it from running
|
||||
* further, e.g. if a server goes down fsck should abort
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FSCKEXCEPTION_H
|
||||
#define FSCKEXCEPTION_H
|
||||
|
||||
#include <common/toolkit/NamedException.h>
|
||||
|
||||
DECLARE_NAMEDEXCEPTION(FsckException, "FsckException")
|
||||
|
||||
#endif /* FSCKEXCEPTION_H */
|
||||
604
fsck/source/toolkit/FsckTkEx.cpp
Normal file
604
fsck/source/toolkit/FsckTkEx.cpp
Normal file
@@ -0,0 +1,604 @@
|
||||
#include "FsckTkEx.h"
|
||||
|
||||
#include <common/net/message/fsck/FsckSetEventLoggingMsg.h>
|
||||
#include <common/net/message/fsck/FsckSetEventLoggingRespMsg.h>
|
||||
#include <common/net/message/storage/StatStoragePathMsg.h>
|
||||
#include <common/net/message/storage/StatStoragePathRespMsg.h>
|
||||
#include <common/toolkit/ListTk.h>
|
||||
#include <common/toolkit/FsckTk.h>
|
||||
#include <common/toolkit/UnitTk.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
char FsckTkEx::progressChar = '-';
|
||||
Mutex FsckTkEx::outputMutex;
|
||||
|
||||
/*
|
||||
* check the reachability of all nodes in the system
|
||||
*/
|
||||
bool FsckTkEx::checkReachability()
|
||||
{
|
||||
NodeStore* metaNodes = Program::getApp()->getMetaNodes();
|
||||
NodeStore* storageNodes = Program::getApp()->getStorageNodes();
|
||||
|
||||
StringList errors;
|
||||
bool commSuccess = true;
|
||||
|
||||
FsckTkEx::fsckOutput("Step 1: Check reachability of nodes: ", OutputOptions_FLUSH);
|
||||
|
||||
if ( metaNodes->getSize() == 0 )
|
||||
{
|
||||
errors.push_back("No metadata nodes found");
|
||||
commSuccess = false;
|
||||
}
|
||||
|
||||
if ( storageNodes->getSize() == 0 )
|
||||
{
|
||||
errors.push_back("No storage nodes found");
|
||||
commSuccess = false;
|
||||
}
|
||||
|
||||
for (const auto& node : metaNodes->referenceAllNodes())
|
||||
{
|
||||
if ( !FsckTkEx::checkReachability(*node, NODETYPE_Meta) )
|
||||
{
|
||||
errors.push_back("Communication with metadata node failed: " + node->getAlias());
|
||||
commSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& node : storageNodes->referenceAllNodes())
|
||||
{
|
||||
if ( !FsckTkEx::checkReachability(*node, NODETYPE_Storage) )
|
||||
{
|
||||
errors.push_back("Communication with storage node failed: " + node->getAlias());
|
||||
commSuccess = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( commSuccess )
|
||||
FsckTkEx::fsckOutput("Finished", OutputOptions_LINEBREAK);
|
||||
else
|
||||
{
|
||||
for ( StringListIter iter = errors.begin(); iter != errors.end(); iter++ )
|
||||
{
|
||||
FsckTkEx::fsckOutput(*iter,
|
||||
OutputOptions_NONE | OutputOptions_LINEBREAK | OutputOptions_STDERR);
|
||||
}
|
||||
}
|
||||
|
||||
return commSuccess;
|
||||
}
|
||||
|
||||
/*
|
||||
* check reachability of a single node
|
||||
*/
|
||||
bool FsckTkEx::checkReachability(Node& node, NodeType nodetype)
|
||||
{
|
||||
bool retVal = false;
|
||||
HeartbeatRequestMsg heartbeatRequestMsg;
|
||||
std::string realNodeID = node.getAlias();
|
||||
|
||||
const auto respMsg = MessagingTk::requestResponse(node, heartbeatRequestMsg,
|
||||
NETMSGTYPE_Heartbeat);
|
||||
if (respMsg)
|
||||
{
|
||||
HeartbeatMsg *heartbeatMsg = (HeartbeatMsg *) respMsg.get();
|
||||
std::string receivedNodeID = heartbeatMsg->getNodeID();
|
||||
retVal = receivedNodeID.compare(realNodeID) == 0;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void FsckTkEx::fsckOutput(std::string text, int optionFlags)
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(outputMutex);
|
||||
|
||||
static bool fileErrLogged = false; // to make sure we print logfile open err only once
|
||||
|
||||
Config* cfg = Program::getApp()->getConfig(); // might be NULL on app init failure
|
||||
bool toLog = cfg && (!(OutputOptions_NOLOG & optionFlags)); // true if write to log file
|
||||
|
||||
FILE *logFile = NULL;
|
||||
|
||||
if (likely(toLog))
|
||||
{
|
||||
std::string logFilePath = cfg->getLogOutFile();
|
||||
|
||||
logFile = fopen(logFilePath.c_str(),"a+");
|
||||
if (logFile == NULL)
|
||||
{
|
||||
toLog = false;
|
||||
|
||||
if(!fileErrLogged)
|
||||
{
|
||||
std::cerr << "Cannot open output file for writing: '" << logFilePath << "'"
|
||||
<< std::endl;
|
||||
|
||||
fileErrLogged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* colorNormal = OutputColor_NORMAL;
|
||||
const char* color = OutputColor_NORMAL;
|
||||
|
||||
FILE *outFile = stdout;
|
||||
|
||||
if (OutputOptions_STDERR & optionFlags)
|
||||
{
|
||||
outFile = stderr;
|
||||
}
|
||||
else if (OutputOptions_NOSTDOUT & optionFlags)
|
||||
{
|
||||
outFile = NULL;
|
||||
}
|
||||
|
||||
bool outFileIsTty;
|
||||
|
||||
if (outFile)
|
||||
outFileIsTty = isatty(fileno(outFile));
|
||||
else
|
||||
outFileIsTty = false;
|
||||
|
||||
if (OutputOptions_COLORGREEN & optionFlags)
|
||||
{
|
||||
color = OutputColor_GREEN;
|
||||
}
|
||||
else if (OutputOptions_COLORRED & optionFlags)
|
||||
{
|
||||
color = OutputColor_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = OutputColor_NORMAL;
|
||||
}
|
||||
|
||||
if (OutputOptions_LINEDELETE & optionFlags)
|
||||
{
|
||||
optionFlags = optionFlags | OutputOptions_FLUSH;
|
||||
SAFE_FPRINTF(outFile, "\r");
|
||||
SAFE_FPRINTF(outFile, " ");
|
||||
SAFE_FPRINTF(outFile, "\r");
|
||||
}
|
||||
|
||||
if (OutputOptions_ADDLINEBREAKBEFORE & optionFlags)
|
||||
{
|
||||
SAFE_FPRINTF(outFile, "\n");
|
||||
if (likely(toLog)) SAFE_FPRINTF(logFile,"\n");
|
||||
}
|
||||
|
||||
if (OutputOptions_HEADLINE & optionFlags)
|
||||
{
|
||||
SAFE_FPRINTF(outFile, "\n--------------------------------------------------------------------\n");
|
||||
|
||||
if (likely(toLog))
|
||||
SAFE_FPRINTF(logFile,"\n--------------------------------------------------------------------\n");
|
||||
|
||||
if (likely(outFileIsTty))
|
||||
SAFE_FPRINTF(outFile, "%s%s%s",color,text.c_str(),colorNormal);
|
||||
else
|
||||
SAFE_FPRINTF(outFile, "%s",text.c_str());
|
||||
|
||||
if (likely(toLog))
|
||||
SAFE_FPRINTF(logFile,"%s",text.c_str());
|
||||
|
||||
SAFE_FPRINTF(outFile, "\n--------------------------------------------------------------------\n") ;
|
||||
|
||||
if (likely(toLog))
|
||||
SAFE_FPRINTF(logFile,"\n--------------------------------------------------------------------\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (likely(outFileIsTty))
|
||||
SAFE_FPRINTF(outFile, "%s%s%s",color,text.c_str(),colorNormal);
|
||||
else
|
||||
SAFE_FPRINTF(outFile, "%s",text.c_str());
|
||||
|
||||
if (likely(toLog)) SAFE_FPRINTF(logFile,"%s",text.c_str());
|
||||
}
|
||||
|
||||
if (OutputOptions_LINEBREAK & optionFlags)
|
||||
{
|
||||
SAFE_FPRINTF(outFile, "\n");
|
||||
if (likely(toLog))
|
||||
SAFE_FPRINTF(logFile,"\n");
|
||||
}
|
||||
|
||||
if (OutputOptions_DOUBLELINEBREAK & optionFlags)
|
||||
{
|
||||
SAFE_FPRINTF(outFile, "\n\n");
|
||||
if (likely(toLog))
|
||||
SAFE_FPRINTF(logFile,"\n\n");
|
||||
}
|
||||
|
||||
if (OutputOptions_FLUSH & optionFlags)
|
||||
{
|
||||
fflush(outFile);
|
||||
if (likely(toLog))
|
||||
fflush(logFile);
|
||||
}
|
||||
|
||||
if (logFile != NULL)
|
||||
{
|
||||
fclose(logFile);
|
||||
}
|
||||
}
|
||||
|
||||
void FsckTkEx::printVersionHeader(bool toStdErr, bool noLogFile)
|
||||
{
|
||||
int optionFlags = OutputOptions_LINEBREAK;
|
||||
if (toStdErr)
|
||||
{
|
||||
optionFlags = OutputOptions_LINEBREAK | OutputOptions_STDERR;
|
||||
}
|
||||
if (noLogFile)
|
||||
{
|
||||
optionFlags = optionFlags | OutputOptions_NOLOG;
|
||||
}
|
||||
|
||||
FsckTkEx::fsckOutput("\n", optionFlags);
|
||||
FsckTkEx::fsckOutput("BeeGFS File System Check Version : " + std::string(BEEGFS_VERSION),
|
||||
optionFlags);
|
||||
FsckTkEx::fsckOutput("----", optionFlags);
|
||||
}
|
||||
|
||||
void FsckTkEx::progressMeter()
|
||||
{
|
||||
const std::lock_guard<Mutex> lock(outputMutex);
|
||||
|
||||
printf("\b%c",progressChar);
|
||||
fflush(stdout);
|
||||
|
||||
switch(progressChar)
|
||||
{
|
||||
case '-' :
|
||||
{
|
||||
progressChar = '\\';
|
||||
break;
|
||||
}
|
||||
case '\\' :
|
||||
{
|
||||
progressChar = '|';
|
||||
break;
|
||||
}
|
||||
case '|' :
|
||||
{
|
||||
progressChar = '/';
|
||||
break;
|
||||
}
|
||||
case '/' :
|
||||
{
|
||||
progressChar = '-';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
progressChar = '-';
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* this is only a rough approximation
|
||||
*/
|
||||
int64_t FsckTkEx::calcNeededSpace()
|
||||
{
|
||||
const char* logContext = "FsckTkEx (calcNeededSpace)";
|
||||
int64_t neededSpace = 0;
|
||||
|
||||
// get used inodes from all meta data servers and sum them up
|
||||
NodeStore* metaNodes = Program::getApp()->getMetaNodes();
|
||||
|
||||
for (const auto& metaNode : metaNodes->referenceAllNodes())
|
||||
{
|
||||
NumNodeID nodeID = metaNode->getNumID();
|
||||
|
||||
StatStoragePathMsg statStoragePathMsg(0);
|
||||
|
||||
const auto respMsg = MessagingTk::requestResponse(*metaNode, statStoragePathMsg,
|
||||
NETMSGTYPE_StatStoragePathResp);
|
||||
if (respMsg)
|
||||
{
|
||||
StatStoragePathRespMsg* statStoragePathRespMsg = (StatStoragePathRespMsg *) respMsg.get();
|
||||
int64_t usedInodes = statStoragePathRespMsg->getInodesTotal()
|
||||
- statStoragePathRespMsg->getInodesFree();
|
||||
neededSpace += usedInodes * NEEDED_DISKSPACE_META_INODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext(logContext).logErr(
|
||||
"Unable to calculate needed disk space; Communication error with node: "
|
||||
+ nodeID.str());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// get used inodes from all storage servers and sum them up
|
||||
NodeStore* storageNodes = Program::getApp()->getStorageNodes();
|
||||
TargetMapper* targetMapper = Program::getApp()->getTargetMapper();
|
||||
|
||||
for (const auto& storageNode : storageNodes->referenceAllNodes())
|
||||
{
|
||||
NumNodeID nodeID = storageNode->getNumID();
|
||||
UInt16List targetIDs;
|
||||
targetMapper->getTargetsByNode(nodeID, targetIDs);
|
||||
|
||||
for ( UInt16ListIter targetIDIter = targetIDs.begin(); targetIDIter != targetIDs.end();
|
||||
targetIDIter++ )
|
||||
{
|
||||
uint16_t targetID = *targetIDIter;
|
||||
StatStoragePathMsg statStoragePathMsg(targetID);
|
||||
|
||||
const auto respMsg = MessagingTk::requestResponse(*storageNode, statStoragePathMsg,
|
||||
NETMSGTYPE_StatStoragePathResp);
|
||||
if (respMsg)
|
||||
{
|
||||
auto* statStoragePathRespMsg = (StatStoragePathRespMsg *) respMsg.get();
|
||||
int64_t usedInodes = statStoragePathRespMsg->getInodesTotal()
|
||||
- statStoragePathRespMsg->getInodesFree();
|
||||
neededSpace += usedInodes * NEEDED_DISKSPACE_STORAGE_INODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext(logContext).logErr(
|
||||
"Unable to calculate needed disk space; Communication error with node: "
|
||||
+ nodeID.str());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we take the calculated approximation and double it to have a lot of space for errors
|
||||
return neededSpace*2;
|
||||
}
|
||||
|
||||
bool FsckTkEx::checkDiskSpace(Path& dbPath)
|
||||
{
|
||||
int64_t neededDiskSpace = FsckTkEx::calcNeededSpace();
|
||||
|
||||
if ( unlikely(neededDiskSpace < 0) )
|
||||
{
|
||||
FsckTkEx::fsckOutput("Could not determine needed disk space. Aborting now.",
|
||||
OutputOptions_LINEBREAK | OutputOptions_ADDLINEBREAKBEFORE);
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t sizeTotal;
|
||||
int64_t sizeFree;
|
||||
int64_t inodesTotal;
|
||||
int64_t inodesFree;
|
||||
bool statRes = StorageTk::statStoragePath(dbPath, true, &sizeTotal, &sizeFree,
|
||||
&inodesTotal, &inodesFree);
|
||||
|
||||
if (!statRes)
|
||||
{
|
||||
FsckTkEx::fsckOutput(
|
||||
"Could not stat database file path to determine free space; database file: "
|
||||
+ dbPath.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( neededDiskSpace >= sizeFree )
|
||||
{
|
||||
std::string neededDiskSpaceUnit;
|
||||
double neededDiskSpaceValue = UnitTk::byteToXbyte(neededDiskSpace, &neededDiskSpaceUnit);
|
||||
|
||||
std::string sizeFreeUnit;
|
||||
double sizeFreeValue = UnitTk::byteToXbyte(sizeFree, &sizeFreeUnit);
|
||||
|
||||
FsckTkEx::fsckOutput(
|
||||
"Not enough disk space to create database file: " + dbPath.str()
|
||||
+ "; Recommended free space: " + StringTk::doubleToStr(neededDiskSpaceValue)
|
||||
+ neededDiskSpaceUnit + "; Free space: " + StringTk::doubleToStr(sizeFreeValue)
|
||||
+ sizeFreeUnit, OutputOptions_LINEBREAK | OutputOptions_ADDLINEBREAKBEFORE);
|
||||
|
||||
bool ignoreDBDiskSpace = Program::getApp()->getConfig()->getIgnoreDBDiskSpace();
|
||||
if(!ignoreDBDiskSpace)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string FsckTkEx::getRepairActionDesc(FsckRepairAction repairAction, bool shortDesc)
|
||||
{
|
||||
for (size_t i = 0; __FsckRepairActions[i].actionDesc != nullptr; i++)
|
||||
{
|
||||
if( repairAction == __FsckRepairActions[i].action )
|
||||
{ // we have a match
|
||||
if (shortDesc)
|
||||
return __FsckRepairActions[i].actionShortDesc;
|
||||
else
|
||||
return __FsckRepairActions[i].actionDesc;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
FhgfsOpsErr FsckTkEx::startModificationLogging(NodeStore* metaNodes, Node& localNode,
|
||||
bool forceRestart)
|
||||
{
|
||||
const char* logContext = "FsckTkEx (startModificationLogging)";
|
||||
|
||||
FhgfsOpsErr retVal = FhgfsOpsErr_SUCCESS;
|
||||
|
||||
NicAddressList localNicList = localNode.getNicList();
|
||||
unsigned localPortUDP = localNode.getPortUDP();
|
||||
|
||||
FsckTkEx::fsckOutput("-----",
|
||||
OutputOptions_ADDLINEBREAKBEFORE | OutputOptions_FLUSH | OutputOptions_LINEBREAK);
|
||||
FsckTkEx::fsckOutput(
|
||||
"Waiting for metadata servers to start modification logging. This might take some time.",
|
||||
OutputOptions_FLUSH | OutputOptions_LINEBREAK);
|
||||
FsckTkEx::fsckOutput("-----", OutputOptions_FLUSH | OutputOptions_DOUBLELINEBREAK);
|
||||
|
||||
NumNodeIDList nodeIDs;
|
||||
|
||||
auto metaNodeList = metaNodes->referenceAllNodes();
|
||||
|
||||
for (auto iter = metaNodeList.begin(); iter != metaNodeList.end(); iter++)
|
||||
{
|
||||
auto node = metaNodes->referenceNode((*iter)->getNumID());
|
||||
|
||||
NicAddressList nicList;
|
||||
FsckSetEventLoggingMsg fsckSetEventLoggingMsg(true, localPortUDP,
|
||||
&localNicList, forceRestart);
|
||||
|
||||
const auto respMsg = MessagingTk::requestResponse(*node, fsckSetEventLoggingMsg,
|
||||
NETMSGTYPE_FsckSetEventLoggingResp);
|
||||
|
||||
if (respMsg)
|
||||
{
|
||||
auto* fsckSetEventLoggingRespMsg = (FsckSetEventLoggingRespMsg*) respMsg.get();
|
||||
|
||||
bool started = fsckSetEventLoggingRespMsg->getLoggingEnabled();
|
||||
|
||||
if (!started) // EventFlusher was already running on this node!
|
||||
{
|
||||
LogContext(logContext).logErr("Modification logging already running on node: "
|
||||
+ node->getAlias());
|
||||
|
||||
retVal = FhgfsOpsErr_INUSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext(logContext).logErr("Communication error occured with node: " + node->getAlias());
|
||||
retVal = FhgfsOpsErr_COMMUNICATION;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool FsckTkEx::stopModificationLogging(NodeStore* metaNodes)
|
||||
{
|
||||
const char* logContext = "FsckTkEx (stopModificationLogging)";
|
||||
|
||||
bool retVal = true;
|
||||
|
||||
FsckTkEx::fsckOutput("-----",
|
||||
OutputOptions_ADDLINEBREAKBEFORE | OutputOptions_FLUSH | OutputOptions_LINEBREAK);
|
||||
FsckTkEx::fsckOutput(
|
||||
"Waiting for metadata servers to stop modification logging. This might take some time.",
|
||||
OutputOptions_FLUSH | OutputOptions_LINEBREAK);
|
||||
FsckTkEx::fsckOutput("-----", OutputOptions_FLUSH | OutputOptions_DOUBLELINEBREAK);
|
||||
|
||||
NumNodeIDList nodeIDs;
|
||||
|
||||
auto metaNodeList = metaNodes->referenceAllNodes();
|
||||
|
||||
for (auto iter = metaNodeList.begin(); iter != metaNodeList.end(); iter++)
|
||||
nodeIDs.push_back((*iter)->getNumID());
|
||||
|
||||
NumNodeIDListIter nodeIdIter = nodeIDs.begin();
|
||||
|
||||
while (! nodeIDs.empty())
|
||||
{
|
||||
NumNodeID nodeID = *nodeIdIter;
|
||||
|
||||
auto node = metaNodes->referenceNode(nodeID);
|
||||
|
||||
NicAddressList nicList;
|
||||
FsckSetEventLoggingMsg fsckSetEventLoggingMsg(false, 0, &nicList, false);
|
||||
|
||||
const auto respMsg = MessagingTk::requestResponse(*node, fsckSetEventLoggingMsg,
|
||||
NETMSGTYPE_FsckSetEventLoggingResp);
|
||||
|
||||
if (respMsg)
|
||||
{
|
||||
auto* fsckSetEventLoggingRespMsg = (FsckSetEventLoggingRespMsg*) respMsg.get();
|
||||
|
||||
bool result = fsckSetEventLoggingRespMsg->getResult();
|
||||
bool missedEvents = fsckSetEventLoggingRespMsg->getMissedEvents();
|
||||
|
||||
if ( result )
|
||||
{
|
||||
nodeIdIter = nodeIDs.erase(nodeIdIter);
|
||||
if ( missedEvents )
|
||||
{
|
||||
retVal = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
nodeIdIter++; // keep in list and try again later
|
||||
}
|
||||
else
|
||||
{
|
||||
LogContext(logContext).logErr("Communication error occurred with node: " + node->getAlias());
|
||||
retVal = false;
|
||||
}
|
||||
|
||||
if (nodeIdIter == nodeIDs.end())
|
||||
{
|
||||
nodeIdIter = nodeIDs.begin();
|
||||
sleep(5);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool FsckTkEx::checkConsistencyStates()
|
||||
{
|
||||
auto mgmtdNode = Program::getApp()->getMgmtNodes()->referenceFirstNode();
|
||||
if (!mgmtdNode)
|
||||
throw std::runtime_error("Management node not found");
|
||||
|
||||
std::list<uint8_t> storageReachabilityStates;
|
||||
std::list<uint8_t> storageConsistencyStates;
|
||||
std::list<uint16_t> storageTargetIDs;
|
||||
std::list<uint8_t> metaReachabilityStates;
|
||||
std::list<uint8_t> metaConsistencyStates;
|
||||
std::list<uint16_t> metaTargetIDs;
|
||||
|
||||
if (!NodesTk::downloadTargetStates(*mgmtdNode, NODETYPE_Storage, &storageTargetIDs,
|
||||
&storageReachabilityStates, &storageConsistencyStates, false)
|
||||
|| !NodesTk::downloadTargetStates(*mgmtdNode, NODETYPE_Meta, &metaTargetIDs,
|
||||
&metaReachabilityStates, &metaConsistencyStates, false))
|
||||
{
|
||||
throw std::runtime_error("Could not download target states from management.");
|
||||
}
|
||||
|
||||
|
||||
bool result = true;
|
||||
|
||||
{
|
||||
auto idIt = storageTargetIDs.begin();
|
||||
auto stateIt = storageConsistencyStates.begin();
|
||||
for (; idIt != storageTargetIDs.end() && stateIt != storageConsistencyStates.end();
|
||||
idIt++, stateIt++)
|
||||
{
|
||||
if (*stateIt == TargetConsistencyState_NEEDS_RESYNC)
|
||||
{
|
||||
FsckTkEx::fsckOutput("Storage target " + StringTk::uintToStr(*idIt) + " is set to "
|
||||
"NEEDS_RESYNC.", OutputOptions_LINEBREAK);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto idIt = metaTargetIDs.begin();
|
||||
auto stateIt = metaConsistencyStates.begin();
|
||||
for (; idIt != metaTargetIDs.end() && stateIt != metaConsistencyStates.end();
|
||||
idIt++, stateIt++)
|
||||
{
|
||||
if (*stateIt == TargetConsistencyState_NEEDS_RESYNC)
|
||||
{
|
||||
FsckTkEx::fsckOutput("Meta node " + StringTk::uintToStr(*idIt) + " is set to "
|
||||
"NEEDS_RESYNC.", OutputOptions_LINEBREAK);
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
103
fsck/source/toolkit/FsckTkEx.h
Normal file
103
fsck/source/toolkit/FsckTkEx.h
Normal file
@@ -0,0 +1,103 @@
|
||||
#ifndef FSCKTKEX_H_
|
||||
#define FSCKTKEX_H_
|
||||
|
||||
#include <common/app/log/LogContext.h>
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <common/fsck/FsckChunk.h>
|
||||
#include <common/fsck/FsckContDir.h>
|
||||
#include <common/fsck/FsckDirEntry.h>
|
||||
#include <common/fsck/FsckDirInode.h>
|
||||
#include <common/fsck/FsckFileInode.h>
|
||||
#include <common/fsck/FsckFsID.h>
|
||||
#include <common/net/message/nodes/HeartbeatRequestMsg.h>
|
||||
#include <common/net/message/nodes/HeartbeatMsg.h>
|
||||
#include <common/nodes/NodeStore.h>
|
||||
#include <common/threading/PThread.h>
|
||||
#include <common/toolkit/NodesTk.h>
|
||||
#include <common/toolkit/MessagingTk.h>
|
||||
#include <toolkit/FsckDefinitions.h>
|
||||
|
||||
/* OutputOption Flags for fsckOutput */
|
||||
#define OutputOptions_NONE 0
|
||||
#define OutputOptions_LINEBREAK 1
|
||||
#define OutputOptions_DOUBLELINEBREAK 1 << 1
|
||||
#define OutputOptions_HEADLINE 1 << 2
|
||||
#define OutputOptions_FLUSH 1 << 3
|
||||
#define OutputOptions_ADDLINEBREAKBEFORE 1 << 4
|
||||
#define OutputOptions_COLORGREEN 1 << 5
|
||||
#define OutputOptions_COLORRED 1 << 6
|
||||
#define OutputOptions_LINEDELETE 1 << 7
|
||||
#define OutputOptions_NOSTDOUT 1 << 8
|
||||
#define OutputOptions_NOLOG 1 << 9
|
||||
#define OutputOptions_STDERR 1 << 10
|
||||
|
||||
#define OutputColor_NORMAL "\033[0m";
|
||||
#define OutputColor_GREEN "\033[32m";
|
||||
#define OutputColor_RED "\033[31m";
|
||||
|
||||
#define SAFE_FPRINTF(stream, fmt, args...) \
|
||||
do{ if(stream) {fprintf(stream, fmt, ##args);} } while(0)
|
||||
|
||||
/*
|
||||
* calculating with:
|
||||
* DirEntry 76+256+28 Byte (space for dentry + longest name + one index)
|
||||
* FileInode 96 Byte |
|
||||
* DirInode 56 Byte # only the larger of these two counts, even though files are inlined
|
||||
* ContDir 16 Byte
|
||||
* FsID 40 Byte
|
||||
* chunk 88 Byte
|
||||
*
|
||||
*/
|
||||
#define NEEDED_DISKSPACE_META_INODE 512
|
||||
#define NEEDED_DISKSPACE_STORAGE_INODE 88
|
||||
|
||||
class FsckTkEx
|
||||
{
|
||||
public:
|
||||
// check the reachability of all nodes
|
||||
static bool checkReachability();
|
||||
// check the reachability of a given node by sending a heartbeat message
|
||||
static bool checkReachability(Node& node, NodeType nodetype);
|
||||
|
||||
/*
|
||||
* a formatted output for fsck
|
||||
*
|
||||
* @param text The text to be printed
|
||||
* @param optionFlags OutputOptions_... flags (mainly for formatiing)
|
||||
*/
|
||||
static void fsckOutput(std::string text, int optionFlags);
|
||||
// just print a formatted header with the version to the console
|
||||
static void printVersionHeader(bool toStdErr = false, bool noLogFile = false);
|
||||
// print the progress meter which goes round and round (-\|/-)
|
||||
static void progressMeter();
|
||||
|
||||
static int64_t calcNeededSpace();
|
||||
static bool checkDiskSpace(Path& dbPath);
|
||||
|
||||
static std::string getRepairActionDesc(FsckRepairAction repairAction, bool shortDesc = false);
|
||||
|
||||
static FhgfsOpsErr startModificationLogging(NodeStore* metaNodes, Node& localNode,
|
||||
bool forceRestart);
|
||||
static bool stopModificationLogging(NodeStore* metaNodes);
|
||||
|
||||
static bool checkConsistencyStates();
|
||||
|
||||
private:
|
||||
FsckTkEx() {}
|
||||
|
||||
// saves the last char output by the progress meter
|
||||
static char progressChar;
|
||||
// a mutex that is locked by output functions to make sure the output does not get messed up
|
||||
// by two threads doing output at the same time
|
||||
static Mutex outputMutex;
|
||||
|
||||
|
||||
public:
|
||||
// inliners
|
||||
static void fsckOutput(std::string text)
|
||||
{
|
||||
fsckOutput(text, OutputOptions_LINEBREAK);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FSCKTKEX_H_ */
|
||||
Reference in New Issue
Block a user