diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/IceGrid/Client.cpp | 301 | ||||
-rw-r--r-- | cpp/src/IceGrid/Grammar.y | 11 | ||||
-rw-r--r-- | cpp/src/IceGrid/Parser.cpp | 69 | ||||
-rw-r--r-- | cpp/src/IceGrid/Parser.h | 13 |
4 files changed, 299 insertions, 95 deletions
diff --git a/cpp/src/IceGrid/Client.cpp b/cpp/src/IceGrid/Client.cpp index 6d9cb1ae053..25c19192b9b 100644 --- a/cpp/src/IceGrid/Client.cpp +++ b/cpp/src/IceGrid/Client.cpp @@ -9,7 +9,8 @@ #include <IceUtil/DisableWarnings.h> #include <IceUtil/Options.h> -#include <Ice/Application.h> +#include <IceUtil/CtrlCHandler.h> +#include <Ice/Ice.h> #include <Ice/SliceChecksums.h> #include <IceGrid/Parser.h> #include <IceGrid/FileParserI.h> @@ -21,6 +22,11 @@ using namespace std; using namespace Ice; using namespace IceGrid; +class Client; + +static IceUtil::StaticMutex _staticMutex = ICE_STATIC_MUTEX_INITIALIZER; +static Client* _globalClient = 0; + class SessionKeepAliveThread : public IceUtil::Thread, public IceUtil::Monitor<IceUtil::Mutex> { public: @@ -70,16 +76,36 @@ private: }; typedef IceUtil::Handle<SessionKeepAliveThread> SessionKeepAliveThreadPtr; -class Client : public Application +class Client : public IceUtil::Monitor<IceUtil::Mutex> { public: void usage(); - virtual int run(int, char*[]); + int main(int argc, char* argv[]); + int run(int, char*[]); + void interrupted(); + + Ice::CommunicatorPtr communicator() const { return _communicator; } + const char* appName() const { return _appName; } string trim(const string&); +private: + + IceUtil::CtrlCHandler _ctrlCHandler; + Ice::CommunicatorPtr _communicator; + const char* _appName; + ParserPtr _parser; }; +static void interruptCallback(int signal) +{ + IceUtil::StaticMutex::Lock lock(_staticMutex); + if(_globalClient) + { + _globalClient->interrupted(); + } +} + int main(int argc, char* argv[]) { @@ -110,6 +136,107 @@ Client::usage() } int +Client::main(int argc, char* argv[]) +{ + int status = EXIT_SUCCESS; + + try + { + _appName = argv[0]; + _communicator = Ice::initialize(argc, argv); + + { + IceUtil::StaticMutex::Lock sync(_staticMutex); + _globalClient = this; + } + _ctrlCHandler.setCallback(interruptCallback); + + try + { + run(argc, argv); + } + catch(const Ice::CommunicatorDestroyedException&) + { + // Expected if the client is interrupted during the initialization. + } + } + catch(const IceUtil::Exception& ex) + { + cerr << _appName << ": " << ex << endl; + status = EXIT_FAILURE; + } + catch(const std::exception& ex) + { + cerr << _appName << ": std::exception: " << ex.what() << endl; + status = EXIT_FAILURE; + } + catch(const std::string& msg) + { + cerr << _appName << ": " << msg << endl; + status = EXIT_FAILURE; + } + catch(const char* msg) + { + cerr << _appName << ": " << msg << endl; + status = EXIT_FAILURE; + } + catch(...) + { + cerr << _appName << ": unknown exception" << endl; + status = EXIT_FAILURE; + } + + if(_communicator) + { + try + { + _communicator->destroy(); + } + catch(const Ice::CommunicatorDestroyedException&) + { + } + catch(const Ice::Exception& ex) + { + cerr << ex << endl; + status = EXIT_FAILURE; + } + } + + _ctrlCHandler.setCallback(0); + { + IceUtil::StaticMutex::Lock sync(_staticMutex); + _globalClient = 0; + } + + return status; + +} + +void +Client::interrupted() +{ + Lock sync(*this); + if(_parser) // If there's an interactive parser, notify the parser. + { + _parser->interrupt(); + } + else + { + // + // Otherwise, destroy the communicator. + // + assert(_communicator); + try + { + _communicator->destroy(); + } + catch(const Ice::Exception&) + { + } + } +} + +int Client::run(int argc, char* argv[]) { string cpp("cpp"); @@ -165,7 +292,6 @@ Client::run(int argc, char* argv[]) return EXIT_SUCCESS; } - if(opts.isSet("D")) { vector<string> optargs = opts.argVec("D"); @@ -217,8 +343,6 @@ Client::run(int argc, char* argv[]) instanceName = communicator()->getProperties()->getPropertyWithDefault("IceGrid.InstanceName", "IceGrid"); } - int timeout; - AdminSessionPrx session; bool ssl = communicator()->getProperties()->getPropertyAsInt("IceGridAdmin.AuthenticateUsingSSL"); if(opts.isSet("ssl")) { @@ -240,21 +364,24 @@ Client::run(int argc, char* argv[]) // If a glacier2 router is configured, then set routed to true by // default. // - bool routed = communicator()->getProperties()->getPropertyAsIntWithDefault( - "IceGridAdmin.Routed", communicator()->getDefaultRouter()); + Ice::PropertiesPtr properties = communicator()->getProperties(); + bool routed = properties->getPropertyAsIntWithDefault("IceGridAdmin.Routed", communicator()->getDefaultRouter()); if(opts.isSet("routed")) { routed = true; } - string replica = communicator()->getProperties()->getProperty("IceGridAdmin.Replica"); + string replica = properties->getProperty("IceGridAdmin.Replica"); if(!opts.optArg("replica").empty()) { replica = opts.optArg("replica"); } - + AdminSessionPrx session; + SessionKeepAliveThreadPtr keepAlive; + int status = EXIT_SUCCESS; try { + int timeout; if(routed) { Glacier2::RouterPrx router = Glacier2::RouterPrx::checkedCast(communicator()->getDefaultRouter()); @@ -372,103 +499,119 @@ Client::run(int argc, char* argv[]) assert(session); timeout = registry->getSessionTimeout(); } - } - catch(const IceGrid::PermissionDeniedException& ex) - { - cout << "permission denied:\n" << ex.reason << endl; - return EXIT_FAILURE; - } - - SessionKeepAliveThreadPtr keepAlive = new SessionKeepAliveThread(session, timeout / 2); - keepAlive->start(); + + keepAlive = new SessionKeepAliveThread(session, timeout / 2); + keepAlive->start(); - AdminPrx admin = session->getAdmin(); + AdminPrx admin = session->getAdmin(); - Ice::SliceChecksumDict serverChecksums = admin->getSliceChecksums(); - Ice::SliceChecksumDict localChecksums = Ice::sliceChecksums(); + Ice::SliceChecksumDict serverChecksums = admin->getSliceChecksums(); + Ice::SliceChecksumDict localChecksums = Ice::sliceChecksums(); - // - // The following slice types are only used by the admin CLI. - // - localChecksums.erase("::IceGrid::FileParser"); - localChecksums.erase("::IceGrid::ParseException"); + // + // The following slice types are only used by the admin CLI. + // + localChecksums.erase("::IceGrid::FileParser"); + localChecksums.erase("::IceGrid::ParseException"); - for(Ice::SliceChecksumDict::const_iterator q = localChecksums.begin(); q != localChecksums.end(); ++q) - { - Ice::SliceChecksumDict::const_iterator r = serverChecksums.find(q->first); - if(r == serverChecksums.end()) - { - cerr << appName() << ": server is using unknown Slice type `" << q->first << "'" << endl; - } - else if(q->second != r->second) - { - cerr << appName() << ": server is using a different Slice definition of `" << q->first << "'" << endl; - } - } - - ParserPtr p = Parser::createParser(communicator(), session, admin); - - int status = EXIT_SUCCESS; - - if(args.empty()) // No files given - { - if(!commands.empty()) // Commands were given + for(Ice::SliceChecksumDict::const_iterator q = localChecksums.begin(); q != localChecksums.end(); ++q) { - int parseStatus = p->parse(commands, debug); - if(parseStatus == EXIT_FAILURE) + Ice::SliceChecksumDict::const_iterator r = serverChecksums.find(q->first); + if(r == serverChecksums.end()) { - status = EXIT_FAILURE; + cerr << appName() << ": server is using unknown Slice type `" << q->first << "'" << endl; } - } - else // No commands, let's use standard input - { - p->showBanner(); - - int parseStatus = p->parse(stdin, debug); - if(parseStatus == EXIT_FAILURE) + else if(q->second != r->second) { - status = EXIT_FAILURE; + cerr << appName() << ": server is using a different Slice definition of `" << q->first << "'" << endl; } } - } - else // Process files given on the command line - { - for(vector<string>::const_iterator i = args.begin(); i != args.end(); ++i) + + { + Lock sync(*this); + _parser = Parser::createParser(communicator(), session, admin, args.empty() && commands.empty()); + } + + if(!args.empty()) // Files given { - ifstream test(i->c_str()); - if(!test) + // Process files given on the command line + for(vector<string>::const_iterator i = args.begin(); i != args.end(); ++i) { - cerr << appName() << ": can't open `" << *i << "' for reading: " << strerror(errno) << endl; - return EXIT_FAILURE; - } - test.close(); + ifstream test(i->c_str()); + if(!test) + { + cerr << appName() << ": can't open `" << *i << "' for reading: " << strerror(errno) << endl; + return EXIT_FAILURE; + } + test.close(); - string cmd = cpp + " " + *i; + string cmd = cpp + " " + *i; #ifdef _WIN32 - FILE* cppHandle = _popen(cmd.c_str(), "r"); + FILE* cppHandle = _popen(cmd.c_str(), "r"); #else - FILE* cppHandle = popen(cmd.c_str(), "r"); + FILE* cppHandle = popen(cmd.c_str(), "r"); #endif - if(cppHandle == NULL) - { - cerr << appName() << ": can't run C++ preprocessor: " << strerror(errno) << endl; - return EXIT_FAILURE; - } + if(cppHandle == NULL) + { + cerr << appName() << ": can't run C++ preprocessor: " << strerror(errno) << endl; + return EXIT_FAILURE; + } - int parseStatus = p->parse(cppHandle, debug); + int parseStatus = _parser->parse(cppHandle, debug); #ifdef _WIN32 - _pclose(cppHandle); + _pclose(cppHandle); #else - pclose(cppHandle); + pclose(cppHandle); #endif + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + } + } + else if(!commands.empty()) // Commands were given + { + int parseStatus = _parser->parse(commands, debug); + if(parseStatus == EXIT_FAILURE) + { + status = EXIT_FAILURE; + } + } + else // No commands, let's use standard input + { + _parser->showBanner(); + + int parseStatus = _parser->parse(stdin, debug); if(parseStatus == EXIT_FAILURE) { status = EXIT_FAILURE; } } } + catch(const IceGrid::PermissionDeniedException& ex) + { + cout << "permission denied:\n" << ex.reason << endl; + return EXIT_FAILURE; + } + catch(...) + { + if(keepAlive) + { + keepAlive->destroy(); + keepAlive->getThreadControl().join(); + } + + try + { + session->destroy(); + } + catch(const Ice::Exception&) + { + } + throw; + } keepAlive->destroy(); keepAlive->getThreadControl().join(); diff --git a/cpp/src/IceGrid/Grammar.y b/cpp/src/IceGrid/Grammar.y index 4b708aba0d3..00e283199ff 100644 --- a/cpp/src/IceGrid/Grammar.y +++ b/cpp/src/IceGrid/Grammar.y @@ -91,14 +91,21 @@ start // ---------------------------------------------------------------------- commands // ---------------------------------------------------------------------- -: commands command +: commands checkInterrupted command { } -| command +| checkInterrupted command { } ; +checkInterrupted +: +{ + parser->checkInterrupted(); +} +; + // ---------------------------------------------------------------------- command // ---------------------------------------------------------------------- diff --git a/cpp/src/IceGrid/Parser.cpp b/cpp/src/IceGrid/Parser.cpp index 0601951648a..8d869cfa1f1 100644 --- a/cpp/src/IceGrid/Parser.cpp +++ b/cpp/src/IceGrid/Parser.cpp @@ -41,9 +41,10 @@ Parser* parser; } ParserPtr -Parser::createParser(const CommunicatorPtr& communicator, const AdminSessionPrx& session, const AdminPrx& admin) +Parser::createParser(const CommunicatorPtr& communicator, const AdminSessionPrx& session, const AdminPrx& admin, + bool interactive) { - return new Parser(communicator, session, admin); + return new Parser(communicator, session, admin, interactive); } void @@ -131,6 +132,41 @@ Parser::usage() } void +Parser::interrupt() +{ + Lock sync(*this); + _interrupted = true; + notifyAll(); +} + +bool +Parser::interrupted() const +{ + Lock sync(*this); + return _interrupted; +} + +void +Parser::resetInterrupt() +{ + Lock sync(*this); + _interrupted = false; +} + +void +Parser::checkInterrupted() +{ + if(!_interactive) + { + Lock sync(*this); + if(_interrupted) + { + throw "interrupted with Ctrl-C"; + } + } +} + +void Parser::addApplication(const list<string>& origArgs) { list<string> copyArgs = origArgs; @@ -1346,6 +1382,7 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string } bool follow = opts.isSet("follow"); + resetInterrupt(); if(head) { if(follow) @@ -1355,7 +1392,7 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string } int i = 0; - while(true) + while(!interrupted()) { lines = it->read(20); @@ -1375,7 +1412,7 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string else if(tail) { deque<string> lastLines; - while(true) + while(!interrupted()) { lines = it->read(20); @@ -1400,7 +1437,7 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string } else { - while(true) + while(!interrupted()) { lines = it->read(20); for(Ice::StringSeq::const_iterator p = lines.begin(); p != lines.end(); ++p) @@ -1417,7 +1454,7 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string if(follow) { - while(true) + while(!interrupted()) { lines = it->read(20); for(Ice::StringSeq::const_iterator p = lines.begin(); p != lines.end(); ++p) @@ -1433,7 +1470,14 @@ Parser::dumpFile(const string& reader, const string& filename, const list<string } } - IceUtil::ThreadControl::sleep(IceUtil::Time::seconds(2)); + { + Lock sync(*this); + if(_interrupted) + { + break; + } + timedWait(IceUtil::Time::seconds(5)); + } } } @@ -1468,7 +1512,6 @@ Parser::showWarranty() cout << "This command is not implemented." << endl; } - void Parser::getInput(char* buf, int& result, int maxSize) { @@ -1542,7 +1585,6 @@ Parser::getInput(char* buf, int& result, int maxSize) } break; } - line += c; if(c == '\n') @@ -1793,10 +1835,15 @@ Parser::parse(const std::string& commands, bool debug) return status; } -Parser::Parser(const CommunicatorPtr& communicator, const AdminSessionPrx& session, const AdminPrx& admin) : +Parser::Parser(const CommunicatorPtr& communicator, + const AdminSessionPrx& session, + const AdminPrx& admin, + bool interactive) : _communicator(communicator), _session(session), - _admin(admin) + _admin(admin), + _interrupted(false), + _interactive(interactive) { } diff --git a/cpp/src/IceGrid/Parser.h b/cpp/src/IceGrid/Parser.h index 3e800be4d96..a4a1d0637da 100644 --- a/cpp/src/IceGrid/Parser.h +++ b/cpp/src/IceGrid/Parser.h @@ -62,14 +62,19 @@ typedef ::IceUtil::Handle<Parser> ParserPtr; namespace IceGrid { -class Parser : public ::IceUtil::SimpleShared +class Parser : public ::IceUtil::SimpleShared, IceUtil::Monitor<IceUtil::Mutex> { public: - static ParserPtr createParser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&); + static ParserPtr createParser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&, bool); void usage(); + void interrupt(); + bool interrupted() const; + void resetInterrupt(); + void checkInterrupted(); + void addApplication(const std::list<std::string>&); void removeApplication(const std::list<std::string>&); void describeApplication(const std::list<std::string>&); @@ -143,7 +148,7 @@ public: private: - Parser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&); + Parser(const Ice::CommunicatorPtr&, const AdminSessionPrx&, const AdminPrx&, bool); void exception(const Ice::Exception&); std::string _commands; @@ -151,9 +156,11 @@ private: AdminSessionPrx _session; AdminPrx _admin; bool _continue; + bool _interrupted; int _errors; int _currentLine; std::string _currentFile; + bool _interactive; }; extern Parser* parser; // The current parser for bison/flex |