Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

ServerMain.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Fri Apr 22 22:55:49 EDT 2005 by ken@xorian.net 
00020 //      modified on Fri Feb  5 17:16:04 PST 1999 by heydon 
00021 //      modified on Tue Oct 13 11:19:29 PDT 1998 by mann  
00022 //      modified on Thu Jun 27 15:22:08 PDT 1996 by levin
00023 
00024 #include <Basics.H>
00025 #include <OS.H>
00026 #include <VestaConfig.H>
00027 #include <signal.h>
00028 #include <sys/resource.h>
00029 
00030 // SRPC stuff
00031 #include <LimService.H>
00032 
00033 // Repository stuff
00034 #include <SourceOrDerived.H>
00035 
00036 #include "RunToolClient.H"
00037 #include "RunToolDaemon.H"
00038 extern "C" {
00039 #include "get_load.h"
00040 }
00041 
00042 using std::ostringstream;
00043 using std::cerr;
00044 using std::endl;
00045 
00046 //  ********************
00047 //  *  Initialization  *
00048 //  ********************
00049 
00050 void init_repository_access()
00051 {
00052   char *root = SourceOrDerived::getMetadataRootLocalName();
00053   if (chdir(root) == SYSERROR) {
00054     Text msg = Basics::errno_Text(errno);
00055     cerr << "Can't chdir(" << root << ") because: " << msg << endl;
00056     exit(1);
00057   }
00058   delete[] root;
00059   SourceOrDerived::setMetadataRootLocalName("");
00060 }
00061 
00062 
00063 //  ***********************************
00064 //  *  Tool driver support functions  *
00065 //  ***********************************
00066 
00067 static Text config_Text(const Text &key)
00068 {
00069   return VestaConfig::get_Text(RUN_TOOL_CONFIG_SECTION, key);
00070 }
00071 
00072 static int config_int(const Text &key)
00073 {
00074   return VestaConfig::get_int(RUN_TOOL_CONFIG_SECTION, key);
00075 }
00076 
00077 static int config_int(const Text &key, int default_value)
00078 {
00079   Text tval;
00080   if(VestaConfig::get(RUN_TOOL_CONFIG_SECTION, key, tval))
00081     {
00082       return VestaConfig::get_int(RUN_TOOL_CONFIG_SECTION, key);
00083     }
00084   return default_value;
00085 }
00086 
00087 Text convert_failure(const SRPC::failure &f) {
00088   ostringstream s;
00089   s << "SRPC failure (";
00090   switch (f.r) {
00091   case SRPC::unknown_host:
00092     s << "unknown_host"; break;
00093   case SRPC::unknown_interface:
00094     s << "unknown_interface"; break;
00095   case SRPC::version_skew:
00096     s << "version_skew"; break;
00097   case SRPC::protocol_violation:
00098     s << "protocol_violation"; break;
00099   case SRPC::buffer_too_small:
00100     s << "buffer_too_small"; break;
00101   case SRPC::transport_failure:
00102     s << "transport_failure"; break;
00103   case SRPC::internal_trouble:
00104     s << "internal_trouble"; break;
00105   case SRPC::invalid_parameter:
00106     s << "invalid_parameter"; break;
00107   case SRPC::partner_went_away:
00108     s << "partner_went_away"; break;
00109   case SRPC::not_implemented:
00110     s << "not_implemented"; break;
00111   default:
00112     s << f.r; break;
00113   }
00114   s << "): " << f.msg.chars();
00115   Text t(s.str());
00116   return t;
00117 }
00118 
00119 void RunToolServerFailure(SRPC *srpc, const SRPC::failure &f, void *arg) {
00120     // called when a failure occurs during server execution
00121     if (f.r == SRPC::partner_went_away) {
00122         // Normal; do not print anything
00123         return;
00124     }
00125     cerr << "RunToolServer: " << convert_failure(f).chars()
00126       << " (server continuing)\n";
00127 }
00128 
00129 // Exit cleanly on SIGINT or SIGTERM
00130 #if defined(__linux__)
00131 // On Linux, we need to remember which is the main thread.
00132 static pthread_t g_main_thread = pthread_self();
00133 #endif
00134 extern "C" void
00135 SigHandler(int sig)
00136 {
00137 #if defined(__linux__)
00138   // The Linux pthreads implementation uses one process pre thread.
00139   // The main thread will recieve the signal from a ^C and then
00140   // proceed to call exit below.  This will in turn kill off the other
00141   // threads, delivering each of them a signal which will in turn call
00142   // this handler again.  If any of those threads then call exit, the
00143   // pthreads library seems to become confused and crashes.  For that
00144   // reason, we don't call exit unless we're the main thread.
00145   if(pthread_self() != g_main_thread)
00146     {
00147       return;
00148     }
00149 #endif
00150 
00151   RunToolServerCleanup();
00152   exit(3);
00153 }
00154 
00155 //  ***************************
00156 //  *  Tool driver main loop  *
00157 //  ***************************
00158 
00159 int main(int argc, char *argv[])
00160 {
00161   // Are we exiting because of a fatal error?
00162   bool l_error = false;
00163 
00164   InitLoadPoint(); // initialization of the load average reading lib
00165   try
00166     {
00167       int maxTools   = config_int("server_max_threads");
00168       int maxPending = config_int("server_max_pending");
00169       int maxBlocked = config_int("server_max_blocked", maxPending);
00170       // adjust the core dump size - setting coredumpsize_limit
00171       // negative gets the maximum
00172       if(VestaConfig::is_set(RUN_TOOL_CONFIG_SECTION, "coredumpsize_limit"))
00173         {
00174           int coredumpsize = config_int("coredumpsize_limit");
00175           struct rlimit r;
00176           int err = getrlimit(RLIMIT_CORE, &r);
00177           if(err != 0)
00178             {
00179               int errno_save = errno;
00180               cerr << "Error getting core dump size limit: "
00181                    << Basics::errno_Text(errno_save)
00182                    << "(errno = " << errno_save << ")" << endl;
00183             }
00184           if(r.rlim_max > coredumpsize && coredumpsize >= 0)
00185             r.rlim_cur = coredumpsize;
00186           else
00187             r.rlim_cur = r.rlim_max;
00188           err = setrlimit(RLIMIT_CORE, &r);
00189           if(err != 0)
00190             {
00191               int errno_save = errno;
00192               cerr << "Error setting core dump size limit:  "
00193                    << Basics::errno_Text(errno_save)
00194                    << "(errno = " << errno_save << ")" << endl;
00195             }
00196         }
00197 
00198       init_repository_access();
00199       RunToolServerInit(maxTools, maxPending);
00200       // The maximum number of threads allowed to run from
00201       // LimService's perspective is the maximum number of running
00202       // tools, plus the maximum number pending, plus one more to make
00203       // sure we can always service "get_info" queries.
00204       int maxRunning = maxTools + maxPending + 1;
00205       signal(SIGINT, SigHandler);
00206       signal(SIGTERM, SigHandler);
00207 
00208       // Perhaps command line arguments (currently ignored) should
00209       // someday be accepted to override selected information?
00210 
00211       LimService *ls =
00212         NEW_CONSTR(LimService,
00213                    (/* intfName */    config_Text("SRPC_port"),
00214                     /* maxRunning */  maxRunning,
00215                     /* maxBlocked */  maxBlocked,
00216                     /* callback */    &RunToolServer,
00217                     /* failure */     &RunToolServerFailure));
00218 
00219       try
00220         {
00221           ls->Run();
00222         }
00223       catch (SRPC::failure f) {
00224         cerr << convert_failure(f).chars() << '\n';
00225         if (f.r == SRPC::transport_failure &&
00226             f.msg.FindText("already in use") != -1)
00227           {
00228             cerr << "Is a RunToolServer already running on this machine?"
00229                  << endl;
00230           }
00231         l_error = true;
00232       }
00233 
00234       delete ls;
00235       RunToolServerCleanup();
00236     }
00237   catch(VestaConfig::failure f)
00238     {
00239       cerr << argv[0] << ": Configuration error: " << f.msg.cchars() << endl;
00240       l_error = true;
00241     }
00242 
00243   return (l_error ? 1 : 0);
00244 }
00245 

Generated on Mon May 8 00:48:56 2006 for Vesta by  doxygen 1.4.2