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

rt_client.cc

Go to the documentation of this file.
00001 /*
00002  * rt_client.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_client.cc
00014  *
00015  * CORBA Client used to drive the real-time synthetic server.
00016  *
00017  * @sa RTServer.idl
00018  * @sa rt_server.cc
00019  */
00020 
00021 #include "config.h"
00022 
00023 #undef DEBUG
00024 
00025 #include <errno.h>
00026 
00027 #if TIME_WITH_SYS_TIME
00028 # include <sys/time.h>
00029 # include <time.h>
00030 #else
00031 # if HAVE_SYS_TIME_H
00032 #  include <sys/time.h>
00033 # else
00034 #  include <time.h>
00035 # endif
00036 #endif
00037 
00038 #include <time_util.h>
00039 
00040 #include <iostream>
00041 
00042 #include "RTServerC.h"
00043 
00044 using namespace std;
00045 
00046 #if !defined(timespecclear)
00047 /**
00048  * Clear a timespec structure.
00049  *
00050  * @param tvp Pointer to the timespec object to clear.
00051  */
00052 #define timespecclear(tvp)      ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
00053 
00054 /**
00055  * Test if a timespec has non-zero values.
00056  *
00057  * @param tvp Pointer to the timespec object to check.
00058  */
00059 #define timespecisset(tvp)      ((tvp)->tv_sec || (tvp)->tv_nsec)
00060 
00061 /**
00062  * Compare two timespec structures.
00063  *
00064  * @param tvp Pointer to the 'left hand side' of the comparison.
00065  * @param uvp Pointer to the 'right hande side' of the comparison.
00066  * @param cmp The comparison operator.  (e.g. '<', '>', ...)
00067  */
00068 #define timespeccmp(tvp, uvp, cmp)                                      \
00069         (((tvp)->tv_sec == (uvp)->tv_sec) ?                             \
00070             ((tvp)->tv_nsec cmp (uvp)->tv_nsec) :                       \
00071             ((tvp)->tv_sec cmp (uvp)->tv_sec))
00072 
00073 /**
00074  * Add one timespec to another.
00075  *
00076  * @param vvp Pointer to the timespec that will be added to.
00077  * @param uvp Pointer to the timespec to add.
00078  */
00079 #define timespecadd(vvp, uvp)                                           \
00080         do {                                                            \
00081                 (vvp)->tv_sec += (uvp)->tv_sec;                         \
00082                 (vvp)->tv_nsec += (uvp)->tv_nsec;                       \
00083                 if ((vvp)->tv_nsec >= 1000000000) {                     \
00084                         (vvp)->tv_sec++;                                \
00085                         (vvp)->tv_nsec -= 1000000000;                   \
00086                 }                                                       \
00087         } while (0)
00088 
00089 /**
00090  * Subtract one timespec from another.
00091  *
00092  * @param vvp Pointer to the timespec that will be subtracted from.
00093  * @param uvp Pointer to the timespec to subtract.
00094  */
00095 #define timespecsub(vvp, uvp)                                           \
00096         do {                                                            \
00097                 (vvp)->tv_sec -= (uvp)->tv_sec;                         \
00098                 (vvp)->tv_nsec -= (uvp)->tv_nsec;                       \
00099                 if ((vvp)->tv_nsec < 0) {                               \
00100                         (vvp)->tv_sec--;                                \
00101                         (vvp)->tv_nsec += 1000000000;                   \
00102                 }                                                       \
00103         } while (0)
00104 #endif
00105 
00106 /**
00107  * The CORBA ORB for this process.
00108  */
00109 static CORBA::ORB_var orb;
00110 
00111 /**
00112  * Handle SIGALRM signal by exiting.
00113  *
00114  * @param sig The actual signal received.
00115  */
00116 static void sigalrm_handler(int sig)
00117 {
00118     orb->shutdown();
00119     
00120     exit(0);
00121 }
00122 
00123 int main(int argc, char *argv[])
00124 {
00125     int retval = EXIT_FAILURE;
00126 
00127     try
00128     {
00129         const char *server_ior = "file://rtserver.ior";
00130         CORBA::ULong period = 1000000;
00131         unsigned long run_time = 0;
00132         struct timespec interval;
00133         int ch, g2g = 1;
00134 
00135         /* Start up the ORB, */
00136         orb = CORBA::ORB_init(argc, argv);
00137 
00138         /* ... process the arguments, */
00139         while( ((ch = getopt(argc, argv, "hVf:s:P:")) != -1) && g2g )
00140         {
00141             switch( ch )
00142             {
00143             case 'f':
00144                 {
00145                     unsigned long long run_time_ull;
00146                     
00147                     if( string_to_microsec(&run_time_ull, optarg) )
00148                     {
00149                         run_time = run_time_ull;
00150                     }
00151                     else
00152                     {
00153                         cerr << "Error: Run for value not a time: "
00154                              << period
00155                              << endl;
00156                         throw CORBA::BAD_PARAM();
00157                     }
00158                 }
00159                 break;
00160             case 's':
00161                 if( strlen(optarg) == 0 )
00162                 {
00163                     cerr << "Error: Server IOR is empty" << endl;
00164                     throw CORBA::BAD_PARAM();
00165                 }
00166                 server_ior = optarg;
00167                 break;
00168             case 'P':
00169                 {
00170                     unsigned long long period_ull;
00171                     
00172                     if( string_to_microsec(&period_ull, optarg) )
00173                     {
00174                         period = period_ull;
00175                     }
00176                     else
00177                     {
00178                         cerr << "Error: Period value is not a number: "
00179                              << optarg
00180                              << endl;
00181                         throw CORBA::BAD_PARAM();
00182                     }
00183                 }
00184                 break;
00185             case 'V':
00186                 cout << PACKAGE_VERSION << endl;
00187                 exit(0);
00188                 break;
00189             case 'h':
00190             case '?':
00191             default:
00192                 g2g = 0;
00193                 break;
00194             }
00195         }
00196 
00197         /* ... make sure there are no extraneous arguments, and */
00198         if( g2g && (optind != argc) )
00199         {
00200             cerr << "Error: Extra arguments" << endl;
00201             throw CORBA::BAD_PARAM();
00202         }
00203 
00204         /* ... continue if we are good to go. */
00205         if( g2g )
00206         {
00207             interval.tv_sec = period / 1000000;
00208             interval.tv_nsec = (period % 1000000) * 1000;
00209             
00210             if( run_time > 0 )
00211             {
00212                 struct itimerval itv;
00213                 
00214                 signal(SIGALRM, sigalrm_handler);
00215                 itv.it_interval.tv_sec = 0;
00216                 itv.it_interval.tv_usec = 0;
00217                 itv.it_value.tv_sec = run_time / 1000000;
00218                 itv.it_value.tv_usec = run_time % 1000000;
00219                 if( setitimer(ITIMER_REAL, &itv, NULL) < 0 )
00220                 {
00221                     perror("setitimer");
00222                 }
00223             }
00224             
00225             CORBA::Object_var obj = orb->string_to_object(server_ior);
00226             
00227             RTServer_var rts;
00228             
00229             rts = RTServer::_narrow(obj.in());
00230             if( CORBA::is_nil(rts.in()) )
00231             {
00232                 cerr << "Invalid RTServer IOR: " << endl;
00233                 throw CORBA::BAD_PARAM();
00234             }
00235             else
00236             {
00237                 struct timespec start, end, next;
00238                 int eventCount = 1;
00239                 
00240                 for( ;; )
00241                 {
00242                     clock_gettime(CLOCK_REALTIME, &start);
00243                     next = start;
00244                     timespecadd(&next, &interval);
00245                     rts->Periodic();
00246                     clock_gettime(CLOCK_REALTIME, &end);
00247                     timespecsub(&next, &end);
00248                     
00249                     timespecsub(&end, &interval);
00250                     eventCount -= 1;
00251                     while( timespeccmp(&start, &end, <) )
00252                     {
00253                         timespecsub(&end, &interval);
00254                         eventCount += 1;
00255                     }
00256 #if defined(DEBUG)
00257                     cout << "Queued Events = " << eventCount << endl;
00258 #endif
00259                     if( eventCount == 0 )
00260                     {
00261                         int rc;
00262                         
00263                         while( (rc = nanosleep(&next, NULL)) == -1 )
00264                         {
00265                             perror("nanosleep");
00266                             
00267                             ensure(errno == EINTR);
00268                         }
00269                         eventCount += 1;
00270                     }
00271                 }
00272                 
00273                 retval = EXIT_SUCCESS;
00274             }
00275         }
00276     }
00277     catch(const CORBA::SystemException &e)
00278     {
00279         cerr << "Caught Exception: " << e << endl;
00280     }
00281     catch(...)
00282     {
00283         cerr << "Caught an unhandled exception" << endl;
00284     }
00285     return( retval );
00286 }

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