// Boost include for boost::thread::sleep #include #include "shell.hpp" /////////////////////////////////////////////////////////// // // we get some environment variables at startup, for the // initial working directory and initial job manager. // std::string init_contact (void) { char const* env = ::getenv ("SAGA_SHELL_CONTACT"); return env ? env : "fork://localhost/"; } std::string init_host (std::string url) { saga::url u (url); std::string host = u.get_host (); if (host.empty()) { return ("localhost"); } return (host); } std::string init_home (void) { char const* env = ::getenv ("SAGA_SHELL_HOME"); return env ? env : "file://localhost//tmp"; } /////////////////////////////////////////////////////////// // // the c'tor only initializes a number of variables // shell::shell (void) : session_ (), home_ (init_home ()), cwd_ (session_, home_, saga::name_space::ReadWrite), contact_ (init_contact ()), host_ (init_host (contact_)), js_ (session_, contact_) { return; } /////////////////////////////////////////////////////////// // // now and then, we have to re-initialize member variables, // as some operations change the environment // void shell::init (void) { home_ = init_home (); contact_ = init_contact (); host_ = init_host (contact_); carp ("reinit js with " + contact_, false); // recreate session saga::session s; session_ = s; // recreate job service in that session saga::job::service js (s, contact_); js_ = js; // recreate cwd in that session saga::name_space::directory cwd (s, cwd_.get_url ()); cwd_ = cwd; } /////////////////////////////////////////////////////////// // // as long as there is input, get it, and run the // respective command // namespace detail { ////////////////////////////////////////////////////////////////////////// // chop off whitespace in the beginning and the end of the input string std::string trim_whitespace(std::string const& str) { typedef std::string::size_type size_type; size_type first = str.find_first_not_of(" \t\v\f"); if (std::string::npos == first) return std::string(); size_type last = str.find_last_not_of(" \t\v\f"); return str.substr(first, last-first+1); } } void shell::run (void) { // get first command line prompt (); std::string input; std::getline (std::cin, input); input = detail::trim_whitespace(input); // keep running until we see 'exit' while ( input != "exit" && input != "quit" ) { // split line in command and arguments std::string command = input; std::string args = input; try { size_t idx = input.find (" "); if ( idx != 0 && idx != std::string::npos) { command.erase (idx); args.erase (0, idx + 1); } else { args = ""; } // operations on the name space if ( command == "ls" ) { c_ls (args); } else if ( command == "pwd" ) { c_pwd (args); } else if ( command == "cd" ) { c_cd (args); } else if ( command == "touch" ) { c_touch (args); } else if ( command == "cp" ) { c_cp (args); } else if ( command == "mv" ) { c_mv (args); } else if ( command == "ln" ) { c_ln (args); } else if ( command == "rm" ) { c_rm (args); } else if ( command == "mkdir" ) { c_mkdir (args); } else if ( command == "rmdir" ) { c_rmdir (args); } // operations on file contents else if ( command == "cat" ) { c_cat (args); } // operations on replica locations else if ( command == "log_find" ) { c_log_find (args); } else if ( command == "log_list" ) { c_log_list (args); } else if ( command == "log_add" ) { c_log_add (args); } else if ( command == "log_remove" ) { c_log_remove (args); } else if ( command == "log_update" ) { c_log_update (args); } else if ( command == "log_replicate" ) { c_log_replicate (args); } // job related operations else if ( command == "run" ) { c_run (args); } else if ( command == "run2" ) { c_run2 (args); } else if ( command == "ps" ) { c_ps (args); } else if ( command == "status" ) { c_status (args); } else if ( command == "suspend" ) { c_suspend (args); } else if ( command == "resume" ) { c_resume (args); } else if ( command == "kill" ) { c_kill (args); } // others else if ( command == "set" ) { c_set (args); } else if ( command == "help" ) { c_help (args); } else if ( command == "man" ) { c_help (args); } else if ( command == "//" ) { /* ignore comments */ } else if ( command == "" ) { /* nothing to do */ } else { c_help (args); } } // catch SAGA exceptions, but leave system exceptions untouched catch ( saga::exception const & e ) { switch ( e.get_error () ) { // handle NotImplemented gracefully case saga::NotImplemented: carp ("This method is not yet implemented in SAGA"); break; // generic handler and dump of other exceptions default: carp ("saga exception caught: " + std::string (e.what ())); break; } } // get ready for next command prompt (); std::getline (std::cin, input); input = detail::trim_whitespace(input); } return; } /////////////////////////////////////////////////////////// // // print a shell prompt, with optional message // void shell::prompt (std::string text, std::string marker) { if ( !text.empty() ) { std::cout << text << std::endl; } std::cout << marker << std::flush; } /////////////////////////////////////////////////////////// // // print an error message // void shell::carp (std::string text, bool is_error) { if (is_error) std::cout << "Ooops!" << std::endl; if ( !text.empty() ) { std::cout << text << std::endl; } } /////////////////////////////////////////////////////////// // // translate a job state into a string // std::string shell::state_to_string (saga::job::state state) { switch ( state ) { case saga::job::New : return ("New "); case saga::job::Running : return ("Running "); case saga::job::Suspended : return ("Suspended"); case saga::job::Done : return ("Done "); case saga::job::Failed : return ("Failed "); case saga::job::Canceled : return ("Canceled "); default : std::cout << "Unknown state: " << state << std::endl; return ("Unknown "); } } void shell::usleep (long int usec) { boost::xtime xt; boost::xtime_get (&xt, boost::TIME_UTC); xt.nsec += usec; boost::thread::sleep (xt); }