diff options
Diffstat (limited to 'src/Client')
-rw-r--r-- | src/Client/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Client/CommandManager.cpp | 335 | ||||
-rw-r--r-- | src/Client/CommandManager.h | 85 | ||||
-rw-r--r-- | src/Client/CommandParser.cpp | 331 | ||||
-rw-r--r-- | src/Client/CommandParser.h | 15 | ||||
-rw-r--r-- | src/Client/InformationManager.cpp | 30 | ||||
-rw-r--r-- | src/Client/InformationManager.h | 17 | ||||
-rw-r--r-- | src/Client/Requests/DaemonCommandRequest.h | 4 | ||||
-rw-r--r-- | src/Client/Requests/DaemonFSInfoRequest.h | 3 | ||||
-rw-r--r-- | src/Client/Requests/DaemonListRequest.h | 3 | ||||
-rw-r--r-- | src/Client/Requests/DaemonStatusRequest.h | 3 |
11 files changed, 338 insertions, 490 deletions
diff --git a/src/Client/CMakeLists.txt b/src/Client/CMakeLists.txt index fd8922d..00b72c5 100644 --- a/src/Client/CMakeLists.txt +++ b/src/Client/CMakeLists.txt @@ -2,5 +2,5 @@ add_subdirectory(Requests) include_directories(${INCLUDES}) -add_library(Client CommandManager.cpp CommandParser.cpp InformationManager.cpp) +add_library(Client CommandParser.cpp InformationManager.cpp) target_link_libraries(Client ClientRequests Common) diff --git a/src/Client/CommandManager.cpp b/src/Client/CommandManager.cpp deleted file mode 100644 index 6c643f2..0000000 --- a/src/Client/CommandManager.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * CommandManager.cpp - * - * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "CommandManager.h" -#include <Common/HostInfo.h> -#include <Common/Logger.h> -#include <Common/Request.h> - -#include <cmath> -#include <iostream> -#include <vector> - - -namespace Mad { -namespace Client { - -CommandManager CommandManager::commandManager; - - -void CommandManager::printFSInfo(const Common::XmlPacket &packet) { - const std::string units[] = { - "kB", "MB", "GB", "TB", "" - }; - - for(size_t i = 0; i < packet["filesystems"].getSize(); ++i) { - const Common::XmlPacket::Entry &fs = packet["filesystems"][i]; - - unsigned usedUnit = 0, totalUnit = 0; - - float used = fs["usedSize"]; - float total = fs["totalSize"]; - float available = fs["availableSize"]; - - while(used >= 1024 && !units[usedUnit+1].empty()) { - ++usedUnit; - used /= 1024; - available /= 1024; - } - - while(total >= 1024 && !units[totalUnit+1].empty()) { - ++totalUnit; - total /= 1024; - } - - - std::string name = fs["name"]; - std::string mountedOn = fs["mountedOn"]; - - std::string nameString = mountedOn + " (" + name + ")"; - - if(nameString.length() < 32) { - nameString.resize(32, ' '); - } - else { - nameString += "\n\t"; - nameString.resize(nameString.length() + 32, ' '); - } - - std::printf("\t%s%.*f%s", nameString.c_str(), (used < 10) ? 2 : 1, used, (usedUnit == totalUnit) ? "" : (" " + units[usedUnit]).c_str()); - std::printf("/%.*f %s (%.1f%%)\n", (total < 10) ? 2 : 1, total, units[totalUnit].c_str(), std::min(100*used/(used+available), 100.0f)); - } - - std::printf("\n"); -} - -void CommandManager::printHostStatus(const Common::XmlPacket &packet) { - unsigned long uptime = packet["uptime"]; - - if(uptime) { - unsigned long uptime = packet["uptime"]; - - unsigned long days = uptime/86400; - unsigned long hours = (uptime%86400)/3600; - unsigned long minutes = (uptime%3600)/60; - - std::printf("\tUptime:\t\t"); - - if(days) std::printf("%lu days ", days); - - std::printf("%lu:%02lu", hours, minutes); - - std::printf(" (load average: %.2f %.2f %.2f, %lu processes)", (float)packet["loadAvg1"], (float)packet["loadAvg5"], (float)packet["loadAvg15"], (unsigned long)packet["nProcesses"]); - - std::printf("\n\n"); - } - - if((unsigned long)packet["totalMem"] && (unsigned long)packet["freeMem"]) { - const std::string units[] = { - "kB", "MB", "GB", "TB", "" - }; - - unsigned unit = 0; - float totalMem = packet["totalMem"], usedMem = totalMem-(float)packet["freeMem"]; - - while(totalMem >= 1024 && !units[unit+1].empty()) { - ++unit; - totalMem /= 1024; - usedMem /= 1024; - } - - std::printf("\tMemory usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str()); - std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); - - if((unsigned long)packet["totalSwap"] && (unsigned long)packet["freeSwap"]) { - unit = 0; - totalMem = packet["totalSwap"]; usedMem = totalMem-(float)packet["freeSwap"]; - - while(totalMem >= 1024 && !units[unit+1].empty()) { - ++unit; - totalMem /= 1024; - usedMem /= 1024; - } - - std::printf("\tSwap usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str()); - std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); - } - - std::printf("\n"); - } -} - - -void CommandManager::daemonCommandRequestFinished(Common::Request &request) { - try { - request.getResult(); - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::daemonFSInfoRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - std::cout << "Host file system usage:" << std::endl; - printFSInfo(packet); - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::daemonStatusRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - std::cout << "Host status:" << std::endl; - printHostStatus(packet); - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::disconnectRequestFinished(Common::Request &request) { - try { - request.getResult(); - disconnect = true; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::fsInfoRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - std::cout << "Server file system usage:" << std::endl; - printFSInfo(packet); - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::statusRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - std::cout << "Server status:" << std::endl; - printHostStatus(packet); - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::userInfoRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - - std::cout << " " << (unsigned long)packet["uid"] << ", " << (unsigned long)packet["gid"] << ", " << (const std::string&)packet["username"] << ", " - << (const std::string&)packet["fullName"] << std::endl << std::endl; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::userListRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - - const Common::XmlPacket::Element &users = packet["users"]; - - if(users.isEmpty()) { - std::cout << "User list is empty." << std::endl; - } - else { - std::cout << "Found " << users.getSize() << " user" << (users.getSize()==1 ? "" : "s") << ":" << std::endl; - - - for(size_t i = 0; i < users.getSize(); ++i) - std::cout << " " << (unsigned long)users[i]["uid"] << ", " << (unsigned long)users[i]["gid"] << ", " << (const std::string&)users[i]["username"] << ", " << (const std::string&)users[i]["fullName"] << std::endl; - } - - std::cout << std::endl; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::userGroupListRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - - const Common::XmlPacket::Element &groups = packet["groups"]; - - if(groups.isEmpty()) { - std::cout << "The user isn't member of any group." << std::endl; - } - else { - - std::cout << "User is member of " << groups.getSize() << " group" << (groups.getSize()==1 ? "" : "s") << ":" << std::endl; - - - for(size_t i = 0; i < groups.getSize(); ++i) - std::cout << " " << (unsigned long)groups[i]["gid"] << std::endl; - } - - std::cout << std::endl; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::groupListRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - - const Common::XmlPacket::Element &groups = packet["groups"]; - - if(groups.isEmpty()) { - std::cout << "Group list is empty." << std::endl; - } - else { - std::cout << "Found " << groups.getSize() << " group" << (groups.getSize()==1 ? "" : "s") << ":" << std::endl; - - - for(size_t i = 0; i < groups.getSize(); ++i) - std::cout << " " << (unsigned long)groups[i]["gid"] << ", " << (const std::string&)groups[i]["name"] << std::endl; - } - - std::cout << std::endl; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -void CommandManager::groupUserListRequestFinished(Common::Request &request) { - try { - const Common::XmlPacket &packet = request.getResult(); - - const Common::XmlPacket::Element &users = packet["users"]; - - if(users.isEmpty()) { - std::cout << "The group doesn't have any members." << std::endl; - } - else { - - std::cout << "The group has " << users.getSize() << " member" << (users.getSize()==1 ? "" : "s") << ":" << std::endl; - - - for(size_t i = 0; i < users.getSize(); ++i) - std::cout << " " << (unsigned long)users[i]["uid"] << std::endl; - } - - std::cout << std::endl; - } - catch(Net::Exception &exception) { - Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", exception.strerror().c_str()); - } - - requestFinished(); -} - -} -} diff --git a/src/Client/CommandManager.h b/src/Client/CommandManager.h deleted file mode 100644 index 3c51bd3..0000000 --- a/src/Client/CommandManager.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * CommandManager.h - * - * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MAD_CLIENT_COMMANDMANAGER_H_ -#define MAD_CLIENT_COMMANDMANAGER_H_ - -#include <Net/Signals/Signals.h> - -namespace Mad { - -namespace Common { -class XmlPacket; -class Request; -} - -namespace Client { - -class CommandManager { - private: - friend class CommandParser; - - static CommandManager commandManager; - - unsigned int activeRequests; - - Net::Signals::Signal0 finished; - - bool disconnect; - - void requestFinished() { - activeRequests--; - - finished.emit(); - } - - void printFSInfo(const Common::XmlPacket &packet); - void printHostStatus(const Common::XmlPacket &packet); - - void daemonCommandRequestFinished(Common::Request &request); - void daemonFSInfoRequestFinished(Common::Request &request); - void daemonStatusRequestFinished(Common::Request &request); - void disconnectRequestFinished(Common::Request &request); - void fsInfoRequestFinished(Common::Request &request); - void statusRequestFinished(Common::Request &request); - void userInfoRequestFinished(Common::Request &request); - void userListRequestFinished(Common::Request &request); - void userGroupListRequestFinished(Common::Request &request); - void groupListRequestFinished(Common::Request &request); - void groupUserListRequestFinished(Common::Request &request); - - CommandManager() : activeRequests(0), disconnect(false) {} - - public: - static CommandManager *get() { - return &commandManager; - } - - bool requestsActive() {return (activeRequests > 0);} - bool willDisconnect() {return disconnect;} - - Net::Signals::Connection connectSignalFinished(const Net::Signals::Signal0::slot_type &slot) { - return finished.connect(slot); - } -}; - -} -} - -#endif /* MAD_CLIENT_COMMANDMANAGER_H_ */ diff --git a/src/Client/CommandParser.cpp b/src/Client/CommandParser.cpp index 4c395b7..2a67dab 100644 --- a/src/Client/CommandParser.cpp +++ b/src/Client/CommandParser.cpp @@ -116,18 +116,138 @@ std::map<std::string, Common::HostInfo> CommandParser::parseHostList(const std:: } +void CommandParser::printFSInfo(boost::shared_ptr<const Common::XmlPacket> &packet) { + const std::string units[] = { + "kB", "MB", "GB", "TB", "" + }; + + for(size_t i = 0; i < (*packet)["filesystems"].getSize(); ++i) { + const Common::XmlPacket::Entry &fs = (*packet)["filesystems"][i]; + + unsigned usedUnit = 0, totalUnit = 0; + + float used = fs["usedSize"]; + float total = fs["totalSize"]; + float available = fs["availableSize"]; + + while(used >= 1024 && !units[usedUnit+1].empty()) { + ++usedUnit; + used /= 1024; + available /= 1024; + } + + while(total >= 1024 && !units[totalUnit+1].empty()) { + ++totalUnit; + total /= 1024; + } + + + std::string name = fs["name"]; + std::string mountedOn = fs["mountedOn"]; + + std::string nameString = mountedOn + " (" + name + ")"; + + if(nameString.length() < 32) { + nameString.resize(32, ' '); + } + else { + nameString += "\n\t"; + nameString.resize(nameString.length() + 32, ' '); + } + + std::printf("\t%s%.*f%s", nameString.c_str(), (used < 10) ? 2 : 1, used, (usedUnit == totalUnit) ? "" : (" " + units[usedUnit]).c_str()); + std::printf("/%.*f %s (%.1f%%)\n", (total < 10) ? 2 : 1, total, units[totalUnit].c_str(), std::min(100*used/(used+available), 100.0f)); + } + + std::printf("\n"); +} + +void CommandParser::printHostStatus(boost::shared_ptr<const Common::XmlPacket> &packet) { + unsigned long uptime = (*packet)["uptime"]; + + if(uptime) { + unsigned long uptime = (*packet)["uptime"]; + + unsigned long days = uptime/86400; + unsigned long hours = (uptime%86400)/3600; + unsigned long minutes = (uptime%3600)/60; + + std::printf("\tUptime:\t\t"); + + if(days) std::printf("%lu days ", days); + + std::printf("%lu:%02lu", hours, minutes); + + std::printf(" (load average: %.2f %.2f %.2f, %lu processes)", (float)(*packet)["loadAvg1"], (float)(*packet)["loadAvg5"], (float)(*packet)["loadAvg15"], (unsigned long)(*packet)["nProcesses"]); + + std::printf("\n\n"); + } + + if((unsigned long)(*packet)["totalMem"] && (unsigned long)(*packet)["freeMem"]) { + const std::string units[] = { + "kB", "MB", "GB", "TB", "" + }; + + unsigned unit = 0; + float totalMem = (*packet)["totalMem"], usedMem = totalMem-(float)(*packet)["freeMem"]; + + while(totalMem >= 1024 && !units[unit+1].empty()) { + ++unit; + totalMem /= 1024; + usedMem /= 1024; + } + + std::printf("\tMemory usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str()); + std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); + + if((unsigned long)(*packet)["totalSwap"] && (unsigned long)(*packet)["freeSwap"]) { + unit = 0; + totalMem = (*packet)["totalSwap"]; usedMem = totalMem-(float)(*packet)["freeSwap"]; + + while(totalMem >= 1024 && !units[unit+1].empty()) { + ++unit; + totalMem /= 1024; + usedMem /= 1024; + } + + std::printf("\tSwap usage:\t%.*f/%.*f %s", (usedMem < 10) ? 2 : 1, usedMem, (totalMem < 10) ? 2 : 1, totalMem, units[unit].c_str()); + std::printf(" (%.1f%%)\n", usedMem*100.0f/totalMem); + } + + std::printf("\n"); + } +} + + void CommandParser::fsinfoCommand(const std::vector<std::string> &args) { + boost::shared_ptr<Common::Request> request; + if(args.size() == 1) - Common::RequestManager::get()->sendRequest0<Common::Requests::FSInfoRequest>(connection, boost::bind(&CommandManager::fsInfoRequestFinished, CommandManager::get(), _1)); + request = boost::shared_ptr<Common::Requests::FSInfoRequest>(new Common::Requests::FSInfoRequest); else if(args.size() == 2) - Common::RequestManager::get()->sendRequest1<Requests::DaemonFSInfoRequest>(connection, args[1], boost::bind(&CommandManager::daemonFSInfoRequestFinished, CommandManager::get(), _1)); + request = boost::shared_ptr<Requests::DaemonFSInfoRequest>(new Requests::DaemonFSInfoRequest(args[1])); else { Common::Logger::logf(Common::Logger::ERROR, "%s: Too many arguments.", args[0].c_str()); printUsage("fsinfo"); return; } - ++CommandManager::get()->activeRequests; + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + if(args.size() == 1) + std::cout << "Server file system usage:" << std::endl; + else + std::cout << "Host file system usage:" << std::endl; + + printFSInfo(result.first); + } } void CommandParser::helpCommand(const std::vector<std::string> &args) { @@ -220,12 +340,23 @@ void CommandParser::rebootCommand(const std::vector<std::string> &args) { std::map<std::string, Common::HostInfo> hosts = parseHostList(std::vector<std::string>(args.begin()+1, args.end()), true); + std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> > requests; + for(std::map<std::string, Common::HostInfo>::iterator host = hosts.begin(); host != hosts.end(); ++host) { - Common::RequestManager::get()->sendRequest2<Requests::DaemonCommandRequest>(connection, - host->first, true, boost::bind(&CommandManager::daemonCommandRequestFinished, CommandManager::get(), _1) - ); + boost::shared_ptr<Requests::DaemonCommandRequest> request(new Requests::DaemonCommandRequest(host->first, true)); + Common::RequestManager::get()->sendRequest(connection, request); + + requests.push_back(request); + } + + for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) + (*request)->wait(); - ++CommandManager::get()->activeRequests; + for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) { + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = (*request)->getResult(); + + if(result.second) + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); } } @@ -238,29 +369,55 @@ void CommandParser::shutdownCommand(const std::vector<std::string> &args) { std::map<std::string, Common::HostInfo> hosts = parseHostList(std::vector<std::string>(args.begin()+1, args.end()), true); + std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> > requests; + for(std::map<std::string, Common::HostInfo>::iterator host = hosts.begin(); host != hosts.end(); ++host) { - Common::RequestManager::get()->sendRequest2<Requests::DaemonCommandRequest>(connection, - host->first, false, boost::bind(&CommandManager::daemonCommandRequestFinished, CommandManager::get(), _1) - ); + boost::shared_ptr<Requests::DaemonCommandRequest> request(new Requests::DaemonCommandRequest(host->first, false)); + Common::RequestManager::get()->sendRequest(connection, request); - ++CommandManager::get()->activeRequests; + requests.push_back(request); + } + + for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) + (*request)->wait(); + + for(std::vector<boost::shared_ptr<Requests::DaemonCommandRequest> >::iterator request = requests.begin(); request != requests.end(); ++request) { + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = (*request)->getResult(); + + if(result.second) + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); } } void CommandParser::statusCommand(const std::vector<std::string> &args) { + boost::shared_ptr<Common::Request> request; + if(args.size() == 1) - Common::RequestManager::get()->sendRequest0<Common::Requests::StatusRequest>(connection, - boost::bind(&CommandManager::statusRequestFinished, CommandManager::get(), _1)); + request = boost::shared_ptr<Common::Requests::StatusRequest>(new Common::Requests::StatusRequest); else if(args.size() == 2) - Common::RequestManager::get()->sendRequest1<Requests::DaemonStatusRequest>(connection, - args[1], boost::bind(&CommandManager::daemonStatusRequestFinished, CommandManager::get(), _1)); + request = boost::shared_ptr<Requests::DaemonStatusRequest>(new Requests::DaemonStatusRequest(args[1])); else { Common::Logger::logf(Common::Logger::ERROR, "%s: Too many arguments.", args[0].c_str()); printUsage("status"); return; } - ++CommandManager::get()->activeRequests; + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + if(args.size() == 1) + std::cout << "Server status:" << std::endl; + else + std::cout << "Host status:" << std::endl; + + printHostStatus(result.first); + } } void CommandParser::userInfoCommand(const std::vector<std::string> &args) { @@ -283,17 +440,50 @@ void CommandParser::userInfoCommand(const std::vector<std::string> &args) { return; } - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::UserInfoRequest> request(new Common::Requests::UserInfoRequest(uid)); + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + const Common::XmlPacket &packet = *result.first; - Common::RequestManager::get()->sendRequest1<Common::Requests::UserInfoRequest>(connection, - uid, boost::bind(&CommandManager::userInfoRequestFinished, CommandManager::get(), _1)); + std::cout << " " << (unsigned long)packet["uid"] << ", " << (unsigned long)packet["gid"] << ", " << (const std::string&)packet["username"] << ", " + << (const std::string&)packet["fullName"] << std::endl << std::endl; + } } void CommandParser::listUsersCommand(const std::vector<std::string>&) { - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::UserListRequest> request(new Common::Requests::UserListRequest); + + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + const Common::XmlPacket::Element &users = (*result.first)["users"]; + + if(users.isEmpty()) { + std::cout << "User list is empty." << std::endl; + } + else { + std::cout << "Found " << users.getSize() << " user" << (users.getSize()==1 ? "" : "s") << ":" << std::endl; + + + for(size_t i = 0; i < users.getSize(); ++i) + std::cout << " " << (unsigned long)users[i]["uid"] << ", " << (unsigned long)users[i]["gid"] << ", " << (const std::string&)users[i]["username"] << ", " << (const std::string&)users[i]["fullName"] << std::endl; + } - Common::RequestManager::get()->sendRequest0<Common::Requests::UserListRequest>(connection, - boost::bind(&CommandManager::userListRequestFinished, CommandManager::get(), _1)); + std::cout << std::endl; + } } void CommandParser::listUserGroupsCommand(const std::vector<std::string> &args) { @@ -316,17 +506,61 @@ void CommandParser::listUserGroupsCommand(const std::vector<std::string> &args) return; } - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::UserGroupListRequest> request(new Common::Requests::UserGroupListRequest(uid)); + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + const Common::XmlPacket::Element &groups = (*result.first)["groups"]; + + if(groups.isEmpty()) { + std::cout << "The user isn't member of any group." << std::endl; + } + else { + + std::cout << "User is member of " << groups.getSize() << " group" << (groups.getSize()==1 ? "" : "s") << ":" << std::endl; + + + for(size_t i = 0; i < groups.getSize(); ++i) + std::cout << " " << (unsigned long)groups[i]["gid"] << std::endl; + } - Common::RequestManager::get()->sendRequest1<Common::Requests::UserGroupListRequest>(connection, - uid, boost::bind(&CommandManager::userGroupListRequestFinished, CommandManager::get(), _1)); + std::cout << std::endl; + } } void CommandParser::listGroupsCommand(const std::vector<std::string>&) { - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::GroupListRequest> request(new Common::Requests::GroupListRequest); + + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); + + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + const Common::XmlPacket::Element &groups = (*result.first)["groups"]; - Common::RequestManager::get()->sendRequest0<Common::Requests::GroupListRequest>(connection, - boost::bind(&CommandManager::groupListRequestFinished, CommandManager::get(), _1)); + if(groups.isEmpty()) { + std::cout << "Group list is empty." << std::endl; + } + else { + std::cout << "Found " << groups.getSize() << " group" << (groups.getSize()==1 ? "" : "s") << ":" << std::endl; + + + for(size_t i = 0; i < groups.getSize(); ++i) + std::cout << " " << (unsigned long)groups[i]["gid"] << ", " << (const std::string&)groups[i]["name"] << std::endl; + } + + std::cout << std::endl; + } } void CommandParser::listGroupUsersCommand(const std::vector<std::string> &args) { @@ -349,17 +583,46 @@ void CommandParser::listGroupUsersCommand(const std::vector<std::string> &args) return; } - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::GroupUserListRequest> request(new Common::Requests::GroupUserListRequest(gid)); + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); - Common::RequestManager::get()->sendRequest1<Common::Requests::GroupUserListRequest>(connection, - gid, boost::bind(&CommandManager::groupUserListRequestFinished, CommandManager::get(), _1)); + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(!result.first || result.second) { + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + } + else { + const Common::XmlPacket::Element &users = (*result.first)["users"]; + + if(users.isEmpty()) { + std::cout << "The group doesn't have any members." << std::endl; + } + else { + + std::cout << "The group has " << users.getSize() << " member" << (users.getSize()==1 ? "" : "s") << ":" << std::endl; + + + for(size_t i = 0; i < users.getSize(); ++i) + std::cout << " " << (unsigned long)users[i]["uid"] << std::endl; + } + + std::cout << std::endl; + } } void CommandParser::exitCommand(const std::vector<std::string>&) { - ++CommandManager::get()->activeRequests; + boost::shared_ptr<Common::Requests::DisconnectRequest> request(new Common::Requests::DisconnectRequest); + + Common::RequestManager::get()->sendRequest(connection, request); + request->wait(); - Common::RequestManager::get()->sendRequest0<Common::Requests::DisconnectRequest>(connection, - boost::bind(&CommandManager::disconnectRequestFinished, CommandManager::get(), _1)); + std::pair<boost::shared_ptr<const Common::XmlPacket>, Net::Exception> result = request->getResult(); + + if(result.second) + Common::Logger::logf(Common::Logger::ERROR, "An error occurred during your request: %s.", result.second.strerror().c_str()); + else + disconnect = true; } bool CommandParser::parse(const std::string &cmd) { diff --git a/src/Client/CommandParser.h b/src/Client/CommandParser.h index 692eb7e..ca9b59e 100644 --- a/src/Client/CommandParser.h +++ b/src/Client/CommandParser.h @@ -20,8 +20,10 @@ #ifndef MAD_CLIENT_COMMANDPARSER_H_ #define MAD_CLIENT_COMMANDPARSER_H_ -#include "CommandManager.h" #include <Common/HostInfo.h> +#include <Common/XmlPacket.h> + +#include <boost/smart_ptr.hpp> #include <map> #include <string> @@ -52,11 +54,16 @@ class CommandParser { Common::Connection *connection; + bool disconnect; + const Command* findCommand(const std::string& command); void printUsage(const std::string& command); std::map<std::string, Common::HostInfo> parseHostList(const std::vector<std::string> &args, bool mustBeActive = false); + void printFSInfo(boost::shared_ptr<const Common::XmlPacket> &packet); + void printHostStatus(boost::shared_ptr<const Common::XmlPacket> &packet); + void fsinfoCommand(const std::vector<std::string> &args); void helpCommand(const std::vector<std::string> &args); void listHostsCommand(const std::vector<std::string> &args); @@ -70,7 +77,7 @@ class CommandParser { void listGroupUsersCommand(const std::vector<std::string> &args); void exitCommand(const std::vector<std::string>&); - CommandParser() : connection(0) {} + CommandParser() : connection(0), disconnect(false) {} public: static CommandParser *get() { @@ -90,6 +97,10 @@ class CommandParser { void requestDisconnect() { exitCommand(std::vector<std::string>()); } + + bool willDisconnect() const { + return disconnect; + } }; } diff --git a/src/Client/InformationManager.cpp b/src/Client/InformationManager.cpp index 78a0cf7..03a71c6 100644 --- a/src/Client/InformationManager.cpp +++ b/src/Client/InformationManager.cpp @@ -29,8 +29,8 @@ namespace Client { InformationManager InformationManager::informationManager; -void InformationManager::DaemonStateUpdateRequestHandler::handlePacket(const Common::XmlPacket &packet) { - if(packet.getType() != "UpdateHostState") { +void InformationManager::DaemonStateUpdateRequestHandler::handlePacket(boost::shared_ptr<const Common::XmlPacket> packet) { + if(packet->getType() != "UpdateHostState") { Common::Logger::log(Common::Logger::ERROR, "Received an unexpected packet."); Common::XmlPacket ret; @@ -48,9 +48,9 @@ void InformationManager::DaemonStateUpdateRequestHandler::handlePacket(const Com { boost::lock_guard<boost::mutex> lock(informationManager.mutex); - std::map<std::string, Common::HostInfo>::iterator host = informationManager.daemons.find(packet["name"]); + std::map<std::string, Common::HostInfo>::iterator host = informationManager.daemons.find((*packet)["name"]); if(host != informationManager.daemons.end()) - host->second.setState(packet["state"]); + host->second.setState((*packet)["state"]); else Common::Logger::log(Common::Logger::WARNING, "Received a state update for an unknown host."); } @@ -77,19 +77,22 @@ void InformationManager::updateDaemonList(Common::Connection *con) { if(updating) return; - Common::RequestManager::get()->sendRequest0<Requests::DaemonListRequest>(con, - boost::bind(&InformationManager::daemonListRequestFinished, this, _1)); + updateRequest = boost::shared_ptr<Requests::DaemonListRequest>(new Requests::DaemonListRequest); + updateRequest->connectSignalFinished(boost::bind(&InformationManager::daemonListRequestFinished, this, _1, _2)); + + Common::RequestManager::get()->sendRequest(con, updateRequest); updating = true; } -void InformationManager::daemonListRequestFinished(Common::Request &request) { +void InformationManager::daemonListRequestFinished(boost::shared_ptr<const Common::XmlPacket> packet, Net::Exception error) { boost::lock_guard<boost::mutex> lock(mutex); - try { - const Common::XmlPacket &packet = request.getResult(); - - const Common::XmlPacket::Element &hostInfo = packet["hosts"]; + if(!packet || error) { + Common::Logger::logf(Common::Logger::CRITICAL, "Host list request failed: %s", error.strerror().c_str()); + } + else { + const Common::XmlPacket::Element &hostInfo = (*packet)["hosts"]; daemons.clear(); @@ -102,13 +105,8 @@ void InformationManager::daemonListRequestFinished(Common::Request &request) { daemons.insert(std::make_pair(info.getName(), info)); } } - catch(Net::Exception &e) { - Common::Logger::logf(Common::Logger::CRITICAL, "Host list request failed: %s", e.strerror().c_str()); - } updating = false; - - updateCond.notify_all(); } } diff --git a/src/Client/InformationManager.h b/src/Client/InformationManager.h index 239b8d8..a7d2354 100644 --- a/src/Client/InformationManager.h +++ b/src/Client/InformationManager.h @@ -38,17 +38,14 @@ class InformationManager : public Common::Initializable, private boost::noncopya private: class DaemonStateUpdateRequestHandler : public Common::RequestHandler { protected: - virtual void handlePacket(const Common::XmlPacket &packet); - - public: - DaemonStateUpdateRequestHandler(Common::Connection *connection, uint16_t requestId) - : RequestHandler(connection, requestId) {} + virtual void handlePacket(boost::shared_ptr<const Common::XmlPacket> packet); }; static InformationManager informationManager; boost::mutex mutex; - boost::condition_variable updateCond; + + boost::shared_ptr<Common::Request> updateRequest; std::map<std::string, Common::HostInfo> daemons; @@ -56,7 +53,7 @@ class InformationManager : public Common::Initializable, private boost::noncopya InformationManager() : updating(false) {} - void daemonListRequestFinished(Common::Request &request); + void daemonListRequestFinished(boost::shared_ptr<const Common::XmlPacket> packet, Net::Exception error); protected: virtual void doInit(); @@ -76,9 +73,11 @@ class InformationManager : public Common::Initializable, private boost::noncopya void waitWhileUpdating() { boost::unique_lock<boost::mutex> lock(mutex); + boost::shared_ptr<Common::Request> request = updateRequest; + lock.unlock(); - while(updating) - updateCond.wait(lock); + if(request) + request->wait(); } diff --git a/src/Client/Requests/DaemonCommandRequest.h b/src/Client/Requests/DaemonCommandRequest.h index 2e421e8..8559f87 100644 --- a/src/Client/Requests/DaemonCommandRequest.h +++ b/src/Client/Requests/DaemonCommandRequest.h @@ -36,8 +36,8 @@ class DaemonCommandRequest : public Common::Request { virtual void sendRequest(); public: - DaemonCommandRequest(Common::Connection *connection, uint16_t requestId, slot_type slot, const std::string &daemon0, bool reboot0) - : Common::Request(connection, requestId, slot), daemon(daemon0), reboot(reboot0) {} + DaemonCommandRequest(const std::string &daemon0, bool reboot0) + : daemon(daemon0), reboot(reboot0) {} }; } diff --git a/src/Client/Requests/DaemonFSInfoRequest.h b/src/Client/Requests/DaemonFSInfoRequest.h index 17d2aa0..58ca9a6 100644 --- a/src/Client/Requests/DaemonFSInfoRequest.h +++ b/src/Client/Requests/DaemonFSInfoRequest.h @@ -36,8 +36,7 @@ class DaemonFSInfoRequest : public Common::Request { virtual void sendRequest(); public: - DaemonFSInfoRequest(Common::Connection *connection, uint16_t requestId, slot_type slot, const std::string &daemon0) - : Common::Request(connection, requestId, slot), daemon(daemon0) {} + DaemonFSInfoRequest(const std::string &daemon0) : daemon(daemon0) {} }; } diff --git a/src/Client/Requests/DaemonListRequest.h b/src/Client/Requests/DaemonListRequest.h index 27a025f..d10efab 100644 --- a/src/Client/Requests/DaemonListRequest.h +++ b/src/Client/Requests/DaemonListRequest.h @@ -28,8 +28,7 @@ namespace Requests { class DaemonListRequest : public Common::Requests::SimpleRequest { public: - DaemonListRequest(Common::Connection *connection, uint16_t requestId, slot_type slot) - : SimpleRequest(connection, requestId, slot, "ListHosts") {} + DaemonListRequest() : SimpleRequest("ListHosts") {} }; } diff --git a/src/Client/Requests/DaemonStatusRequest.h b/src/Client/Requests/DaemonStatusRequest.h index 936692f..0642187 100644 --- a/src/Client/Requests/DaemonStatusRequest.h +++ b/src/Client/Requests/DaemonStatusRequest.h @@ -36,8 +36,7 @@ class DaemonStatusRequest : public Common::Request { virtual void sendRequest(); public: - DaemonStatusRequest(Common::Connection *connection, uint16_t requestId, slot_type slot, const std::string &daemon0) - : Common::Request(connection, requestId, slot), daemon(daemon0) {} + DaemonStatusRequest(const std::string &daemon0) : daemon(daemon0) {} }; } |