00001
00002
00003
00004
00005
00006
00013 #include "define.h"
00014 #include "FountainWireProt.h"
00015 #include "NodeID.h"
00016 #include "LokiInclude.h"
00017 #include <bamboo/libbamboo.h>
00018 #include <bamboo/qLog.h>
00019 #include <bamboo/SSSXML.h>
00020 #include <bamboo/ConfigReader.h>
00021 #include <bamboo/TypeConvert.h>
00022 #include <bamboo/ServiceDir.h>
00023 #include <memory>
00024 #include <sstream>
00025 #include <cstddef>
00026 #include <iostream>
00027
00028 using namespace BambooLib;
00029 using namespace Loki;
00030 using std::ostringstream;
00031 using std::string;
00032 using std::auto_ptr;
00033 using std::cout;
00034 using std::cerr;
00035 using std::endl;
00036
00040 enum AdminMode {
00041 invalidMode = 0,
00042 admin,
00043 trace,
00044 bomb,
00045 set,
00046 numAdminModes
00047 };
00048
00054 bool parseArgs(int argc, char **argv);
00055
00060 void version(char* name);
00061
00067 void usage(char** argv, AdminMode mode);
00068
00073 const char* fountain_convert(AdminMode t);
00074
00080 bool fountain_convert(const char* s, AdminMode& a);
00081
00085 void cleanUp();
00086
00091 void handleAdminResponse(const ParseMsg* responseMessage);
00092
00097 void handleSetResponse(const ParseMsg* responseMessage);
00098
00103 void handleTraceResponse(const ParseMsg* responseMessage);
00104
00109 void handleBombResponse(const ParseMsg* responseMessage);
00110
00111
00112 ConfigReader& config(ConfigReader::getInstance());
00113 qLog& qLogger(qLog::getInstance());
00114 ServiceDir& serviceDir(ServiceDir::getInstance());
00115 AdminMode userMode = admin;
00116
00117
00118 bool killServer = false;
00119 bool stats = false;
00120 bool flushDatabase = false;
00121 bool treeTopology = false;
00122 bool rebuildTree = false;
00123 unsigned int rebuildTreeDegree = 0;
00124 qLog_Levels serverLoggingLevel = badLevel;
00125 bool forceDiscover = false;
00126 bool reloadConfig = false;
00127
00128 #if ENABLE_NODE_DAEMONS == 1
00129
00130 bool traceExtendedOutput = false;
00131
00132
00133 string bombNodeIdValue;
00134 #endif
00135
00136
00137 RMAP_Relation_Operator_Type nodeIdOp;
00138 string nodeIdValue;
00139 string nodeStateValue;
00140
00141
00142 int main(int argc, char** argv) {
00143 if (BambooLib::Setup() == FAILURE) {
00144 cerr << "Failed to initialize Bamboo Library\n";
00145 exit(EXIT_FAILURE);
00146 }
00147
00148
00149 ScopeGuard cleanupGuard = MakeGuard(&cleanUp);
00150
00151 try {
00152
00153 if (!parseArgs(argc, argv)) {
00154 usage(argv, userMode);
00155 return EXIT_FAILURE;
00156 }
00157
00158 auto_ptr<SSSWireProt> wireProt(ENFORCE(serviceDir.ObtainConnection(NodeMonitor))("Could not connect to Fountain"));
00159
00160
00161 BuildMsg requestMessage(sss_convert(envelopeElement));
00162 requestMessage.NewMasterName(sss_convert(requestElement));
00163 XMLElement* baseElement = requestMessage.getWorkingElement();
00164 if (userMode != set) {
00165 baseElement->addChildElement("Object", sss_convert(serverObject));
00166 } else {
00167 baseElement->addChildElement("Object", sss_convert(nodeObject));
00168 }
00169 XMLElement* requestDataElement = baseElement->addChildElement(sss_convert(dataElement));
00170 if (userMode == admin) {
00171 baseElement->addAttribute("action", FountainMessage::fountain_convert(FountainMessage::admin));
00172 if (killServer) requestDataElement->addChildElement("KillServer", "true");
00173 if (flushDatabase) requestDataElement->addChildElement("FlushDatabase", "true");
00174 if (serverLoggingLevel != badLevel) {
00175 requestDataElement->addChildElement("ServerLoggingLevel", qLog::levelToText(serverLoggingLevel));
00176 }
00177 if (treeTopology) {
00178 requestDataElement->addChildElement("TreeTopology", "true");
00179 }
00180 if (stats) {
00181 requestDataElement->addChildElement("ServerStats", "true");
00182 }
00183 if (rebuildTree) {
00184 XMLElement* rebuildElement = requestDataElement->addChildElement("RebuildTree", "true");
00185 if (rebuildTreeDegree != 0) {
00186 ostringstream temp;
00187 temp << rebuildTreeDegree;
00188 rebuildElement->addAttribute("degree", temp.str().c_str());
00189 }
00190 }
00191 if (reloadConfig) {
00192 requestDataElement->addChildElement("ReloadConfig", "true");
00193 }
00194
00195 if (forceDiscover) {
00196 XMLElement* serverDataSourceElement = requestDataElement->addChildElement("ServerData");
00197 if (forceDiscover) {
00198 serverDataSourceElement->addChildElement("Discover", "true");
00199 }
00200 }
00201 # if ENABLE_NODE_DAEMONS == 1
00202 } else if (userMode == trace) {
00203 baseElement->addAttribute("action", "trace");
00204 } else if (userMode == bomb) {
00205 baseElement->addAttribute("action", "bomb");
00206 if (bombNodeIdValue.empty()) {
00207 requestDataElement->addChildElement("bombRegEx", ".*");
00208 } else {
00209 requestDataElement->addChildElement("bombRegEx", bombNodeIdValue.c_str());
00210 }
00211 # endif
00212 } else if (userMode == set) {
00213 baseElement->addAttribute("action", "Modify");
00214
00215
00216
00217 if (!nodeIdValue.empty()) {
00218 XMLElement* whereElementPtr = baseElement->addChildElement(sss_convert(whereElement), nodeIdValue.c_str());
00219 whereElementPtr->addAttribute("name", "NodeId");
00220 whereElementPtr->addAttribute("op", sss_convert(nodeIdOp));
00221 }
00222 if (!nodeStateValue.empty()) {
00223 XMLElement* setElementPtr = baseElement->addChildElement(sss_convert(setElement), nodeStateValue.c_str());
00224 setElementPtr->addAttribute("name", "State");
00225 } else {
00227 }
00228 } else {
00229 ENFORCE(false)("Unknown userMode");
00230 }
00231
00232 ENFORCE(wireProt->sendMessage(&requestMessage))("Error sending ")(fountain_convert(userMode))(" request to fountain server");
00233 ParseMsg* resultMessage = ENFORCE(wireProt->recvMessage())("Received zero length message response from fountain server");
00234 if ((qLogger.getLevel() != QLOG_MSGDEBUG) && (!resultMessage->getStatus())) {
00235 cout << "Received Failure response from fountain server!" << endl;
00236 if (resultMessage->getResponseMessage()) {
00237 cout << "Message: " << resultMessage->getResponseMessage() << endl;
00238 }
00239 } else {
00240 if (userMode == admin) {
00241 handleAdminResponse(resultMessage);
00242 } else if (userMode == set) {
00243 handleSetResponse(resultMessage);
00244 # if ENABLE_NODE_DAEMONS == 1
00245 } else if (userMode == trace) {
00246 handleTraceResponse(resultMessage);
00247 } else if (userMode == bomb) {
00248 handleBombResponse(resultMessage);
00249 # endif
00250 } else {
00251 ENFORCE(false)("Unknown userMode");
00252 }
00253 }
00254 } catch (const FountainException& e) {
00255 DebugMessageStream(QLOG_ERR) << e.what();
00256 exit(EXIT_FAILURE);
00257 }
00258
00259
00260
00261
00262 cleanupGuard.Dismiss();
00263 cleanUp();
00264 return EXIT_SUCCESS;
00265 }
00266
00267 void cleanUp() {
00268 BambooLib::Shutdown();
00269 }
00270
00271 void handleAdminResponse(const ParseMsg* responseMessage) {
00272 if (qLogger.getLevel() != QLOG_MSGDEBUG) {
00273 XMLElement* dataElement = responseMessage->getDataElement();
00274 if (dataElement == NULL) {
00275 cerr << "Missing <Data> element in Fountain server response" << endl;
00276 } else {
00277 auto_ptr<XMLElementList> serverStatsList(dataElement->getElementsByName("ServerStats"));
00278 if ((serverStatsList.get() != NULL) && (serverStatsList->length() > 0)) {
00279 cout << "Fountain Statistics:" << endl;
00280 cout << "===============================" << endl;
00281 XMLElement* serverStats = serverStatsList->item(0);
00282 auto_ptr<XMLElementList> uptimeList(serverStats->getElementsByName("Uptime"));
00283 if ((uptimeList.get() != NULL) && (uptimeList->length() > 0)) {
00284 const char* uptime = uptimeList->item(0)->getValue();
00285 if (uptime != NULL) cout << "Server Uptime: " << uptime << endl;
00286 }
00287
00288 auto_ptr<XMLElementList> serverLoggingList(serverStats->getElementsByName("ServerLoggingLevel"));
00289 if ((serverLoggingList.get() != NULL) && (serverLoggingList->length() > 0)) {
00290 const char* serverLoggingLevelValue = serverLoggingList->item(0)->getValue();
00291 if (serverLoggingLevelValue != NULL) cout << "Server Logging Level: " << serverLoggingLevelValue << endl;
00292 }
00293
00294 auto_ptr<XMLElementList> managersList(serverStats->getElementsByName("Managers"));
00295 if ((managersList.get() != NULL) && (managersList->length() > 0)) {
00296 const char* managers = managersList->item(0)->getValue();
00297 if (managers != NULL) cout << "List of managers: " << managers << endl;
00298 }
00299
00300 auto_ptr<XMLElementList> nodesList(serverStats->getElementsByName("Nodes"));
00301 if ((nodesList.get() != NULL) && (nodesList->length() > 0)) {
00302 const char* nodes = nodesList->item(0)->getValue();
00303 if (nodes != NULL) cout << "Number of nodes in monitor database: " << nodes << endl;
00304 }
00305
00306 auto_ptr<XMLElementList> queryIntervalList(serverStats->getElementsByName("QueryInterval"));
00307 if ((queryIntervalList.get() != NULL) && (queryIntervalList->length() > 0)) {
00308 const char* queryInterval = queryIntervalList->item(0)->getValue();
00309 if (queryInterval != NULL) cout << "Query interval: " << queryInterval << " seconds" << endl;
00310 }
00311
00312 auto_ptr<XMLElementList> treeRecoveriesList(serverStats->getElementsByName("TreeRecoveries"));
00313 if ((treeRecoveriesList.get() != NULL) && (treeRecoveriesList->length() > 0)) {
00314 const char* treeRecoveries = treeRecoveriesList->item(0)->getValue();
00315 if (treeRecoveries != NULL) cout << "Total tree recoveries: " << treeRecoveries << endl;
00316 }
00317
00318 auto_ptr<XMLElementList> treeRebuildsList(serverStats->getElementsByName("TreeRebuilds"));
00319 if ((treeRebuildsList.get() != NULL) && (treeRebuildsList->length() > 0)) {
00320 const char* treeRebuilds = treeRebuildsList->item(0)->getValue();
00321 if (treeRebuilds != NULL) cout << "Total tree rebuilds: " << treeRebuilds << endl;
00322 }
00323
00324 # if ENABLE_INFINIBAND == 1
00325 auto_ptr<XMLElementList> infinibandStatisticsList(serverStats->getElementsByName("Infiniband"));
00326 if ((infinibandStatisticsList.get() != NULL) && (infinibandStatisticsList->length() > 0)) {
00327 XMLElement* infinibandElement = infinibandStatisticsList->item(0);
00328 auto_ptr<XMLElementList> discoveryElementList(infinibandElement->getElementsByName("Discovery"));
00329 if ((discoveryElementList.get() != NULL) && (discoveryElementList->length() > 0)) {
00330 XMLElement* discoveryElement = discoveryElementList->item(0);
00331 auto_ptr<XMLElementList> discoveryIntervalList(discoveryElement->getElementsByName("Interval"));
00332 if ((discoveryIntervalList.get() != NULL) && (discoveryIntervalList->length() > 0)) {
00333 const char* discoveryInterval = discoveryIntervalList->item(0)->getValue();
00334 if (discoveryInterval) cout << "Infiniband Network discovery interval: " << discoveryInterval << " seconds" << endl;
00335 }
00336
00337 auto_ptr<XMLElementList> discoveryTimeList(discoveryElement->getElementsByName("Time"));
00338 if ((discoveryTimeList.get() != NULL) && (discoveryTimeList->length() > 0)) {
00339 const char* discoveryTime = discoveryTimeList->item(0)->getValue();
00340 if (discoveryTime) cout << "Infiniband Network discovery time: " << discoveryTime << endl;
00341 }
00342 }
00343
00344 auto_ptr<XMLElementList> pollElementList(infinibandElement->getElementsByName("Poll"));
00345 if ((pollElementList.get() != NULL) && (pollElementList->length() > 0)) {
00346 XMLElement* pollElement = pollElementList->item(0);
00347 auto_ptr<XMLElementList> pollIntervalList(pollElement->getElementsByName("Interval"));
00348 if ((pollIntervalList.get() != NULL) && (pollIntervalList->length() > 0)) {
00349 const char* pollInterval = pollIntervalList->item(0)->getValue();
00350 if (pollInterval) cout << "Infiniband Network poll interval: " << pollInterval << " seconds" << endl;
00351 }
00352
00353 auto_ptr<XMLElementList> pollTimeList(pollElement->getElementsByName("Time"));
00354 if ((pollTimeList.get() != NULL) && (pollTimeList->length() > 0)) {
00355 const char* pollTime = pollTimeList->item(0)->getValue();
00356 if (pollTime) cout << "Infiniband Network poll time: " << pollTime << endl;
00357 }
00358 }
00359 }
00360 # endif
00361
00362 auto_ptr<XMLElementList> requestsList(serverStats->getElementsByName("Requests"));
00363 if ((requestsList.get() != NULL) && (requestsList->length() > 0)) {
00364 XMLElement* requests = requestsList->item(0);
00365 auto_ptr<XMLElementList> totalRequests(requests->getElementsByName("TotalRequests"));
00366 if ((totalRequests.get() != NULL) && (totalRequests->length() > 0)) {
00367 cout << "Total requests: " << totalRequests->item(0)->getValue() << endl;
00368 }
00369 auto_ptr<XMLElementList> totalMalformedRequests(requests->getElementsByName("TotalMalformedRequests"));
00370 if ((totalMalformedRequests.get() != NULL) && (totalMalformedRequests->length() > 0)) {
00371 cout << "Total malformed requests: " << totalMalformedRequests->item(0)->getValue() << endl;
00372 }
00373 auto_ptr<XMLElementList> adminRequests(requests->getElementsByName("AdminRequests"));
00374 if ((adminRequests.get() != NULL) && (adminRequests->length() > 0)) {
00375 cout << "Admin requests: " << adminRequests->item(0)->getValue() << endl;
00376 }
00377 auto_ptr<XMLElementList> adminMalformedRequests(requests->getElementsByName("AdminMalformedRequests"));
00378 if ((adminMalformedRequests.get() != NULL) && (adminMalformedRequests->length() > 0)) {
00379 cout << "Admin malformed requests: " << adminMalformedRequests->item(0)->getValue() << endl;
00380 }
00381 auto_ptr<XMLElementList> nodeMonitorRequests(requests->getElementsByName("NodeMonitorRequests"));
00382 if ((nodeMonitorRequests.get() != NULL) && (nodeMonitorRequests->length() > 0)) {
00383 cout << "Node monitor requests: " << nodeMonitorRequests->item(0)->getValue() << endl;
00384 }
00385 auto_ptr<XMLElementList> nodeMonitorMalformedRequests(requests->getElementsByName("NodeMonitorMalformedRequests"));
00386 if ((nodeMonitorMalformedRequests.get() != NULL) && (nodeMonitorMalformedRequests->length() > 0)) {
00387 cout << "Node monitor malformed requests: " << nodeMonitorMalformedRequests->item(0)->getValue() << endl;
00388 }
00389 }
00390
00391 auto_ptr<XMLElementList> buildDateList(serverStats->getElementsByName("BuildDate"));
00392 if ((buildDateList.get() != NULL) && (buildDateList->length() > 0)) {
00393 XMLElement* buildDate = buildDateList->item(0);
00394 if (buildDate->getValue()) {
00395 cout << "Build date: " << buildDate->getValue() << endl;
00396 }
00397 }
00398
00399 auto_ptr<XMLElementList> buildArgumentsList(serverStats->getElementsByName("BuildArguments"));
00400 if ((buildArgumentsList.get() != NULL) && (buildArgumentsList->length() > 0)) {
00401 XMLElement* buildArguments = buildArgumentsList->item(0);
00402 if (buildArguments->getValue()) {
00403 cout << "Build arguments: " << buildArguments->getValue() << endl;
00404 }
00405 }
00406
00407 cout << endl;
00408 } else if (stats) {
00409 cerr << "Missing <ServerStats> Data element in Fountain server response" << endl;
00410 }
00411
00412
00413 auto_ptr<XMLElementList> treeTopologyList(dataElement->getElementsByName("TreeTopology"));
00414 if ((treeTopologyList.get() != NULL) && (treeTopologyList->length() > 0)) {
00415 cout << "Fountain Tree Structure:" << endl;
00416 cout << "===============================" << endl;
00417 XMLElement* treeTopologyXml = treeTopologyList->item(0);
00418 auto_ptr<XMLElementList> treeTopologyXmlChildren(treeTopologyXml->getElementsByName("Node"));
00419 if ((treeTopologyXmlChildren.get() != NULL) && (treeTopologyXmlChildren->length() > 0)) {
00420 for (unsigned int i=0; i < treeTopologyXmlChildren->length(); i++) {
00421 XMLElement* currNode = treeTopologyXmlChildren->item(i);
00422 cout << i << " " << currNode->getAttributeValue("ID") << endl;
00423 }
00424 cout << endl;
00425 }
00426 }
00427 }
00428
00429 if (responseMessage->getResponseMessage() != NULL) {
00430 cout << "Message:" << endl << responseMessage->getResponseMessage() << endl;
00431 }
00432 }
00433 return;
00434 }
00435
00436 void handleSetResponse(const ParseMsg* responseMessage) {
00437
00438 }
00439
00440 #if ENABLE_NODE_DAEMONS == 1
00441 void handleTraceResponse(const ParseMsg* responseMessage) {
00442 if (qLogger.getLevel() != QLOG_MSGDEBUG) {
00443 XMLElement* dataXML = responseMessage->getDataElement();
00444 auto_ptr<XMLElementList> nodeListList(dataXML->getElementsByName("NodeList"));
00445 if ((nodeListList.get() != NULL) && (nodeListList->length() > 0)) {
00446 auto_ptr<XMLElementList> children(nodeListList->item(0)->getChildren());
00447 for (unsigned int i=0; i < children->length(); i++) {
00448 XMLElement* node = children->item(i);
00449 const char* ID = node->getAttributeValue("ID");
00450 if (ID == NULL) continue;
00451 if (traceExtendedOutput) {
00452 cout << "Node ID: " << ID << endl;
00453 auto_ptr<XMLElementList> nodeChildren(node->getChildren());
00454 for (unsigned int j=0; j < nodeChildren->length(); j++) {
00455 if (nodeChildren->item(j)->isName("Status")) {
00456 XMLElement* status = nodeChildren->item(j);
00457 auto_ptr<XMLElementList> statusValueList(status->getElementsByName("Value"));
00458 if ((statusValueList.get() != NULL) && (statusValueList->length() > 0)) {
00459 const char* statusValue = statusValueList->item(0)->getValue();
00460 if (statusValue != NULL) cout << "\tStatus: " << statusValue << endl;
00461 }
00462 auto_ptr<XMLElementList> messageList(status->getElementsByName("Message"));
00463 if ((messageList.get() != NULL) && (messageList->length() > 0)) {
00464 const char* message = messageList->item(0)->getValue();
00465 if (message != NULL) cout << "\tMessage: " << message << endl;
00466 }
00467 } else if (nodeChildren->item(j)->isName("Parent")) {
00468 XMLElement* parent = nodeChildren->item(j);
00469 if (parent->getAttributeValue("ID")) {
00470 cout << "\tParent: " << parent->getAttributeValue("ID") << endl;
00471 }
00472 }
00473 }
00474 cout << endl;
00475 } else {
00476 cout << ID << endl;
00477 }
00478 }
00479 cout << endl << endl;
00480 } else {
00481 cout << "Missing NodeList data element in response message!" << endl;
00482 }
00483 }
00484 return;
00485 }
00486
00487 void handleBombResponse(const ParseMsg* responseMessage) {
00488 if (qLogger.getLevel() != QLOG_MSGDEBUG) {
00489 XMLElement* dataXML = responseMessage->getDataElement();
00490 if (dataXML == NULL) {
00491 cerr << "Missing data element in Fountain server response!" << endl;
00492 } else {
00493 auto_ptr<XMLElementList> nodeList(dataXML->getElementsByName("NodeList"));
00494 if ((nodeList.get() == NULL) || (nodeList->length() <= 0)) {
00495 cerr << "Missing NodeList element in reply from Fountain server!" << endl;
00496 } else {
00497 auto_ptr<XMLElementList> nodeListChildren(nodeList->item(0)->getChildren());
00498 if ((nodeListChildren.get() == NULL) || (nodeListChildren->length() <= 0)) {
00499 cerr << "Missing NodeList child elements in reply from Fountain server!" << endl;
00500 } else {
00501 cout << "The following nodes exited:" << endl;
00502 for (unsigned int i=0; i < nodeListChildren->length(); i++) {
00503 const char* node = nodeListChildren->item(i)->getAttributeValue("ID");
00504 if (node) {
00505 const char* exitStatus = nodeListChildren->item(i)->getAttributeValue("Exit");
00506 if ((exitStatus) && (!strcmp(exitStatus, "true"))) {
00507 cout << node << " ";
00508 }
00509 }
00510 }
00511 cout << endl;
00512 }
00513 }
00514 }
00515 }
00516
00517 return;
00518 }
00519 #endif
00520
00521 bool parseArgs(int argc, char** argv) {
00522 int argInd = 1;
00523 char * textpart;
00524 string configFile;
00525 bool dumpWireMsg = false;
00526
00527 if (argInd < argc) {
00528
00529 if (!fountain_convert(argv[argInd], userMode)) {
00530 cout << "Could not convert \"" << argv[argInd] << "\" into userMode, assuming admin mode" << endl;
00531 } else {
00532 argInd++;
00533 }
00534 }
00535
00536 while(argInd < argc) {
00537 if (argv[argInd][0] == '-') {
00538 char arg = argv[argInd][1];
00539 if (arg == 'v') {
00540 version(argv[0]);
00541 return false;
00542 } else if (arg == 'h') {
00543 return false;
00544 } else if (arg == 'd') {
00545 dumpWireMsg = true;
00546 } else if ((arg != '-') && (userMode == admin)) {
00547 switch(arg) {
00548 # if ENABLE_NODE_DAEMONS == 1
00549 case 't':
00550 treeTopology = true;
00551 break;
00552 # endif
00553 case 'k':
00554 killServer = true;
00555 break;
00556 case 's':
00557 stats = true;
00558 break;
00559 case 'f':
00560 flushDatabase = true;
00561 break;
00562 default:
00563 cerr << "Invalid Argument: " << argv[argInd] << endl;
00564 return false;
00565 break;
00566 }
00567 # if ENABLE_NODE_DAEMONS == 1
00568 } else if ((arg != '-') && (userMode == trace)) {
00569 switch(arg) {
00570 case 'x':
00571 traceExtendedOutput = true;
00572 break;
00573 default:
00574 cerr << "Invalid Argument: " << argv[argInd] << endl;
00575 return false;
00576 break;
00577 }
00578 # endif
00579 } else if (arg == '-') {
00580 textpart = (argv[argInd]+2);
00581 if (!strcmp(textpart,"help")) {
00582 return false;
00583 } else if (!strcmp(textpart,"version")) {
00584 version(argv[0]);
00585 return false;
00586 } else if (!strcmp(textpart, "debug")) {
00587 dumpWireMsg = true;
00588 } else if (!strcmp(textpart,"config")) {
00589 if ((argInd+1) == argc) {
00590 return false;
00591 }
00592 configFile = argv[argInd+1];
00593 argInd++;
00594 # if ENABLE_NODE_DAEMONS == 1
00595 } else if ((userMode == bomb) && !strcmp(textpart, "node")) {
00596 if ((argInd+1) == argc) {
00597 return false;
00598 }
00599 bombNodeIdValue = argv[argInd+1];
00600 argInd++;
00601 } else if ((userMode == admin) && !strcmp(textpart, "tree")) {
00602 treeTopology = true;
00603 # endif
00604 } else if ((userMode == admin) && !strcmp(textpart, "kill")) {
00605 killServer = true;
00606 } else if ((userMode == admin) && !strcmp(textpart, "flush")) {
00607 flushDatabase = true;
00608 # if ENABLE_NODE_DAEMONS == 1
00609 } else if ((userMode == admin) && !strcmp(textpart, "rebuild")) {
00610 rebuildTree = true;
00611
00612 if (argInd+1 < argc) {
00613
00614
00615 if (isdigit(argv[argInd+1][0])) {
00616 if (!TypeConvert::fromString(argv[argInd+1], rebuildTreeDegree)) {
00617 cerr << "Conversion of string " << argv[argInd+1] << " to unsigned int failed" << endl;
00618 return false;
00619 }
00620 argInd++;
00621 }
00622 }
00623 # endif
00624 } else if ((userMode == admin) && !strcmp(textpart, "log")) {
00625 if (argInd+1 >= argc) {
00626 cerr << "Please give a logging level after --log" << endl;
00627 return false;
00628 }
00629 serverLoggingLevel = qLog::levelFromText(argv[argInd+1]);
00630 if (serverLoggingLevel == badLevel) {
00631 cerr << "The level \"" << argv[argInd+1] << "\" is not a valid logging level!" << endl;
00632 return false;
00633 }
00634 argInd++;
00635 } else if ((userMode == admin) && !strcmp(textpart, "stats")) {
00636 stats = true;
00637 } else if ((userMode == admin) && !strcmp(textpart, "discover")) {
00638 forceDiscover = true;
00639 } else if ((userMode == admin) && !strcmp(textpart, "reload")) {
00640 reloadConfig = true;
00641 } else if ((userMode == set) && !strcmp(textpart, "node")) {
00642 if ((argInd+1) < argc) {
00643 textpart = argv[argInd+1];
00644 while (((argInd+1) < argc) && (textpart[0] != '-')) {
00645 if ((nodeIdOp == RO_Invalid) && (sss_convert(textpart, nodeIdOp))) {
00646 if ((nodeIdOp != RO_RegEx) && (nodeIdOp != RO_NotEqual) && (nodeIdOp != RO_Equal)) {
00647 cerr << "Please only use like, eq, or ne for --node" << endl;
00648 exit(EXIT_FAILURE);
00649 }
00650 argInd++;
00651 } else if (nodeIdOp == RO_Invalid) {
00652 cerr << "Please give --node op before value \"" << textpart << "\"" << endl;
00653 return FAILURE;
00654 } else {
00655 nodeIdValue = textpart;
00656 argInd++;
00657 }
00658 if ((argInd+1) < argc) textpart = argv[argInd+1];
00659 }
00660 if ((nodeIdOp != RO_Invalid) && (nodeIdValue.length() == 0)) {
00661 cerr << "Please give a value to compare the nodeId with" << endl;
00662 return FAILURE;
00663 }
00664 }
00665 } else if ((userMode == set) && !strcmp(textpart, "state")) {
00666 if ((argInd+1) == argc) {
00667 return false;
00668 }
00669 argInd++;
00670 nodeStateValue = argv[argInd];
00671 if (!nodeStateValue.compare("Up")) {
00672
00673 } else if (!nodeStateValue.compare("Down")) {
00674
00675 } else if (!nodeStateValue.compare("Unavailable")) {
00676
00677 } else if (!nodeStateValue.compare("Invalid")) {
00678
00679 } else {
00680 cerr << "Use either \"Up\", \"Down\", \"Unavailable\", or \"Invalid\" to set node state" << endl;
00681 exit(EXIT_FAILURE);
00682 }
00683 argInd++;
00684 # if ENABLE_NODE_DAEMONS == 1
00685 } else if ((userMode == trace) && !strcmp(textpart, "extended")) {
00686 traceExtendedOutput = true;
00687 # endif
00688 } else {
00689 cerr << "Invalid Argument: " << argv[argInd] << endl;
00690 return false;
00691 }
00692 }
00693 } else {
00694 cerr << "Invalid Argument: " << argv[argInd] << endl;
00695 return false;
00696 }
00697 argInd++;
00698 }
00699
00700
00701 if (configFile.length() == 0) {
00702 configFile.append(DEFAULT_CONFIG_FILE);
00703 }
00704 if (config.readFile(configFile.c_str()) != FAILURE) {
00705 ostringstream msg;
00706 cout << "read config file \"" << configFile << "\"" << endl;
00707 }
00708 config.readEnvVars();
00709
00710
00711 if (dumpWireMsg) {
00712 qLogger.setThreshold(QLOG_MSGDEBUG);
00713 } else {
00714 qLogger.setThreshold(QLOG_INFO);
00715 }
00716 qLogger.fileOutput(false);
00717 qLogger.screenOutput(true);
00718
00719 return true;
00720 }
00721
00722 void usage(char** argv, AdminMode mode) {
00723 switch(mode) {
00724 case admin:
00725 cout << argv[0] << " [admin ";
00726 # if ENABLE_NODE_DAEMONS == 1
00727 cout << " | trace | bomb ";
00728 # endif
00729 cout << "| set] ";
00730 cout << "[options]" << endl;
00731 cout << "Options:" << endl;
00732 # if ENABLE_NODE_DAEMONS == 1
00733 cout << "\t -t | --tree : Prints the fountain node tree structure." << endl;
00734 # endif
00735 cout << "\t -k | --kill : Requests the server to shutdown." << endl;
00736 cout << "\t -f | --flush : Requests the server to erase its node monitor database and start over from scratch." << endl;
00737 # if ENABLE_NODE_DAEMONS == 1
00738 cout << "\t --rebuild [degree] : Requests the master Fountain node to rebuild the tree topology using the optional degree parameter." << endl;
00739 # endif
00740 cout << "\t -s | --stats : Requests the server to respond with statistical information." << endl;
00741 cout << "\t --reload : Force the Fountain server to reload its config file." << endl;
00742 cout << "\t --discover : Force a server specific datasource discovery." << endl;
00743 cout << "\t --log <level> : Change the current server logging level." << endl;
00744 cout << "\t possible values include:\n"
00745 << "\t QLOG_EMERG, QLOG_ALERT, QLOG_CRIT, QLOG_ERR, QLOG_WARNING,\n"
00746 << "\t QLOG_NOTICE, QLOG_INFO, QLOG_DEBUG, QLOG_MSGDEBUG" << endl;
00747 break;
00748 case trace:
00749 cout << argv[0] << " trace [options]\n";
00750 cout << "\t -x : Display additional information about each node." << endl;
00751 break;
00752 case bomb:
00753 cout << argv[0] << " bomb [options]\n";
00754 cout << "\t --node value : Bomb only the specified node ID(s) using regular expression matching." << endl;
00755 break;
00756 case set:
00757 cout << argv[0] << " set [options]\n";
00758 cout << "\t --node [[op] [value]] : Specify the node to set. Use the \"like\" op for regular expression matching." << endl;
00759 cout << "\t --state <Up | Down | Unavailable | Invalid> : The node state value to set." << endl;
00760 break;
00761 default:
00762
00763 break;
00764 }
00765
00766 cout << "\t --config <file> : Path to config file, otherwise it's assumed to be " << DEFAULT_CONFIG_FILE << endl;
00767 cout << "\t -d | --debug : Dump raw messages sent to and from the Fountain server. No other output will be displayed." << endl;
00768 cout << "\t -v | --version : Display version information." << endl;
00769 cout << "\t -h | --help : Display this help screen." << endl;
00770 }
00771
00772 void version(char* name) {
00773 cout << name << " - Fountain client utility - Version " << FOUNTAIN_VERSION_STRING << endl;
00774 }
00775
00776 const char* fountain_convert(AdminMode t) {
00777 const char* result =