ARPDAS_QNX6 1.0
tmaR2.c
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include "nortlib.h"
00003 #include "tma.h"
00004 char rcsid_tmaR2_c[] = 
00005   "$Header: /cvsroot/arp-das/QNX6/tmlib/src/tmaR2.c,v 1.3 2009/11/18 20:46:18 ntallen Exp $";
00006 
00007 void tma_init_state( int partno, tma_state *cmds, const char *name ) {
00008   tma_prtn *p;
00009 
00010   if ( partno < tma_n_partitions ) {
00011         /* tma_new_state() sets part basetime, outputs STATETIME
00012            Does *not* set RUNTIME or NEXTTIME or next command area
00013            basetime is set only if tma_basetime is non-zero (set
00014            in tma_process first time after TM starts). lastcheck is 
00015            set to basetime. partno, name );
00016          */
00017         tma_new_state( partno, name );
00018         p = &tma_partitions[partno];
00019         p->cmds = cmds;
00020         p->next_cmd = 0;
00021         p->waiting = 0;
00022         p->lastcheck = p->basetime - 1;
00023         if ( p->basetime == 0L && p->cmds != 0 ) {
00024           /* Issue start-up commands (T==0, ">") */
00025           for (;;) {
00026                 cmds = &p->cmds[p->next_cmd];
00027                 if ( cmds->dt != 0 || cmds->cmd[0] != '>' )
00028                   break;
00029                 p->next_cmd++;
00030                 if ( cmds->cmd[1] == '_' ) ci_sendcmd(cmds->cmd+2, 2);
00031                 else ci_sendcmd(cmds->cmd+1, 0);
00032           }
00033         }
00034   }
00035 }
00036 
00037 /* tma_process returns 0 when no more action is required for any
00038    partition at the present time (now). Otherwise it returns
00039    a positive integer which is an index into case statement
00040    generated by tmcalgo for validating states. */
00041 int tma_process( long int now ) {
00042   int partno, success, state_case, Rpartno;
00043   tma_prtn *p;
00044   long int dt, pdt, timeout, lastcheck;
00045   const char *cmd;
00046   
00047   if (tma_runbasetime == 0L) {
00048         unsigned int i;
00049 
00050         tma_runbasetime = now;
00051         for (i = 0; i < tma_n_partitions; i++) {
00052           tma_partitions[i].basetime = now;
00053           tma_partitions[i].lastcheck = now-1;
00054         }
00055   }
00056   for ( partno = 0; partno < tma_n_partitions; partno++ ) {
00057         p = &tma_partitions[ partno ];
00058         if ( now != p->lastcheck ) {
00059           lastcheck = p->lastcheck;
00060           if ( lastcheck < p->basetime )
00061                 lastcheck = p->basetime;
00062           if ( p->waiting > 0 ) {
00063                 dt = now - lastcheck;
00064                 if ( dt >= p->waiting ) {
00065                   p->waiting = 0;
00066                   p->next_cmd++;
00067                 }
00068           }
00069           if ( p->waiting == 0 && tma_is_holding == 0 ) {
00070                 dt = now - p->basetime;
00071                 if ( p->cmds != 0 && p->next_cmd >= 0 ) {
00072                   while ( p->waiting == 0 ) {
00073                         pdt = p->cmds[p->next_cmd].dt;
00074                         cmd = p->cmds[p->next_cmd].cmd;
00075                         if ( pdt == -1 ) {
00076                           p->next_cmd = -1;
00077                           p->nexttime = 0;
00078                           break;
00079                         } else if ( pdt > dt ) {
00080                           if ( p->nexttime != pdt ) {
00081                                 p->nexttime = pdt;
00082                                 if ( ( p->next_str == 0 || *p->next_str == '\0' )
00083                                           && *cmd == '>' )
00084                                   p->next_str = cmd+1;
00085                           }
00086                           break;
00087                         } else {
00088                           p->next_cmd++;
00089                           switch( *cmd ) {
00090                                 case '>':
00091                                   if ( cmd[1] == '_' )
00092                                         ci_sendcmd(cmd+2, 2);
00093                                   else
00094                                         ci_sendcmd(cmd+1, 0);
00095                                   p->next_str = "";
00096                                   break;
00097                                 case '"':
00098                                   p->next_str = cmd;
00099                                   break;
00100                                 case '#':
00101                                   return atoi( cmd+1 );
00102                                 case '?':
00103                                   if ( sscanf( cmd+1, "%d,%ld,%d",
00104                                         &success, &timeout, &state_case ) != 3 )
00105                                         nl_error( 4, "Error reading hold command\n" );
00106                                   if ( timeout > 0 )
00107                                         timeout += pdt + p->basetime - lastcheck;
00108                                   p->waiting = timeout;
00109                                   p->next_cmd--;
00110                                   if ( state_case > 0 ) return state_case;
00111                                   break;
00112                                 case 'R':
00113                                   if ( sscanf( cmd+1, "%d,%d", &Rpartno,
00114                                                 &state_case ) != 2 )
00115                                         nl_error( 4, "Error reading Resume command\n" );
00116                                   tma_succeed( Rpartno, -state_case );
00117                                   if ( Rpartno < partno ) return -1;
00118                                   break;
00119                                 default:
00120                                   nl_error( 1, "Unknown cmd char %c in tma_process", *cmd );
00121                           }
00122                         }
00123                   }
00124                 }
00125           }
00126         }
00127   }
00128   for ( partno = 0; partno < tma_n_partitions; partno++ ) {
00129         p = &tma_partitions[ partno ];
00130         lastcheck = p->lastcheck;
00131         if ( lastcheck < p->basetime )
00132           lastcheck = p->basetime;
00133         dt = now - lastcheck;
00134         if ( dt != 0 ) {
00135           if ( p->waiting != 0 || tma_is_holding != 0 ) {
00136                 p->basetime += dt;
00137                 if ( p->waiting > dt ) {
00138                   p->waiting -= dt;
00139                 } else if ( p->waiting > 0 )
00140                   p->waiting = 0;
00141           }
00142         }
00143         if ( now != p->lastcheck ) {
00144           p->lastcheck = now;
00145           if ( p->row >= 0 ) {
00146                 if ( p->next_str != 0 ) {
00147                   tma_next_cmd( partno, p->next_str );
00148                   p->next_str = NULL;
00149                 }
00150                 tma_time( p, RUNTIME_COL, now - tma_runbasetime );
00151                 tma_time( p, STATETIME_COL, now - p->basetime );
00152                 pdt = p->nexttime;
00153                 switch ( pdt ) {
00154                   case -1: continue;
00155                   case 0:
00156                         pdt = 0;
00157                         p->nexttime = -1;
00158                         break;
00159                   default:
00160                         pdt += p->basetime - now;
00161                         break;
00162                 }
00163                 tma_time( p, NEXTTIME_COL, pdt );
00164           }
00165         }
00166   }
00167   return 0; /* Nothing left to do */
00168 }
00169 
00170 void tma_succeed( int partno, int statecase ) {
00171   tma_prtn *p;
00172   int success, state_case, res_case;
00173   long int timeout;
00174   const char *cmd;
00175 
00176   if ( partno < 0 || partno >= tma_n_partitions )
00177         nl_error( 4, "Invalid partno in tma_succeed" );
00178   p = &tma_partitions[ partno ];
00179   if ( p->cmds != 0 && p->next_cmd >= 0 ) {
00180         cmd = p->cmds[p->next_cmd].cmd;
00181         if ( cmd != 0 && *cmd == '?' ) {
00182           int n_args = sscanf( cmd+1, "%d,%ld,%d,%d",
00183                   &success, &timeout, &state_case, &res_case );
00184           if ( n_args < 3 ) nl_error( 4, "Error re-reading hold command\n" );
00185           if ( statecase > 0 && state_case != statecase )
00186                 nl_error( 1, "Different statecase active in tma_succeed" );
00187           else if ( statecase < 0 &&
00188                                 ( n_args < 4 || -statecase != res_case) ) {
00189                 if ( n_args < 4 )
00190                   nl_error( 1, "Resume not compatible with this version" );
00191                 else
00192                   nl_error( -3, "Resume(%d,%d): other state is holding", partno,
00193                                           -statecase );
00194           } else {
00195                 p->waiting = 0;
00196                 p->next_cmd += success;
00197           }
00198           return;
00199         }
00200   }
00201   if ( statecase < 0 )
00202         nl_error( -3, "Resume(%d,%d): Specified state not holding",
00203                 partno, -statecase );
00204   else nl_error( -3, "Hold(%d,%d) not active in tma_succeed",
00205                 partno, statecase );
00206 }
00207 
00208 /*
00209 =Name  <funcname>: <Description>
00210 =Name tma_init_state(): Initialize a new TMA state
00211 =Subject TMA Internal
00212 =Name tma_process(): Execute TMA commands
00213 =Subject TMA Internal
00214 =Name tma_succeed(): End TMA Hold states
00215 =Subject TMA Internal
00216 =Synopsis
00217 #include "tma.h"
00218 void tma_init_state( int partno, tma_state *cmds, char *name );
00219 int tma_process( long int now );
00220 void tma_succeed( int partno, int statecase );
00221 
00222 =Description
00223 
00224 These are support functions for TMCALGO algorithms. They are
00225 called from the .tmc code which TMCALGO generates. Users should
00226 not need to call these functions directly.
00227 
00228 tma_init_state() is called to when a TMA state is validated.
00229 It is responsible for initializing the status lines and setting
00230 up the internal structures which keep track of the current
00231 position within the algorithm.
00232 
00233 tma_process() is called every second to execute algorithm
00234 commands. Its single argument is the "current" data stream
00235 time. (This will be very close to the current time when
00236 running an algorithm in realtime, but during playback, it will
00237 be the time when the data was taken.)
00238 
00239 tma_succeed() is called to release a partition from a HOLD
00240 state. If statecase is greater than zero, it must match
00241 the third argument of the currently pending hold command.
00242 This form is generated by "Hold until" syntaxes. If statecase
00243 is less than zero, it must equal (but negative) to the fourth
00244 argument. This form is generated by the "Resume" statement.
00245 
00246 =Returns
00247 
00248 tma_process() returns zero if there is no more work to be done at
00249 this time. If it returns a non-zero value, the TMCALGO-generated
00250 .tmc program uses the value in a switch statement to select a
00251 state to validate. (This value is referred to as a "state_case"
00252 within the tmcalgo source code.) A return value of -1 indicates
00253 that work is not completed, but no action is required by the
00254 caller other than to call tma_process() again. This is necessary
00255 when a "Resume" command is executed, which may unblock a
00256 partition that has already been passed over.
00257 
00258 tma_init_state() and tma_succeed() have void returns.
00259 
00260 =SeeAlso
00261 
00262 =TMA Internal= functions.
00263 
00264 =End
00265 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines