New upstream version 8.1.0
This commit is contained in:
562
fsck/source/app/App.cpp
Normal file
562
fsck/source/app/App.cpp
Normal file
@@ -0,0 +1,562 @@
|
||||
#include <common/components/RegistrationDatagramListener.h>
|
||||
#include <program/Program.h>
|
||||
|
||||
#include <toolkit/FsckTkEx.h>
|
||||
|
||||
#include <csignal>
|
||||
#include <syslog.h>
|
||||
|
||||
#define APP_WORKERS_DIRECT_NUM 1
|
||||
#define APP_SYSLOG_IDENTIFIER "beegfs-fsck"
|
||||
|
||||
App::App(int argc, char** argv)
|
||||
{
|
||||
this->argc = argc;
|
||||
this->argv = argv;
|
||||
|
||||
this->appResult = APPCODE_NO_ERROR;
|
||||
|
||||
this->cfg = NULL;
|
||||
this->netFilter = NULL;
|
||||
this->tcpOnlyFilter = NULL;
|
||||
this->log = NULL;
|
||||
this->mgmtNodes = NULL;
|
||||
this->metaNodes = NULL;
|
||||
this->storageNodes = NULL;
|
||||
this->internodeSyncer = NULL;
|
||||
this->targetMapper = NULL;
|
||||
this->targetStateStore = NULL;
|
||||
this->buddyGroupMapper = NULL;
|
||||
this->metaBuddyGroupMapper = NULL;
|
||||
this->workQueue = NULL;
|
||||
this->ackStore = NULL;
|
||||
this->netMessageFactory = NULL;
|
||||
this->dgramListener = NULL;
|
||||
this->modificationEventHandler = NULL;
|
||||
this->runMode = NULL;
|
||||
|
||||
}
|
||||
|
||||
App::~App()
|
||||
{
|
||||
// Note: Logging of the common lib classes is not working here, because this is called
|
||||
// from class Program (so the thread-specific app-pointer isn't set in this context).
|
||||
|
||||
workersDelete();
|
||||
|
||||
SAFE_DELETE(this->dgramListener);
|
||||
SAFE_DELETE(this->netMessageFactory);
|
||||
SAFE_DELETE(this->ackStore);
|
||||
SAFE_DELETE(this->workQueue);
|
||||
SAFE_DELETE(this->storageNodes);
|
||||
SAFE_DELETE(this->metaNodes);
|
||||
SAFE_DELETE(this->mgmtNodes);
|
||||
this->localNode.reset();
|
||||
SAFE_DELETE(this->buddyGroupMapper);
|
||||
SAFE_DELETE(this->metaBuddyGroupMapper);
|
||||
SAFE_DELETE(this->targetStateStore);
|
||||
SAFE_DELETE(this->targetMapper);
|
||||
SAFE_DELETE(this->internodeSyncer);
|
||||
SAFE_DELETE(this->log);
|
||||
SAFE_DELETE(this->tcpOnlyFilter);
|
||||
SAFE_DELETE(this->netFilter);
|
||||
SAFE_DELETE(this->cfg);
|
||||
SAFE_DELETE(this->runMode);
|
||||
|
||||
Logger::destroyLogger();
|
||||
closelog();
|
||||
}
|
||||
|
||||
void App::run()
|
||||
{
|
||||
try
|
||||
{
|
||||
openlog(APP_SYSLOG_IDENTIFIER, LOG_NDELAY | LOG_PID | LOG_CONS, LOG_DAEMON);
|
||||
|
||||
this->cfg = new Config(argc, argv);
|
||||
|
||||
runNormal();
|
||||
}
|
||||
catch (InvalidConfigException& e)
|
||||
{
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
std::cerr << std::endl;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if(this->log)
|
||||
log->logErr(e.what() );
|
||||
|
||||
this->appResult = APPCODE_INVALID_CONFIG;
|
||||
return;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Unrecoverable error: " << e.what() << std::endl;
|
||||
std::cerr << std::endl;
|
||||
|
||||
if(this->log)
|
||||
log->logErr(e.what() );
|
||||
|
||||
appResult = APPCODE_RUNTIME_ERROR;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void App::runNormal()
|
||||
{
|
||||
bool componentsStarted = false;
|
||||
|
||||
auto runModeEnum = Program::getApp()->getConfig()->determineRunMode();
|
||||
|
||||
if (runModeEnum == RunMode_CHECKFS || runModeEnum == RunMode_ENABLEQUOTA)
|
||||
{
|
||||
// check if running as root
|
||||
if(geteuid())
|
||||
{
|
||||
std::cerr << std::endl
|
||||
<< "Running beegfs-fsck requires root privileges."
|
||||
<< std::endl << std::endl << std::endl;
|
||||
ModeHelp().execute();
|
||||
appResult = APPCODE_INITIALIZATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
if (runModeEnum == RunMode_CHECKFS)
|
||||
runMode = new ModeCheckFS();
|
||||
else if (runModeEnum == RunMode_ENABLEQUOTA)
|
||||
runMode = new ModeEnableQuota();
|
||||
}
|
||||
else if (runModeEnum == RunMode_HELP)
|
||||
{
|
||||
appResult = ModeHelp().execute();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ModeHelp().execute();
|
||||
appResult = APPCODE_INVALID_CONFIG;
|
||||
return;
|
||||
}
|
||||
|
||||
initDataObjects(argc, argv);
|
||||
|
||||
// wait for mgmtd
|
||||
if ( !cfg->getSysMgmtdHost().length() )
|
||||
throw InvalidConfigException("Management host undefined");
|
||||
|
||||
bool mgmtWaitRes = waitForMgmtNode();
|
||||
if(!mgmtWaitRes)
|
||||
{ // typically user just pressed ctrl+c in this case
|
||||
log->logErr("Waiting for beegfs-mgmtd canceled");
|
||||
appResult = APPCODE_RUNTIME_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// init components
|
||||
try
|
||||
{
|
||||
initComponents();
|
||||
}
|
||||
catch (ComponentInitException& e)
|
||||
{
|
||||
FsckTkEx::fsckOutput(e.what(), OutputOptions_DOUBLELINEBREAK | OutputOptions_STDERR);
|
||||
|
||||
FsckTkEx::fsckOutput("A hard error occurred. BeeGFS Fsck will abort.",
|
||||
OutputOptions_LINEBREAK | OutputOptions_STDERR);
|
||||
appResult = APPCODE_INITIALIZATION_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// log system and configuration info
|
||||
|
||||
logInfos();
|
||||
|
||||
// start component threads
|
||||
startComponents();
|
||||
componentsStarted = true;
|
||||
|
||||
try
|
||||
{
|
||||
appResult = runMode->execute();
|
||||
}
|
||||
catch (InvalidConfigException& e)
|
||||
{
|
||||
ModeHelp modeHelp;
|
||||
modeHelp.execute();
|
||||
|
||||
appResult = APPCODE_INVALID_CONFIG;
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
FsckTkEx::fsckOutput("Unrecoverable error. BeeGFS Fsck will abort.",
|
||||
OutputOptions_LINEBREAK | OutputOptions_ADDLINEBREAKBEFORE | OutputOptions_STDERR);
|
||||
FsckTkEx::fsckOutput(e.what(), OutputOptions_LINEBREAK | OutputOptions_STDERR);
|
||||
}
|
||||
|
||||
// self-termination
|
||||
if(componentsStarted)
|
||||
{
|
||||
stopComponents();
|
||||
joinComponents();
|
||||
}
|
||||
}
|
||||
|
||||
void App::initDataObjects(int argc, char** argv)
|
||||
{
|
||||
this->netFilter = new NetFilter(cfg->getConnNetFilterFile() );
|
||||
this->tcpOnlyFilter = new NetFilter(cfg->getConnTcpOnlyFilterFile() );
|
||||
|
||||
Logger::createLogger(cfg->getLogLevel(), cfg->getLogType(), cfg->getLogNoDate(),
|
||||
cfg->getLogStdFile(), cfg->getLogNumLines(), cfg->getLogNumRotatedFiles());
|
||||
|
||||
this->log = new LogContext("App");
|
||||
|
||||
std::string interfacesFilename = this->cfg->getConnInterfacesFile();
|
||||
if ( interfacesFilename.length() )
|
||||
Config::loadStringListFile(interfacesFilename.c_str(), this->allowedInterfaces);
|
||||
|
||||
this->targetMapper = new TargetMapper();
|
||||
this->targetStateStore = new TargetStateStore(NODETYPE_Storage);
|
||||
this->buddyGroupMapper = new MirrorBuddyGroupMapper(targetMapper);
|
||||
this->metaBuddyGroupMapper = new MirrorBuddyGroupMapper();
|
||||
|
||||
this->mgmtNodes = new NodeStoreServers(NODETYPE_Mgmt, false);
|
||||
this->metaNodes = new NodeStoreServers(NODETYPE_Meta, false);
|
||||
this->storageNodes = new NodeStoreServers(NODETYPE_Storage, false);
|
||||
|
||||
this->workQueue = new MultiWorkQueue();
|
||||
this->ackStore = new AcknowledgmentStore();
|
||||
|
||||
initLocalNodeInfo();
|
||||
|
||||
registerSignalHandler();
|
||||
|
||||
this->netMessageFactory = new NetMessageFactory();
|
||||
}
|
||||
|
||||
void App::findAllowedRDMAInterfaces(NicAddressList& outList) const
|
||||
{
|
||||
Config* cfg = this->getConfig();
|
||||
|
||||
if(cfg->getConnUseRDMA() && RDMASocket::rdmaDevicesExist() )
|
||||
{
|
||||
bool foundRdmaInterfaces = NetworkInterfaceCard::checkAndAddRdmaCapability(outList);
|
||||
if (foundRdmaInterfaces)
|
||||
outList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces}); // re-sort the niclist
|
||||
}
|
||||
}
|
||||
|
||||
void App::findAllowedInterfaces(NicAddressList& outList) const
|
||||
{
|
||||
// discover local NICs and filter them
|
||||
NetworkInterfaceCard::findAllInterfaces(allowedInterfaces, outList);
|
||||
outList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces});
|
||||
}
|
||||
|
||||
void App::initLocalNodeInfo()
|
||||
{
|
||||
|
||||
findAllowedInterfaces(localNicList);
|
||||
findAllowedRDMAInterfaces(localNicList);
|
||||
|
||||
if ( this->localNicList.empty() )
|
||||
throw InvalidConfigException("Couldn't find any usable NIC");
|
||||
|
||||
initRoutingTable();
|
||||
updateRoutingTable();
|
||||
|
||||
std::string nodeID = System::getHostname();
|
||||
|
||||
this->localNode = std::make_shared<LocalNode>(NODETYPE_Client, nodeID, NumNodeID(), 0, 0,
|
||||
this->localNicList);
|
||||
}
|
||||
|
||||
void App::initComponents()
|
||||
{
|
||||
this->log->log(Log_DEBUG, "Initializing components...");
|
||||
|
||||
// Note: We choose a random udp port here to avoid conflicts with the client
|
||||
unsigned short udpListenPort = 0;
|
||||
|
||||
this->dgramListener = new DatagramListener(netFilter, localNicList, ackStore, udpListenPort,
|
||||
this->cfg->getConnRestrictOutboundInterfaces());
|
||||
|
||||
// update the local node info with udp port
|
||||
this->localNode->updateInterfaces(dgramListener->getUDPPort(), 0, this->localNicList);
|
||||
|
||||
this->internodeSyncer = new InternodeSyncer();
|
||||
|
||||
workersInit();
|
||||
|
||||
this->log->log(Log_DEBUG, "Components initialized.");
|
||||
}
|
||||
|
||||
void App::startComponents()
|
||||
{
|
||||
log->log(Log_SPAM, "Starting up components...");
|
||||
|
||||
// make sure child threads don't receive SIGINT/SIGTERM (blocked signals are inherited)
|
||||
PThread::blockInterruptSignals();
|
||||
|
||||
dgramListener->start();
|
||||
|
||||
internodeSyncer->start();
|
||||
internodeSyncer->waitForServers();
|
||||
|
||||
workersStart();
|
||||
|
||||
PThread::unblockInterruptSignals(); // main app thread may receive SIGINT/SIGTERM
|
||||
|
||||
log->log(Log_DEBUG, "Components running.");
|
||||
}
|
||||
|
||||
void App::stopComponents()
|
||||
{
|
||||
// note: this method may not wait for termination of the components, because that could
|
||||
// lead to a deadlock (when calling from signal handler)
|
||||
workersStop();
|
||||
|
||||
if(this->internodeSyncer)
|
||||
this->internodeSyncer->selfTerminate();
|
||||
|
||||
if ( dgramListener )
|
||||
{
|
||||
dgramListener->selfTerminate();
|
||||
dgramListener->sendDummyToSelfUDP();
|
||||
}
|
||||
|
||||
this->selfTerminate();
|
||||
}
|
||||
|
||||
void App::joinComponents()
|
||||
{
|
||||
log->log(4, "Joining component threads...");
|
||||
|
||||
this->internodeSyncer->join();
|
||||
|
||||
/* (note: we need one thread for which we do an untimed join, so this should be a quite reliably
|
||||
terminating thread) */
|
||||
this->dgramListener->join();
|
||||
|
||||
workersJoin();
|
||||
}
|
||||
|
||||
void App::workersInit()
|
||||
{
|
||||
unsigned numWorkers = cfg->getTuneNumWorkers();
|
||||
|
||||
for(unsigned i=0; i < numWorkers; i++)
|
||||
{
|
||||
Worker* worker = new Worker(
|
||||
std::string("Worker") + StringTk::intToStr(i+1), workQueue, QueueWorkType_INDIRECT);
|
||||
workerList.push_back(worker);
|
||||
}
|
||||
|
||||
for(unsigned i=0; i < APP_WORKERS_DIRECT_NUM; i++)
|
||||
{
|
||||
Worker* worker = new Worker(
|
||||
std::string("DirectWorker") + StringTk::intToStr(i+1), workQueue, QueueWorkType_DIRECT);
|
||||
workerList.push_back(worker);
|
||||
}
|
||||
}
|
||||
|
||||
void App::workersStart()
|
||||
{
|
||||
for ( WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++ )
|
||||
{
|
||||
(*iter)->start();
|
||||
}
|
||||
}
|
||||
|
||||
void App::workersStop()
|
||||
{
|
||||
// need two loops because we don't know if the worker that handles the work will be the same that
|
||||
// received the self-terminate-request
|
||||
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
|
||||
{
|
||||
(*iter)->selfTerminate();
|
||||
}
|
||||
|
||||
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
|
||||
{
|
||||
workQueue->addDirectWork(new DummyWork() );
|
||||
}
|
||||
}
|
||||
|
||||
void App::workersDelete()
|
||||
{
|
||||
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
|
||||
{
|
||||
delete(*iter);
|
||||
}
|
||||
|
||||
workerList.clear();
|
||||
}
|
||||
|
||||
void App::workersJoin()
|
||||
{
|
||||
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
|
||||
{
|
||||
waitForComponentTermination(*iter);
|
||||
}
|
||||
}
|
||||
|
||||
void App::logInfos()
|
||||
{
|
||||
// print software version (BEEGFS_VERSION)
|
||||
log->log(Log_NOTICE, std::string("Version: ") + BEEGFS_VERSION);
|
||||
|
||||
// print debug version info
|
||||
LOG_DEBUG_CONTEXT(*log, Log_CRITICAL, "--DEBUG VERSION--");
|
||||
|
||||
// print local nodeID
|
||||
log->log(Log_NOTICE, std::string("LocalNode: ") + localNode->getTypedNodeID() );
|
||||
|
||||
// list usable network interfaces
|
||||
NicAddressList nicList(localNode->getNicList());
|
||||
logUsableNICs(log, nicList);
|
||||
|
||||
// print net filters
|
||||
if ( netFilter->getNumFilterEntries() )
|
||||
{
|
||||
this->log->log(2,
|
||||
std::string("Net filters: ") + StringTk::uintToStr(netFilter->getNumFilterEntries()));
|
||||
}
|
||||
|
||||
if(tcpOnlyFilter->getNumFilterEntries() )
|
||||
{
|
||||
this->log->log(Log_WARNING, std::string("TCP-only filters: ") +
|
||||
StringTk::uintToStr(tcpOnlyFilter->getNumFilterEntries() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request mgmt heartbeat and wait for the mgmt node to appear in nodestore.
|
||||
*
|
||||
* @return true if mgmt heartbeat received, false on error or thread selftermination order
|
||||
*/
|
||||
bool App::waitForMgmtNode()
|
||||
{
|
||||
const unsigned waitTimeoutMS = 0; // infinite wait
|
||||
const unsigned nameResolutionRetries = 3;
|
||||
|
||||
// choose a random udp port here
|
||||
unsigned udpListenPort = 0;
|
||||
unsigned udpMgmtdPort = cfg->getConnMgmtdPort();
|
||||
std::string mgmtdHost = cfg->getSysMgmtdHost();
|
||||
|
||||
RegistrationDatagramListener regDGramLis(this->netFilter, this->localNicList, this->ackStore,
|
||||
udpListenPort, this->cfg->getConnRestrictOutboundInterfaces());
|
||||
|
||||
regDGramLis.start();
|
||||
|
||||
log->log(Log_CRITICAL, "Waiting for beegfs-mgmtd@" +
|
||||
mgmtdHost + ":" + StringTk::uintToStr(udpMgmtdPort) + "...");
|
||||
|
||||
bool gotMgmtd = NodesTk::waitForMgmtHeartbeat(
|
||||
this, ®DGramLis, this->mgmtNodes, mgmtdHost, udpMgmtdPort, waitTimeoutMS,
|
||||
nameResolutionRetries);
|
||||
|
||||
regDGramLis.selfTerminate();
|
||||
regDGramLis.sendDummyToSelfUDP(); // for faster termination
|
||||
|
||||
regDGramLis.join();
|
||||
|
||||
return gotMgmtd;
|
||||
}
|
||||
|
||||
void App::updateLocalNicList(NicAddressList& localNicList)
|
||||
{
|
||||
std::vector<AbstractNodeStore*> allNodes({ mgmtNodes, metaNodes, storageNodes});
|
||||
updateLocalNicListAndRoutes(log, localNicList, allNodes);
|
||||
localNode->updateInterfaces(0, 0, localNicList);
|
||||
dgramListener->setLocalNicList(localNicList);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles expections that lead to the termination of a component.
|
||||
* Initiates an application shutdown.
|
||||
*/
|
||||
|
||||
void App::handleComponentException(std::exception& e)
|
||||
{
|
||||
const char* logContext = "App (component exception handler)";
|
||||
LogContext log(logContext);
|
||||
|
||||
const auto componentName = PThread::getCurrentThreadName();
|
||||
|
||||
log.logErr(
|
||||
"The component [" + componentName + "] encountered an unrecoverable error. " +
|
||||
std::string("[SysErr: ") + System::getErrString() + "] " +
|
||||
std::string("Exception message: ") + e.what() );
|
||||
|
||||
log.log(2, "Shutting down...");
|
||||
|
||||
shallAbort.set(1);
|
||||
stopComponents();
|
||||
}
|
||||
|
||||
void App::handleNetworkInterfaceFailure(const std::string& devname)
|
||||
{
|
||||
LOG(GENERAL, ERR, "Network interface failure.",
|
||||
("Device", devname));
|
||||
internodeSyncer->setForceCheckNetwork();
|
||||
}
|
||||
|
||||
void App::registerSignalHandler()
|
||||
{
|
||||
signal(SIGINT, App::signalHandler);
|
||||
signal(SIGTERM, App::signalHandler);
|
||||
}
|
||||
|
||||
void App::signalHandler(int sig)
|
||||
{
|
||||
App* app = Program::getApp();
|
||||
|
||||
Logger* log = Logger::getLogger();
|
||||
const char* logContext = "App::signalHandler";
|
||||
|
||||
// note: this might deadlock if the signal was thrown while the logger mutex is locked by the
|
||||
// application thread (depending on whether the default mutex style is recursive). but
|
||||
// even recursive mutexes are not acceptable in this case.
|
||||
// we need something like a timed lock for the log mutex. if it succeeds within a
|
||||
// few seconds, we know that we didn't hold the mutex lock. otherwise we simply skip the
|
||||
// log message. this will only work if the mutex is non-recusive (which is unknown for
|
||||
// the default mutex style).
|
||||
// but it is very unlikely that the application thread holds the log mutex, because it
|
||||
// joins the component threads and so it doesn't do anything else but sleeping!
|
||||
|
||||
switch(sig)
|
||||
{
|
||||
case SIGINT:
|
||||
{
|
||||
signal(sig, SIG_DFL); // reset the handler to its default
|
||||
log->log(1, logContext, "Received a SIGINT. Shutting down...");
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
{
|
||||
signal(sig, SIG_DFL); // reset the handler to its default
|
||||
log->log(1, logContext, "Received a SIGTERM. Shutting down...");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
signal(sig, SIG_DFL); // reset the handler to its default
|
||||
log->log(1, logContext, "Received an unknown signal. Shutting down...");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
app->abort();
|
||||
}
|
||||
|
||||
void App::abort()
|
||||
{
|
||||
shallAbort.set(1);
|
||||
stopComponents();
|
||||
}
|
||||
223
fsck/source/app/App.h
Normal file
223
fsck/source/app/App.h
Normal file
@@ -0,0 +1,223 @@
|
||||
#ifndef APP_H_
|
||||
#define APP_H_
|
||||
|
||||
#include <app/config/Config.h>
|
||||
#include <common/app/log/LogContext.h>
|
||||
#include <common/app/log/Logger.h>
|
||||
#include <common/app/AbstractApp.h>
|
||||
#include <common/nodes/NodeStore.h>
|
||||
#include <common/toolkit/AcknowledgmentStore.h>
|
||||
#include <common/toolkit/NetFilter.h>
|
||||
#include <common/toolkit/NodesTk.h>
|
||||
#include <common/Common.h>
|
||||
#include <common/components/worker/Worker.h>
|
||||
#include <common/components/worker/DummyWork.h>
|
||||
#include <common/components/ComponentInitException.h>
|
||||
#include <common/net/sock/RDMASocket.h>
|
||||
#include <common/nodes/RootInfo.h>
|
||||
#include <common/nodes/TargetMapper.h>
|
||||
#include <common/nodes/LocalNode.h>
|
||||
#include <components/DatagramListener.h>
|
||||
#include <components/InternodeSyncer.h>
|
||||
#include <components/ModificationEventHandler.h>
|
||||
#include <modes/ModeHelp.h>
|
||||
#include <modes/ModeCheckFS.h>
|
||||
#include <modes/ModeEnableQuota.h>
|
||||
#include <net/message/NetMessageFactory.h>
|
||||
|
||||
|
||||
#ifndef BEEGFS_VERSION
|
||||
#error BEEGFS_VERSION undefined
|
||||
#endif
|
||||
|
||||
// program return codes
|
||||
#define APPCODE_NO_ERROR 0
|
||||
#define APPCODE_INVALID_CONFIG 1
|
||||
#define APPCODE_INITIALIZATION_ERROR 2
|
||||
#define APPCODE_COMMUNICATION_ERROR 3
|
||||
#define APPCODE_RUNTIME_ERROR 4
|
||||
#define APPCODE_USER_ABORTED 5
|
||||
|
||||
typedef std::list<Worker*> WorkerList;
|
||||
typedef WorkerList::iterator WorkerListIter;
|
||||
|
||||
|
||||
// forward declarations
|
||||
class LogContext;
|
||||
|
||||
class App : public AbstractApp
|
||||
{
|
||||
public:
|
||||
App(int argc, char** argv);
|
||||
virtual ~App();
|
||||
|
||||
virtual void run() override;
|
||||
|
||||
void abort();
|
||||
virtual void handleComponentException(std::exception& e) override;
|
||||
virtual void handleNetworkInterfaceFailure(const std::string& devname) override;
|
||||
|
||||
bool getShallAbort()
|
||||
{
|
||||
return (shallAbort.read() != 0);
|
||||
}
|
||||
|
||||
private:
|
||||
int appResult;
|
||||
int argc;
|
||||
char** argv;
|
||||
|
||||
AtomicSizeT shallAbort;
|
||||
|
||||
Config* cfg;
|
||||
LogContext* log;
|
||||
|
||||
NetFilter* netFilter;
|
||||
NetFilter* tcpOnlyFilter; // for IPs that allow only plain TCP (no RDMA etc)
|
||||
std::list<std::string> allowedInterfaces;
|
||||
|
||||
std::shared_ptr<Node> localNode;
|
||||
NodeStore* mgmtNodes;
|
||||
NodeStore* metaNodes;
|
||||
NodeStore* storageNodes;
|
||||
RootInfo metaRoot;
|
||||
InternodeSyncer* internodeSyncer;
|
||||
TargetMapper* targetMapper;
|
||||
TargetStateStore* targetStateStore;
|
||||
MirrorBuddyGroupMapper* buddyGroupMapper;
|
||||
MirrorBuddyGroupMapper* metaBuddyGroupMapper;
|
||||
MultiWorkQueue* workQueue;
|
||||
AcknowledgmentStore* ackStore;
|
||||
NetMessageFactory* netMessageFactory;
|
||||
|
||||
DatagramListener* dgramListener;
|
||||
WorkerList workerList;
|
||||
|
||||
ModificationEventHandler* modificationEventHandler;
|
||||
|
||||
Mode* runMode;
|
||||
|
||||
void runNormal();
|
||||
|
||||
void workersInit();
|
||||
void workersStart();
|
||||
void workersStop();
|
||||
void workersDelete();
|
||||
void workersJoin();
|
||||
void initDataObjects(int argc, char** argv);
|
||||
void initLocalNodeInfo();
|
||||
void initComponents();
|
||||
bool initRunMode();
|
||||
void startComponents();
|
||||
void joinComponents();
|
||||
virtual void stopComponents() override;
|
||||
void logInfos();
|
||||
bool waitForMgmtNode();
|
||||
void registerSignalHandler();
|
||||
static void signalHandler(int sig);
|
||||
|
||||
public:
|
||||
virtual const ICommonConfig* getCommonConfig() const override
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
virtual const AbstractNetMessageFactory* getNetMessageFactory() const override
|
||||
{
|
||||
return netMessageFactory;
|
||||
}
|
||||
|
||||
virtual const NetFilter* getNetFilter() const override
|
||||
{
|
||||
return netFilter;
|
||||
}
|
||||
|
||||
virtual const NetFilter* getTcpOnlyFilter() const override
|
||||
{
|
||||
return tcpOnlyFilter;
|
||||
}
|
||||
|
||||
Config* getConfig() const
|
||||
{
|
||||
return cfg;
|
||||
}
|
||||
|
||||
DatagramListener* getDatagramListener() const
|
||||
{
|
||||
return dgramListener;
|
||||
}
|
||||
|
||||
int getAppResult() const
|
||||
{
|
||||
return appResult;
|
||||
}
|
||||
|
||||
NodeStore* getMgmtNodes() const
|
||||
{
|
||||
return mgmtNodes;
|
||||
}
|
||||
|
||||
NodeStore* getMetaNodes()
|
||||
{
|
||||
return metaNodes;
|
||||
}
|
||||
|
||||
NodeStore* getStorageNodes() const
|
||||
{
|
||||
return storageNodes;
|
||||
}
|
||||
|
||||
Node& getLocalNode() const
|
||||
{
|
||||
return *localNode;
|
||||
}
|
||||
|
||||
void updateLocalNicList(NicAddressList& localNicList);
|
||||
|
||||
MultiWorkQueue* getWorkQueue()
|
||||
{
|
||||
return workQueue;
|
||||
}
|
||||
|
||||
InternodeSyncer* getInternodeSyncer()
|
||||
{
|
||||
return internodeSyncer;
|
||||
}
|
||||
|
||||
TargetMapper* getTargetMapper()
|
||||
{
|
||||
return targetMapper;
|
||||
}
|
||||
|
||||
TargetStateStore* getTargetStateStore()
|
||||
{
|
||||
return targetStateStore;
|
||||
}
|
||||
|
||||
MirrorBuddyGroupMapper* getMirrorBuddyGroupMapper()
|
||||
{
|
||||
return buddyGroupMapper;
|
||||
}
|
||||
|
||||
MirrorBuddyGroupMapper* getMetaMirrorBuddyGroupMapper()
|
||||
{
|
||||
return metaBuddyGroupMapper;
|
||||
}
|
||||
|
||||
ModificationEventHandler* getModificationEventHandler()
|
||||
{
|
||||
return modificationEventHandler;
|
||||
}
|
||||
|
||||
void setModificationEventHandler(ModificationEventHandler* handler)
|
||||
{
|
||||
modificationEventHandler = handler;
|
||||
}
|
||||
|
||||
const RootInfo& getMetaRoot() const { return metaRoot; }
|
||||
RootInfo& getMetaRoot() { return metaRoot; }
|
||||
void findAllowedInterfaces(NicAddressList& outList) const;
|
||||
void findAllowedRDMAInterfaces(NicAddressList& outList) const;
|
||||
};
|
||||
|
||||
#endif // APP_H_
|
||||
317
fsck/source/app/config/Config.cpp
Normal file
317
fsck/source/app/config/Config.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
#include <common/toolkit/StringTk.h>
|
||||
#include "Config.h"
|
||||
|
||||
#define IGNORE_CONFIG_CLIENT_VALUE(keyStr) /* to be used in applyConfigMap() */ \
|
||||
if(testConfigMapKeyMatch(iter, keyStr, addDashes) ) \
|
||||
; \
|
||||
else
|
||||
|
||||
// Note: Keep in sync with enum RunMode
|
||||
RunModesElem const __RunModes[] =
|
||||
{
|
||||
{ "--checkfs", RunMode_CHECKFS },
|
||||
{ "--enablequota", RunMode_ENABLEQUOTA },
|
||||
{ NULL, RunMode_INVALID }
|
||||
};
|
||||
|
||||
Config::Config(int argc, char** argv) :
|
||||
AbstractConfig(argc, argv)
|
||||
{
|
||||
initConfig(argc, argv, false, true);
|
||||
logType = LogType_LOGFILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine RunMode from config.
|
||||
* If a valid RunMode exists in the config, the corresponding config element will be erased.
|
||||
*/
|
||||
enum RunMode Config::determineRunMode()
|
||||
{
|
||||
/* test for given help argument, e.g. in case the user wants to see mode-specific help with
|
||||
arguments "--help --<mode>". */
|
||||
|
||||
StringMapIter iter = configMap.find(RUNMODE_HELP_KEY_STRING);
|
||||
if(iter != configMap.end() )
|
||||
{ // user did specify "--help"
|
||||
/* note: it's important to remove the help arg here, because mode help will call this again
|
||||
to find out whether user wants to see mode-specific help. */
|
||||
eraseFromConfigMap(iter);
|
||||
return RunMode_HELP;
|
||||
}
|
||||
|
||||
// walk all defined modes to check whether we find any of them in the config
|
||||
|
||||
for(int i=0; __RunModes[i].modeString != NULL; i++)
|
||||
{
|
||||
iter = configMap.find(__RunModes[i].modeString);
|
||||
if(iter != configMap.end() )
|
||||
{ // we found a valid mode in the config
|
||||
eraseFromConfigMap(iter);
|
||||
return __RunModes[i].runMode;
|
||||
}
|
||||
}
|
||||
|
||||
// no valid mode found
|
||||
|
||||
return RunMode_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default values for each configurable in the configMap.
|
||||
*
|
||||
* @param addDashes true to prepend "--" to all config keys.
|
||||
*/
|
||||
void Config::loadDefaults(bool addDashes)
|
||||
{
|
||||
AbstractConfig::loadDefaults(addDashes);
|
||||
|
||||
// re-definitions
|
||||
configMapRedefine("cfgFile", createDefaultCfgFilename(), addDashes);
|
||||
|
||||
// own definitions
|
||||
configMapRedefine("connInterfacesFile", "", addDashes);
|
||||
|
||||
configMapRedefine("tuneNumWorkers", "32", addDashes);
|
||||
configMapRedefine("tunePreferredNodesFile", "", addDashes);
|
||||
configMapRedefine("tuneDbFragmentSize", "0", addDashes);
|
||||
configMapRedefine("tuneDentryCacheSize", "0", addDashes);
|
||||
|
||||
configMapRedefine("runDaemonized", "false", addDashes);
|
||||
|
||||
configMapRedefine("databasePath", CONFIG_DEFAULT_DBPATH, addDashes);
|
||||
|
||||
configMapRedefine("overwriteDbFile", "false", addDashes);
|
||||
|
||||
configMapRedefine("testDatabasePath", CONFIG_DEFAULT_TESTDBPATH, addDashes);
|
||||
|
||||
configMapRedefine("DatabaseNumMaxConns", "16", addDashes);
|
||||
|
||||
configMapRedefine("overrideRootMDS", "", addDashes);
|
||||
|
||||
configMapRedefine("logStdFile", CONFIG_DEFAULT_LOGFILE, addDashes);
|
||||
configMapRedefine("logOutFile", CONFIG_DEFAULT_OUTFILE, addDashes);
|
||||
configMapRedefine("logNoDate", "false", addDashes);
|
||||
|
||||
configMapRedefine("readOnly", "false", addDashes);
|
||||
|
||||
configMapRedefine("noFetch", "false", addDashes);
|
||||
|
||||
configMapRedefine("automatic", "false", addDashes);
|
||||
|
||||
configMapRedefine("runOffline", "false", addDashes);
|
||||
|
||||
configMapRedefine("forceRestart", "false", addDashes);
|
||||
|
||||
configMapRedefine("quotaEnabled", "false", addDashes);
|
||||
|
||||
configMapRedefine("ignoreDBDiskSpace", "false", addDashes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param addDashes true to prepend "--" to tested config keys for matching.
|
||||
*/
|
||||
void Config::applyConfigMap(bool enableException, bool addDashes)
|
||||
{
|
||||
AbstractConfig::applyConfigMap(false, addDashes);
|
||||
|
||||
for (StringMapIter iter = configMap.begin(); iter != configMap.end();)
|
||||
{
|
||||
bool unknownElement = false;
|
||||
|
||||
IGNORE_CONFIG_CLIENT_VALUE("logClientID")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("logType")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connNumCommRetries")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connUnmountRetries")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connCommRetrySecs")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connMaxConcurrentAttempts")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAInterfacesFile")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connTCPFallbackEnabled")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connMessagingTimeouts")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connInterfacesList")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMATimeouts")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAFragmentSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAKeyType")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaFragmentSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaBufNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaBufSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheType")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePagedIOBufSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePagedIOBufNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheBufSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheBufNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePageCacheValidityMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneAttribCacheValidityMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxWriteWorks")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWorks")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneAllowMultiSetWrite")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneAllowMultiSetRead")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePathBufSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePathBufNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWriteNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWriteNodesNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMsgBufSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMsgBufNum")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneRemoteFSync")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePreferredMetaFile")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tunePreferredStorageFile")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneUseGlobalFileLocks")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneRefreshOnGetAttr")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneInodeBlockBits")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneInodeBlockSize")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxClientMirrorSize") // was removed, kept here for compat
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneEarlyCloseResponse")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneUseGlobalAppendLocks")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneUseBufferedAppend")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneStatFsCacheSecs")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysCacheInvalidationVersion")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysCreateHardlinksAsSymlinks")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysMountSanityCheckMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysSyncOnClose")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysSessionCheckOnClose")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysSessionChecksEnabled")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysTargetOfflineTimeoutSecs")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysInodeIDStyle")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysACLsEnabled")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysXAttrsEnabled")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysBypassFileAccessCheckOnMeta")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysXAttrsCheckCapabilities")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneDirSubentryCacheValidityMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneFileSubentryCacheValidityMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneENOENTCacheValidityMS")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneCoherentBuffers")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysFileEventLogMask")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("sysRenameEbusyAsXdev")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("tuneNumRetryWorkers")
|
||||
IGNORE_CONFIG_CLIENT_VALUE("connHelperdPortTCP") // was removed, kept here for compat
|
||||
|
||||
if (testConfigMapKeyMatch(iter, "connInterfacesFile", addDashes))
|
||||
connInterfacesFile = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "tuneNumWorkers", addDashes))
|
||||
tuneNumWorkers = StringTk::strToUInt(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "tunePreferredNodesFile", addDashes))
|
||||
tunePreferredNodesFile = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "tuneDbFragmentSize", addDashes))
|
||||
tuneDbFragmentSize = StringTk::strToUInt64(iter->second.c_str());
|
||||
else if (testConfigMapKeyMatch(iter, "tuneDentryCacheSize", addDashes))
|
||||
tuneDentryCacheSize = StringTk::strToUInt64(iter->second.c_str());
|
||||
else if (testConfigMapKeyMatch(iter, "runDaemonized", addDashes))
|
||||
runDaemonized = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "databasePath", addDashes))
|
||||
databasePath = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "overwriteDbFile", addDashes))
|
||||
overwriteDbFile = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "testDatabasePath", addDashes))
|
||||
testDatabasePath = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "databaseNumMaxConns", addDashes))
|
||||
databaseNumMaxConns = StringTk::strHexToUInt(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "overrideRootMDS", addDashes))
|
||||
overrideRootMDS = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "logStdFile", addDashes))
|
||||
logStdFile = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "logOutFile", addDashes))
|
||||
logOutFile = iter->second;
|
||||
else if (testConfigMapKeyMatch(iter, "readOnly", addDashes))
|
||||
readOnly = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "noFetch", addDashes))
|
||||
noFetch = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "automatic", addDashes))
|
||||
automatic = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "runOffline", addDashes))
|
||||
runOffline = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "forceRestart", addDashes))
|
||||
forceRestart = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "quotaEnabled", addDashes))
|
||||
quotaEnabled = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "ignoreDBDiskSpace", addDashes))
|
||||
ignoreDBDiskSpace = StringTk::strToBool(iter->second);
|
||||
else if (testConfigMapKeyMatch(iter, "checkMalformedChunk", addDashes))
|
||||
checkFsActions.set(CHECK_MALFORMED_CHUNK);
|
||||
else if (testConfigMapKeyMatch(iter, "checkFilesWithMissingTargets", addDashes))
|
||||
checkFsActions.set(CHECK_FILES_WITH_MISSING_TARGETS);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOrphanedDentryByIDFiles", addDashes))
|
||||
checkFsActions.set(CHECK_ORPHANED_DENTRY_BYIDFILES);
|
||||
else if (testConfigMapKeyMatch(iter, "checkDirEntriesWithBrokenIDFile", addDashes))
|
||||
checkFsActions.set(CHECK_DIRENTRIES_WITH_BROKENIDFILE);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOrphanedChunk", addDashes))
|
||||
checkFsActions.set(CHECK_ORPHANED_CHUNK);
|
||||
else if (testConfigMapKeyMatch(iter, "checkChunksInWrongPath", addDashes))
|
||||
checkFsActions.set(CHECK_CHUNKS_IN_WRONGPATH);
|
||||
else if (testConfigMapKeyMatch(iter, "checkWrongInodeOwner", addDashes))
|
||||
checkFsActions.set(CHECK_WRONG_INODE_OWNER);
|
||||
else if (testConfigMapKeyMatch(iter, "checkWrongOwnerInDentry", addDashes))
|
||||
checkFsActions.set(CHECK_WRONG_OWNER_IN_DENTRY);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOrphanedContDir", addDashes))
|
||||
checkFsActions.set(CHECK_ORPHANED_CONT_DIR);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOrphanedDirInode", addDashes))
|
||||
checkFsActions.set(CHECK_ORPHANED_DIR_INODE);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOrphanedFileInode", addDashes))
|
||||
checkFsActions.set(CHECK_ORPHANED_FILE_INODE);
|
||||
else if (testConfigMapKeyMatch(iter, "checkDanglingDentry", addDashes))
|
||||
checkFsActions.set(CHECK_DANGLING_DENTRY);
|
||||
else if (testConfigMapKeyMatch(iter, "checkMissingContDir", addDashes))
|
||||
checkFsActions.set(CHECK_MISSING_CONT_DIR);
|
||||
else if (testConfigMapKeyMatch(iter, "checkWrongFileAttribs", addDashes))
|
||||
checkFsActions.set(CHECK_WRONG_FILE_ATTRIBS);
|
||||
else if (testConfigMapKeyMatch(iter, "checkWrongDirAttribs", addDashes))
|
||||
checkFsActions.set(CHECK_WRONG_DIR_ATTRIBS);
|
||||
else if (testConfigMapKeyMatch(iter, "checkOldStyledHardlinks", addDashes))
|
||||
checkFsActions.set(CHECK_OLD_STYLED_HARDLINKS);
|
||||
else
|
||||
{
|
||||
// unknown element occurred
|
||||
unknownElement = true;
|
||||
|
||||
if (enableException)
|
||||
{
|
||||
throw InvalidConfigException("The config argument '" + iter->first + "' is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
// advance iterator (and remove handled element)
|
||||
|
||||
if (unknownElement)
|
||||
{
|
||||
// just skip the unknown element
|
||||
iter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remove this element from the map
|
||||
iter = eraseFromConfigMap(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::initImplicitVals()
|
||||
{
|
||||
// tuneNumWorkers
|
||||
if (!tuneNumWorkers)
|
||||
tuneNumWorkers = BEEGFS_MAX(System::getNumOnlineCPUs() * 2, 4);
|
||||
|
||||
if (!tuneDbFragmentSize)
|
||||
tuneDbFragmentSize = uint64_t(sysconf(_SC_PHYS_PAGES) ) * sysconf(_SC_PAGESIZE) / 2;
|
||||
|
||||
// just blindly assume that 384 bytes will be enough for a single cache entry. should be
|
||||
if (!tuneDentryCacheSize)
|
||||
tuneDentryCacheSize = tuneDbFragmentSize / 384;
|
||||
|
||||
// read in connAuthFile only if we are running as root.
|
||||
// if not root, the program will abort anyway
|
||||
if(!geteuid())
|
||||
{
|
||||
AbstractConfig::initConnAuthHash(connAuthFile, &connAuthHash);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Config::createDefaultCfgFilename() const
|
||||
{
|
||||
struct stat statBuf;
|
||||
|
||||
const int statRes = stat(CONFIG_DEFAULT_CFGFILENAME, &statBuf);
|
||||
|
||||
if (!statRes && S_ISREG(statBuf.st_mode))
|
||||
return CONFIG_DEFAULT_CFGFILENAME; // there appears to be a config file
|
||||
|
||||
return ""; // no default file otherwise
|
||||
}
|
||||
|
||||
224
fsck/source/app/config/Config.h
Normal file
224
fsck/source/app/config/Config.h
Normal file
@@ -0,0 +1,224 @@
|
||||
#ifndef CONFIG_H_
|
||||
#define CONFIG_H_
|
||||
|
||||
#include <common/app/config/AbstractConfig.h>
|
||||
#include <bitset>
|
||||
|
||||
#define CONFIG_DEFAULT_CFGFILENAME "/etc/beegfs/beegfs-client.conf"
|
||||
#define CONFIG_DEFAULT_LOGFILE "/var/log/beegfs-fsck.log"
|
||||
#define CONFIG_DEFAULT_OUTFILE "/var/log/beegfs-fsck.out"
|
||||
#define CONFIG_DEFAULT_DBPATH "/var/lib/beegfs/"
|
||||
#define CONFIG_DEFAULT_TESTDBPATH "/tmp/beegfs-fsck/"
|
||||
|
||||
#define RUNMODE_HELP_KEY_STRING "--help" /* key for usage help */
|
||||
#define __RUNMODES_SIZE \
|
||||
( (sizeof(__RunModes) ) / (sizeof(RunModesElem) ) - 1)
|
||||
/* -1 because last elem is NULL */
|
||||
|
||||
enum CheckFsActions
|
||||
{
|
||||
CHECK_MALFORMED_CHUNK = 0,
|
||||
CHECK_FILES_WITH_MISSING_TARGETS = 1,
|
||||
CHECK_ORPHANED_DENTRY_BYIDFILES = 2,
|
||||
CHECK_DIRENTRIES_WITH_BROKENIDFILE = 3,
|
||||
CHECK_ORPHANED_CHUNK = 4,
|
||||
CHECK_CHUNKS_IN_WRONGPATH = 5,
|
||||
CHECK_WRONG_INODE_OWNER = 6,
|
||||
CHECK_WRONG_OWNER_IN_DENTRY = 7,
|
||||
CHECK_ORPHANED_CONT_DIR = 8,
|
||||
CHECK_ORPHANED_DIR_INODE = 9,
|
||||
CHECK_ORPHANED_FILE_INODE = 10,
|
||||
CHECK_DANGLING_DENTRY = 11,
|
||||
CHECK_MISSING_CONT_DIR = 12,
|
||||
CHECK_WRONG_FILE_ATTRIBS = 13,
|
||||
CHECK_WRONG_DIR_ATTRIBS = 14,
|
||||
CHECK_OLD_STYLED_HARDLINKS = 15,
|
||||
CHECK_FS_ACTIONS_COUNT = 16
|
||||
};
|
||||
|
||||
// Note: Keep in sync with __RunModes array
|
||||
enum RunMode
|
||||
{
|
||||
RunMode_CHECKFS = 0,
|
||||
RunMode_ENABLEQUOTA = 1,
|
||||
RunMode_HELP = 2,
|
||||
RunMode_INVALID = 3 /* not valid as index in RunModes array */
|
||||
};
|
||||
|
||||
struct RunModesElem
|
||||
{
|
||||
const char* modeString;
|
||||
enum RunMode runMode;
|
||||
};
|
||||
|
||||
|
||||
extern RunModesElem const __RunModes[];
|
||||
|
||||
class Config : public AbstractConfig
|
||||
{
|
||||
public:
|
||||
Config(int argc, char** argv);
|
||||
|
||||
enum RunMode determineRunMode();
|
||||
|
||||
private:
|
||||
|
||||
// configurables
|
||||
|
||||
std::string connInterfacesFile;
|
||||
|
||||
unsigned tuneNumWorkers;
|
||||
std::string tunePreferredNodesFile;
|
||||
size_t tuneDbFragmentSize;
|
||||
size_t tuneDentryCacheSize;
|
||||
|
||||
bool runDaemonized;
|
||||
|
||||
std::string databasePath;
|
||||
bool overwriteDbFile;
|
||||
|
||||
// only relevant for unit testing, to give the used databasePath
|
||||
std::string testDatabasePath;
|
||||
|
||||
unsigned databaseNumMaxConns;
|
||||
|
||||
std::string overrideRootMDS; // not tested well, should only be used by developers
|
||||
|
||||
// file for fsck output (not the log messages, but the output, which is also on the console)
|
||||
std::string logOutFile;
|
||||
|
||||
bool readOnly;
|
||||
bool noFetch;
|
||||
bool automatic;
|
||||
bool runOffline;
|
||||
bool forceRestart;
|
||||
bool quotaEnabled;
|
||||
bool ignoreDBDiskSpace;
|
||||
|
||||
std::bitset<CHECK_FS_ACTIONS_COUNT> checkFsActions;
|
||||
|
||||
// internals
|
||||
virtual void loadDefaults(bool addDashes) override;
|
||||
virtual void applyConfigMap(bool enableException, bool addDashes) override;
|
||||
virtual void initImplicitVals() override;
|
||||
std::string createDefaultCfgFilename() const;
|
||||
|
||||
public:
|
||||
// getters & setters
|
||||
const StringMap* getUnknownConfigArgs() const
|
||||
{
|
||||
return getConfigMap();
|
||||
}
|
||||
|
||||
const std::string& getConnInterfacesFile() const
|
||||
{
|
||||
return connInterfacesFile;
|
||||
}
|
||||
|
||||
unsigned getTuneNumWorkers() const
|
||||
{
|
||||
return tuneNumWorkers;
|
||||
}
|
||||
|
||||
size_t getTuneDbFragmentSize() const
|
||||
{
|
||||
return tuneDbFragmentSize;
|
||||
}
|
||||
|
||||
size_t getTuneDentryCacheSize() const
|
||||
{
|
||||
return tuneDentryCacheSize;
|
||||
}
|
||||
|
||||
const std::string& getTunePreferredNodesFile() const
|
||||
{
|
||||
return tunePreferredNodesFile;
|
||||
}
|
||||
|
||||
bool getRunDaemonized() const
|
||||
{
|
||||
return runDaemonized;
|
||||
}
|
||||
|
||||
const std::string& getDatabasePath() const
|
||||
{
|
||||
return databasePath;
|
||||
}
|
||||
|
||||
bool getOverwriteDbFile() const
|
||||
{
|
||||
return overwriteDbFile;
|
||||
}
|
||||
|
||||
const std::string& getTestDatabasePath() const
|
||||
{
|
||||
return testDatabasePath;
|
||||
}
|
||||
|
||||
unsigned getDatabaseNumMaxConns() const
|
||||
{
|
||||
return databaseNumMaxConns;
|
||||
}
|
||||
|
||||
std::string getOverrideRootMDS() const
|
||||
{
|
||||
return overrideRootMDS;
|
||||
}
|
||||
|
||||
bool getReadOnly() const
|
||||
{
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
bool getNoFetch() const
|
||||
{
|
||||
return noFetch;
|
||||
}
|
||||
|
||||
bool getAutomatic() const
|
||||
{
|
||||
return automatic;
|
||||
}
|
||||
|
||||
const std::string& getLogOutFile() const
|
||||
{
|
||||
return logOutFile;
|
||||
}
|
||||
|
||||
bool getRunOffline() const
|
||||
{
|
||||
return runOffline;
|
||||
}
|
||||
|
||||
bool getForceRestart() const
|
||||
{
|
||||
return forceRestart;
|
||||
}
|
||||
|
||||
bool getQuotaEnabled() const
|
||||
{
|
||||
return quotaEnabled;
|
||||
}
|
||||
|
||||
bool getIgnoreDBDiskSpace() const
|
||||
{
|
||||
return ignoreDBDiskSpace;
|
||||
}
|
||||
|
||||
std::bitset<CHECK_FS_ACTIONS_COUNT> getCheckFsActions() const
|
||||
{
|
||||
return checkFsActions;
|
||||
}
|
||||
|
||||
void disableAutomaticRepairMode()
|
||||
{
|
||||
this->automatic = false;
|
||||
}
|
||||
|
||||
void setReadOnly()
|
||||
{
|
||||
this->readOnly = true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /*CONFIG_H_*/
|
||||
Reference in New Issue
Block a user