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

rt_client.cc

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

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