Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

rt_server.cc

Go to the documentation of this file.
00001 /*
00002  * rt_server.cc
00003  *
00004  * Copyright (c) 2003, 2004 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file rt_server.cc
00014  *
00015  * Server for a single RTServer object.
00016  *
00017  * @sa RTServerImpl.hh
00018  * @sa RTServer.idl
00019  * @sa rt_client.cc
00020  */
00021 
00022 #include "config.h"
00023 
00024 #include <signal.h>
00025 #include <fstream>
00026 #include <time_util.h>
00027 
00028 #include <iostream>
00029 
00030 #include <BrokerC.h>
00031 #include <BasicTaskKernelImpl.h>
00032 
00033 #include "RTServerImpl.hh"
00034 #include "RTServerWrapper.hh"
00035 
00036 #include "RealTimeTaskImpl.hh"
00037 #include "MaxDecayTaskAdvocate.hh"
00038 
00039 using namespace std;
00040 
00041 /**
00042  * Global data for the tool.
00043  */
00044 static struct {
00045     /**
00046      * The CORBA ORB for this process.
00047      */
00048     CORBA::ORB_var orb;
00049     /**
00050      * The server object.
00051      */
00052     RTServerImpl *rtsi;
00053     /**
00054      * The manager for this machine.
00055      */
00056     Broker::Manager_var manager;
00057     /**
00058      * The task for this process.
00059      */
00060     Broker::RealTimeTask_var rtt;
00061 } rts_data;
00062 
00063 /**
00064  * Handle a signal by exiting cleanly.
00065  *
00066  * @param sig The actual signal received.
00067  */
00068 static void sigexit(int sig)
00069 {
00070     if( !CORBA::is_nil(rts_data.manager.in()) &&
00071         !CORBA::is_nil(rts_data.rtt.in()) )
00072     {
00073         rts_data.manager->RemoveTask(rts_data.rtt.in());
00074     }
00075 
00076     if( !CORBA::is_nil(rts_data.orb.in()) )
00077     {
00078         rts_data.orb->shutdown();
00079     }
00080     
00081     if( rts_data.rtsi != NULL )
00082     {
00083         delete rts_data.rtsi;
00084     }
00085     
00086     exit(EXIT_SUCCESS);
00087 }
00088 
00089 int main(int argc, char *argv[])
00090 {
00091     int retval = EXIT_FAILURE;
00092 
00093 #if defined(HAVE_ACE)
00094     /* Put a sock in ACE */
00095     ACE_Log_Msg::instance()->priority_mask(0, ACE_Log_Msg::PROCESS);
00096 #endif
00097 
00098     {
00099         struct sigaction sa;
00100         sigset_t sigmask;
00101         
00102         sigemptyset(&sigmask);
00103         sigaddset(&sigmask, SIGINT);
00104         sigaddset(&sigmask, SIGTERM);
00105         sigaddset(&sigmask, SIGALRM);
00106         sa.sa_mask = sigmask;
00107         sa.sa_flags = 0;
00108         sa.sa_handler = sigexit;
00109         if( (sigaction(SIGINT, &sa, NULL) == -1) ||
00110             (sigaction(SIGTERM, &sa, NULL) == -1) )
00111         {
00112             ensure(0);
00113         }
00114     }
00115     
00116     try
00117     {
00118         /* Start up the ORB and */
00119         rts_data.orb = CORBA::ORB_init(argc, argv);
00120 
00121         CORBA::Object_var obj = rts_data.orb->
00122             resolve_initial_references("RootPOA");
00123 
00124         PortableServer::POA_var root_poa =
00125             PortableServer::POA::_narrow(obj.in());
00126         PortableServer::POAManager_var mgr = root_poa->the_POAManager();
00127         mgr->activate();
00128 
00129         quo::QuoKernel_var qk;
00130         
00131         try
00132         {
00133             /* ... check for an IOR from the Java QuOKernel. */
00134             obj = rts_data.orb->string_to_object("file://quoKernel.ior");
00135             qk = quo::QuoKernel::_narrow(obj.in());
00136             if( CORBA::is_nil(qk.in()) || qk->_non_existent() )
00137             {
00138                 qk = quo::QuoKernel::_nil();
00139             }
00140         }
00141         catch(const CORBA::SystemException &e)
00142         {
00143             qk = quo::QuoKernel::_nil();
00144         }
00145         if( CORBA::is_nil(qk.in()) )
00146         {
00147             Qosket::Basic::BasicTaskKernelImpl *btki;
00148             
00149             /* ... no joy on Java QuOKernel, create our own. */
00150             btki = new Qosket::Basic::BasicTaskKernelImpl(rts_data.orb);
00151             qk = btki->_this();
00152         }
00153 
00154         /* Setup the argument defaults, */
00155         const char *manager_ior = "file://manager.ior";
00156         const char *obj_ior = "rtserver.ior";
00157         const char *period = "1s"; /* _must_ match period_ul */
00158         CORBA::ULong period_ul = 1000000; /* _must_ match period */
00159         struct {
00160             CORBA::ULong data[128];
00161             CORBA::ULong length;
00162         } compute = { { 0 }, 0 };
00163         const char *task_ior = NULL;
00164         const char *task_name = NULL;
00165         unsigned long run_time = 0;
00166         int lpc, ch, g2g = 1;
00167 
00168         /* ... parse the options, */
00169         while( ((ch = getopt(argc, argv, "hVm:t:n:P:f:o:")) != -1) && g2g )
00170         {
00171             switch( ch )
00172             {
00173             case 'm':
00174                 manager_ior = optarg;
00175                 if( strlen(manager_ior) == 0 )
00176                 {
00177                     cerr << argv[0] << ": Manager IOR is empty" << endl;
00178                     throw CORBA::BAD_PARAM();
00179                 }
00180                 break;
00181             case 't':
00182                 if( task_name != NULL )
00183                 {
00184                     cerr << argv[0]
00185                          << ": The -n and -t options are mutually exclusive"
00186                          << endl;
00187                     throw CORBA::BAD_PARAM();
00188                 }
00189                 task_ior = optarg;
00190                 if( strlen(task_ior) == 0 )
00191                 {
00192                     cerr << argv[0] << ": Task IOR is empty" << endl;
00193                     throw CORBA::BAD_PARAM();
00194                 }
00195                 break;
00196             case 'n':
00197                 if( task_ior != NULL )
00198                 {
00199                     cerr << argv[0]
00200                          << ": The -n and -t options are mutually exclusive"
00201                          << endl;
00202                     throw CORBA::BAD_PARAM();
00203                 }
00204                 task_name = optarg;
00205                 if( strlen(task_name) == 0 )
00206                 {
00207                     cerr << "Task name is empty" << endl;
00208                 }
00209                 break;
00210             case 'P':
00211                 {
00212                     unsigned long long period_ull;
00213                     
00214                     period = optarg;
00215                     if( string_to_microsec(&period_ull, period) )
00216                     {
00217                         period_ul = period_ull;
00218                     }
00219                     else
00220                     {
00221                         cerr << "Period value not a time: "
00222                              << period
00223                              << endl;
00224                         throw CORBA::BAD_PARAM();
00225                     }
00226                 }
00227                 break;
00228             case 'f':
00229                 {
00230                     unsigned long long run_time_ull;
00231                     
00232                     if( string_to_microsec(&run_time_ull, optarg) )
00233                     {
00234                         run_time = run_time_ull;
00235                     }
00236                     else
00237                     {
00238                         cerr << argv[0]
00239                              << ": Run for value not a time: "
00240                              << period
00241                              << endl;
00242                         throw CORBA::BAD_PARAM();
00243                     }
00244                 }
00245                 break;
00246             case 'o':
00247                 if( strlen(optarg) == 0 )
00248                 {
00249                     cerr << argv[0]
00250                          << ": IOR output file name is empty"
00251                          << endl;
00252                     throw CORBA::BAD_PARAM();
00253                 }
00254                 obj_ior = optarg;
00255                 break;
00256             case 'V':
00257                 cout << PACKAGE_VERSION << endl;
00258                 exit(0);
00259                 break;
00260             case 'h':
00261             case '?':
00262             default:
00263                 g2g = 0;
00264                 break;
00265             }
00266         }
00267 
00268         /* ... parse the compute times, and */
00269         for( lpc = optind; lpc < argc; lpc++ )
00270         {
00271             unsigned long long compute_ull;
00272 
00273             if( compute.length >= 128 )
00274             {
00275                 cerr << "Too many compute values." << endl;
00276                 throw CORBA::BAD_PARAM();
00277             }
00278             else if( string_to_microsec(&compute_ull, argv[lpc]) )
00279             {
00280                 compute.data[compute.length] = compute_ull;
00281                 compute.length += 1;
00282             }
00283             else
00284             {
00285                 cerr << "Compute value is not a time: "
00286                      << argv[lpc]
00287                      << endl;
00288                 throw CORBA::BAD_PARAM();
00289             }
00290         }
00291         /* ... make sure we are good to go. */
00292         if( (task_ior == NULL) && (task_name == NULL) )
00293         {
00294             cerr << "No task name or IOR specified" << endl;
00295             g2g = 0;
00296         }
00297         if( g2g )
00298         {
00299             /* Set an alarm if there is a run time limit. */
00300             if( run_time > 0 )
00301             {
00302                 struct itimerval itv;
00303                 
00304                 signal(SIGALRM, sigexit);
00305                 itv.it_interval.tv_sec = 0;
00306                 itv.it_interval.tv_usec = 0;
00307                 itv.it_value.tv_sec = run_time / 1000000;
00308                 itv.it_value.tv_usec = run_time % 1000000;
00309                 if( setitimer(ITIMER_REAL, &itv, NULL) < 0 )
00310                 {
00311                     perror("setitimer");
00312                 }
00313             }
00314 
00315             /* Setup a default compute time if none was given. */
00316             if( compute.length == 0 )
00317             {
00318                 for( lpc = 0; lpc < 15; lpc++, compute.length++ )
00319                 {
00320                     compute.data[lpc] = period_ul / 4;
00321                 }
00322                 for( ; lpc < 20; lpc++, compute.length++ )
00323                 {
00324                     compute.data[lpc] = period_ul / 2;
00325                 }
00326             }
00327 
00328             /* Get a handle on the manager. */
00329             obj = rts_data.orb->string_to_object(manager_ior);
00330             rts_data.manager = Broker::Manager::_narrow(obj.in());
00331             if( CORBA::is_nil(rts_data.manager.in()) )
00332             {
00333                 cerr << "Invalid manager IOR: "
00334                      << manager_ior
00335                      << endl;
00336                 throw CORBA::BAD_PARAM();
00337             }
00338 
00339             /* Get a handle on the task or create one, and */
00340             if( task_ior != NULL )
00341             {
00342                 obj = rts_data.orb->string_to_object(task_ior);
00343                 rts_data.rtt = Broker::RealTimeTask::_narrow(obj.in());
00344                 if( CORBA::is_nil(rts_data.rtt.in()) )
00345                 {
00346                     cerr << "Invalid task factory IOR: "
00347                          << task_ior
00348                          << endl;
00349                     throw CORBA::BAD_PARAM();
00350                 }
00351             }
00352             else if( task_name != NULL )
00353             {
00354                 /* No existing object given, create a default. */
00355                 try
00356                 {
00357                     Broker::RealTimeTask_var rtt;
00358                     MaxDecayTaskAdvocate *mdta;
00359                     Broker::TaskParameters tp;
00360                     RealTimeTaskImpl *rtti;
00361                     CORBA::Any value;
00362                     
00363                     tp.length(1);
00364                     tp[0].name = "name";
00365                     tp[0].value <<= task_name;
00366                     rtti = new RealTimeTaskImpl(tp);
00367                     rtt = rtti->_this();
00368                     mdta = new MaxDecayTaskAdvocate();
00369                     value <<= rtt.in();
00370                     mdta->SetDelegateAttribute("remote-object", value);
00371                     rts_data.rtt = mdta->_this();
00372                 }
00373                 catch(const Broker::DuplicateTaskParameter &e)
00374                 {
00375                     ensure(0);
00376                 }
00377                 catch(const Broker::InvalidTaskParameter &e)
00378                 {
00379                     ensure(0);
00380                 }
00381                 catch(const Broker::MissingTaskParameter &e)
00382                 {
00383                     ensure(0);
00384                 }
00385             }
00386             else
00387             {
00388                 ensure(0);
00389             }
00390 
00391             /* ... start scheduling for this process. */
00392             try
00393             {
00394                 Broker::ScheduleParameters sp;
00395                 
00396                 sp.length(2);
00397                 sp[0].name = "period";
00398                 sp[0].value <<= period;
00399                 sp[1].name = "pid";
00400                 sp[1].value <<= (CORBA::Long)getpid();
00401                 rts_data.manager->AddTask(rts_data.rtt.in(), sp);
00402             }
00403             catch(const Broker::DuplicateScheduleParameter &e)
00404             {
00405                 cerr << e << endl;
00406                 cerr << e.name << endl;
00407                 throw CORBA::BAD_PARAM();
00408             }
00409             catch(const Broker::InvalidScheduleParameter &e)
00410             {
00411                 cerr << e << endl;
00412                 cerr << e.message << endl;
00413                 throw CORBA::BAD_PARAM();
00414             }
00415             catch(const Broker::MissingScheduleParameter &e)
00416             {
00417                 cerr << e << endl;
00418                 cerr << e.name << endl;
00419                 throw CORBA::BAD_PARAM();
00420             }
00421 
00422             /* Construct the actual server and */
00423             rts_data.rtsi = new RTServerImpl(period_ul,
00424                                              &compute.data[0],
00425                                              compute.length);
00426             RTServer_var real_rts;
00427             
00428             real_rts = rts_data.rtsi->_this();
00429 
00430             /* ... its wrapper. */
00431             RTServerWrapper *rtsw = new RTServerWrapper(rts_data.rtt.in(),
00432                                                         period_ul,
00433                                                         period_ul);
00434             RTServer_var rts;
00435             
00436             rts = rtsw->_this();
00437             
00438             rtsw->initSysconds(qk);
00439             rtsw->initCallbacks(rts_data.orb);
00440             rtsw->linkContract(qk);
00441             rtsw->linkRemoteObject(real_rts.in());
00442 
00443             /* Dump our IOR for the client to pickup later. */
00444             if( obj_ior != NULL )
00445             {
00446                 ofstream ostr(obj_ior);
00447                 ostr << rts_data.orb->object_to_string(rts.in()) << endl;
00448                 ostr.close();
00449             }
00450 
00451             cout << "RT server ready, waiting for connection from rt_client..."
00452                  << endl;
00453 
00454             rts_data.orb->run();
00455 
00456             if( !CORBA::is_nil(rts_data.rtt.in()) )
00457             {
00458                 rts_data.manager->RemoveTask(rts_data.rtt.in());
00459             }
00460                 
00461             rts_data.orb->shutdown();
00462 
00463             retval = EXIT_SUCCESS;
00464         }
00465         else
00466         {
00467             /* Somethings wrong, print the usage. */
00468             cerr << "CORBA Server that exerts synthetic CPU load." << endl
00469                  << "Usage: "
00470                  << argv[0]
00471                  << " [options] [<compute-time1> <compute-time2> ...]\n"
00472                 
00473                  << endl
00474                 
00475                  << "  -m <ior>\tThe Broker::Manager IOR."
00476                  << "  (Default: " << manager_ior << ")" << endl
00477                 
00478                  << "  -n <name>\tThe name of the task to create." << endl
00479                 
00480                  << "  -t <ior>\tThe Broker::RealTimeTask IOR." << endl
00481                 
00482                  << "  -o <file>\tThe file name for the object's IOR."
00483                  << "  (Default: " << obj_ior << ")" << endl
00484                 
00485                  << "  -P <time>\tThe task's period."
00486                  << "  (Default: " << period << ")" << endl
00487                 
00488                  << "  -f <time>\tThe amount of time to run for."
00489                  << "  (Default: forever)" << endl
00490                 
00491                  << endl
00492                 
00493                  << "Package: " << PACKAGE_STRING << endl
00494                  << "Contact: " << PACKAGE_BUGREPORT << endl;
00495         }
00496     }
00497     catch(const CORBA::SystemException &e)
00498     {
00499         cerr << "Caught Exception: " << e << endl;
00500     }
00501     catch(...)
00502     {
00503         cerr << "Caught an unhandled exception" << endl;
00504     }
00505     return( retval );
00506 }

Generated on Fri Oct 22 07:50:24 2004 for CPU Broker by  doxygen 1.3.9.1