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

rt_server.cc

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

Generated on Mon Dec 1 16:29:07 2003 for CPU Broker by doxygen 1.3.4