Added seqcaStats routine, returns CA channel count information.
Annotate for file src/seq/seq_qry.c
2000-04-04 William 1 /**************************************************************************
03:23:15 ' 2 GTA PROJECT AT division
' 3 Copyright, 1990-1994, The Regents of the University of California.
' 4 Los Alamos National Laboratory
' 5 seq_qry.c,v 1.2 1995/06/27 15:26:02 wright Exp
' 6
' 7 DESCRIPTION: Task querry & debug routines for run-time sequencer:
' 8 seqShow - prints state set info.
' 9 seqChanShow - printf channel (pv) info.
' 10
' 11 ENVIRONMENT: VxWorks
' 12 HISTORY:
' 13 25nov91,ajk Display task names(s) with id(s).
' 14 Display logfile name and file descriptor.
' 15 Moved wait_rtn() to top of loop.
' 16 09dec91,ajk Modified to used state program linked list.
' 17 Added option to display all programs when tid=0.
' 18 19dec91,ajk Allow task name as well as task id.
' 19 25feb92,ajk V5.0 accepts 0 as a valid task id: fixed it.
' 20 26feb92,ajk Fixed formatting of task/program listing.
' 21 29apr92,ajk Modified to interpret encoded options.
' 22 21may92,ajk Modified format for listing programs & tasks.
' 23 21feb93,ajk Some minor code cleanup.
' 24 01mar94,ajk Major changes to print more meaningful information.
' 25 12aug96,wfl Add syncQ queue reporting.
' 26 22jan97,wfl Fix seqChanShow() not to list unassigned channels with "-".
' 27 17may99,wfl Fixed missing declaration for debug output.
' 28 06jul99,wfl Supported "+m" (main) option.
' 29 07sep99,wfl Added put completion and message.
' 30 18feb00,wfl Tidied up, avoided prevState undefined crash, output time
' 31 stamp unconditionally.
' 32 29feb00,wfl Supported new OSI; removed remaining OS-dependencies.
' 33 31mar00,wfl Removed limitation on only printing 5 array elements.
' 34 ***************************************************************************/
' 35
' 36 /*#define DEBUG 1*/
' 37
' 38 #include <string.h>
2000-04-14 Janet 39 /* #include <unistd.h> */
2000-04-04 William 40
2000-04-14 Janet 41 #define epicsExportSharedSymbols
2000-04-04 William 42 #include "seq.h"
03:23:15 ' 43
' 44 /* User functions */
' 45 LOCAL int wait_rtn();
' 46 LOCAL void printValue(char *, int, int);
2001-02-16 Marty 47 LOCAL SPROG *seqQryFind(epicsThreadId);
2000-04-04 William 48 LOCAL void seqShowAll();
03:23:15 ' 49
2005-01-20 Andrew 50 /* The seqTraverseProg function is in seq_prog.c */
16:49:06 ' 51 epicsStatus seqTraverseProg(void (*pFunc)(), void *param);
' 52
' 53
2000-04-04 William 54 /*
03:23:15 ' 55 * seqShow() - Query the sequencer for state information.
' 56 * If a non-zero thread id is specified then print the information about
' 57 * the state program, otherwise print a brief summary of all state programs
' 58 */
2001-03-22 Marty 59 long epicsShareAPI seqShow(epicsThreadId tid)
2000-04-04 William 60 {
03:23:15 ' 61 SPROG *pSP;
' 62 SSCB *pSS;
' 63 STATE *pST;
' 64 int nss;
' 65 double timeNow, timeElapsed;
' 66 #ifdef DEBUG
' 67 int n;
' 68 #endif
' 69
' 70 pSP = seqQryFind(tid);
' 71 if (pSP == NULL)
' 72 return 0;
' 73
' 74 /* Print info about state program */
' 75 printf("State Program: \"%s\"\n", pSP->pProgName);
2001-03-19 Marty 76 printf(" initial thread id = %p\n", pSP->threadId);
2000-04-04 William 77 printf(" thread priority = %d\n", pSP->threadPriority);
03:23:15 ' 78 printf(" number of state sets = %ld\n", pSP->numSS);
' 79 printf(" number of syncQ queues = %d\n", pSP->numQueues);
' 80 if (pSP->numQueues > 0)
2001-03-19 Marty 81 printf(" queue array address = %p\n",pSP->pQueues);
2000-04-04 William 82 printf(" number of channels = %ld\n", pSP->numChans);
03:23:15 ' 83 printf(" number of channels assigned = %ld\n", pSP->assignCount);
' 84 printf(" number of channels connected = %ld\n", pSP->connCount);
' 85 printf(" options: async=%d, debug=%d, newef=%d, reent=%d, conn=%d, "
' 86 "main=%d\n",
' 87 ((pSP->options & OPT_ASYNC) != 0), ((pSP->options & OPT_DEBUG) != 0),
' 88 ((pSP->options & OPT_NEWEF) != 0), ((pSP->options & OPT_REENT) != 0),
' 89 ((pSP->options & OPT_CONN) != 0), ((pSP->options & OPT_MAIN) != 0));
' 90 if ((pSP->options & OPT_REENT) != 0)
' 91 printf(" user variables: address = %lu = 0x%lx, length = %ld "
' 92 "= 0x%lx bytes\n", (unsigned long)pSP->pVar,
' 93 (unsigned long)pSP->pVar, pSP->varSize, pSP->varSize);
2001-02-16 W. 94 if (pSP->logFd) {
21:45:18 ' 95 printf(" log file fd = %d\n", fileno(pSP->logFd));
' 96 printf(" log file name = \"%s\"\n", pSP->pLogFile);
' 97 }
2000-04-04 William 98 printf("\n");
03:23:15 ' 99
' 100 /* Print state set info */
' 101 for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
' 102 {
' 103 printf(" State Set: \"%s\"\n", pSS->pSSName);
' 104
2001-02-16 Marty 105 if (pSS->threadId != (epicsThreadId)0)
2000-04-04 William 106 {
03:23:15 ' 107 char threadName[THREAD_NAME_SIZE];
2001-02-16 Marty 108 epicsThreadGetName(pSS->threadId, threadName,sizeof(threadName));
2000-04-04 William 109 printf(" thread name = %s;", threadName);
03:23:15 ' 110 }
' 111
' 112 printf(" thread id = %lu = 0x%lx\n",
' 113 (unsigned long) pSS->threadId, (unsigned long) pSS->threadId);
' 114
' 115 pST = pSS->pStates;
' 116 printf(" First state = \"%s\"\n", pST->pStateName);
' 117
' 118 pST = pSS->pStates + pSS->currentState;
' 119 printf(" Current state = \"%s\"\n", pST->pStateName);
' 120
' 121 pST = pSS->pStates + pSS->prevState;
' 122 printf(" Previous state = \"%s\"\n", pSS->prevState >= 0 ?
' 123 pST->pStateName : "");
' 124
' 125 pvTimeGetCurrentDouble(&timeNow);
' 126 timeElapsed = timeNow - pSS->timeEntered;
' 127 printf(" Elapsed time since state was entered = %.1f "
' 128 "seconds\n", timeElapsed);
' 129 #ifdef DEBUG
' 130 printf(" Queued time delays:\n");
' 131 for (n = 0; n < pSS->numDelays; n++)
' 132 {
' 133 printf("\tdelay[%2d]=%f", n, pSS->delay[n]);
' 134 if (pSS->delayExpired[n])
' 135 printf(" - expired");
' 136 printf("\n");
' 137 }
' 138 #endif /*DEBUG*/
' 139 printf("\n");
' 140 }
' 141
' 142 return 0;
' 143 }
' 144 /*
' 145 * seqChanShow() - Show channel information for a state program.
' 146 */
2001-03-22 Marty 147 long epicsShareAPI seqChanShow(epicsThreadId tid, char *pStr)
2000-04-04 William 148 {
03:23:15 ' 149 SPROG *pSP;
' 150 CHAN *pDB;
' 151 int nch, n;
' 152 char tsBfr[50], connQual;
' 153 int match, showAll;
' 154
' 155 pSP = seqQryFind(tid);
2001-03-19 Marty 156 if(!pSP) return 0;
2000-04-04 William 157
03:23:15 ' 158 printf("State Program: \"%s\"\n", pSP->pProgName);
' 159 printf("Number of channels=%ld\n", pSP->numChans);
' 160
' 161 if (pStr != NULL)
' 162 {
' 163 connQual = pStr[0];
' 164 /* Check for channel connect qualifier */
' 165 if ((connQual == '+') || (connQual == '-'))
' 166 {
' 167 pStr += 1;
' 168 }
' 169 }
' 170 else
' 171 connQual = 0;
' 172
' 173 pDB = pSP->pChan;
' 174 for (nch = 0; nch < pSP->numChans; )
' 175 {
' 176 if (pStr != NULL)
' 177 {
' 178 /* Check for channel connect qualifier */
' 179 if (connQual == '+')
' 180 showAll = pDB->connected;
' 181 else if (connQual == '-')
' 182 showAll = pDB->assigned && (!pDB->connected);
' 183 else
' 184 showAll = TRUE;
' 185
' 186 /* Check for pattern match if specified */
' 187 match = (pStr[0] == 0) ||
' 188 (strstr(pDB->dbName, pStr) != NULL);
' 189 if (!(match && showAll))
' 190 {
' 191 pDB += 1;
' 192 nch += 1;
' 193 continue; /* skip this channel */
' 194 }
' 195 }
' 196 printf("\n#%d of %ld:\n", nch+1, pSP->numChans);
' 197 printf("Channel name: \"%s\"\n", pDB->dbName);
' 198 printf(" Unexpanded (assigned) name: \"%s\"\n", pDB->dbAsName);
' 199 printf(" Variable name: \"%s\"\n", pDB->pVarName);
' 200 printf(" address = %lu = 0x%lx\n",
' 201 (unsigned long)pDB->pVar, (unsigned long)pDB->pVar);
' 202 printf(" type = %s\n", pDB->pVarType);
' 203 printf(" count = %ld\n", pDB->count);
' 204 printValue(pDB->pVar, pDB->putType, pDB->count);
' 205
' 206 printf(" Monitor flag = %d\n", pDB->monFlag);
' 207 if (pDB->monitored)
' 208 printf(" Monitored\n");
' 209 else
' 210 printf(" Not monitored\n");
' 211
' 212 if (pDB->assigned)
' 213 printf(" Assigned\n");
' 214 else
' 215 printf(" Not assigned\n");
' 216
' 217 if(pDB->connected)
' 218 printf(" Connected\n");
' 219 else
' 220 printf(" Not connected\n");
' 221
' 222 if(pDB->getComplete)
' 223 printf(" Last get completed\n");
' 224 else
' 225 printf(" Get not completed or no get issued\n");
' 226
' 227 if(pDB->putComplete)
' 228 printf(" Last put completed\n");
' 229 else
' 230 printf(" Put not completed or no put issued\n");
' 231
' 232 printf(" Status = %d\n", pDB->status);
' 233 printf(" Severity = %d\n", pDB->severity);
' 234 printf(" Message = %s\n", pDB->message != NULL ?
' 235 pDB->message : "");
' 236
' 237 /* Print time stamp in text format: "yyyy/mm/dd hh:mm:ss.sss" */
2001-02-16 Marty 238 epicsTimeToStrftime(tsBfr, sizeof(tsBfr),
2000-04-04 William 239 "%Y/%m/%d %H:%M:%S.%03f", &pDB->timeStamp);
03:23:15 ' 240 printf(" Time stamp = %s\n", tsBfr);
' 241
' 242 n = wait_rtn();
' 243 if (n == 0)
' 244 return 0;
' 245 nch += n;
' 246 if (nch < 0)
' 247 nch = 0;
' 248 pDB = pSP->pChan + nch;
' 249 }
' 250
' 251 return 0;
' 252 }
' 253 /*
2005-01-20 Andrew 254 * seqcar() - Sequencer Channel Access Report
16:49:06 ' 255 */
' 256
' 257 struct seqStats {
' 258 int level;
' 259 int nProgs;
' 260 int nChans;
' 261 int nConn;
' 262 };
' 263
' 264 LOCAL void seqcarCollect(SPROG *pSP, void *param) {
' 265 struct seqStats *pstats = (struct seqStats *) param;
' 266 CHAN *pDB = pSP->pChan;
' 267 int nch;
' 268 int level = pstats->level;
' 269 int printedProgName = 0;
' 270 pstats->nProgs++;
' 271 for (nch = 0; nch < pSP->numChans; nch++) {
' 272 if (pDB->assigned) pstats->nChans++;
' 273 if (pDB->connected) pstats->nConn++;
' 274 if (level > 1 ||
' 275 (level == 1 && !pDB->connected)) {
' 276 if (!printedProgName) {
' 277 printf(" Program \"%s\"\n", pSP->pProgName);
' 278 printedProgName = 1;
' 279 }
' 280 printf(" Variable \"%s\" %sconnected to PV \"%s\"\n",
' 281 pDB->pVarName,
' 282 pDB->connected ? "" : "not ",
' 283 pDB->dbName);
' 284 }
' 285 pDB++;
' 286 }
' 287 }
' 288
' 289 long epicsShareAPI seqcar(int level)
' 290 {
' 291 struct seqStats stats = {0, 0, 0, 0};
' 292 int diss;
' 293 stats.level = level;
' 294 seqTraverseProg(seqcarCollect, (void *) &stats);
' 295 diss = stats.nChans - stats.nConn;
' 296 printf("Total programs=%d, channels=%d, connected=%d, disconnected=%d\n",
' 297 stats.nProgs, stats.nChans, stats.nConn, diss);
' 298 return diss;
' 299 }
2008-07-22 Andrew 300
22:24:01 ' 301 void epicsShareAPI seqcaStats(int *pchans, int *pdiscon) {
' 302 struct seqStats stats = {0, 0, 0, 0};
' 303 seqTraverseProg(seqcarCollect, (void *) &stats);
' 304 if (pchans) *pchans = stats.nChans;
' 305 if (pdiscon) *pdiscon = stats.nChans - stats.nConn;
' 306 }
2005-01-20 Andrew 307 /*
2000-04-04 William 308 * seqQueueShow() - Show syncQ queue information for a state program.
03:23:15 ' 309 */
2001-03-22 Marty 310 long epicsShareAPI seqQueueShow(epicsThreadId tid)
2000-04-04 William 311 {
03:23:15 ' 312 SPROG *pSP;
' 313 ELLLIST *pQueue;
' 314 int nque, n;
' 315 char tsBfr[50];
' 316
' 317 pSP = seqQryFind(tid);
2001-03-19 Marty 318 if(!pSP) return 0;
2000-04-04 William 319
03:23:15 ' 320 printf("State Program: \"%s\"\n", pSP->pProgName);
' 321 printf("Number of queues = %d\n", pSP->numQueues);
' 322
' 323 pQueue = pSP->pQueues;
' 324 for (nque = 0; nque < pSP->numQueues; )
' 325 {
' 326 QENTRY *pEntry;
' 327 int i;
' 328
' 329 printf("\nQueue #%d of %d:\n", nque+1, pSP->numQueues);
' 330 printf("Number of entries = %d\n", ellCount(pQueue));
' 331 for (pEntry = (QENTRY *) ellFirst(pQueue), i = 1;
' 332 pEntry != NULL;
2002-03-25 W. 333 pEntry = (QENTRY *) ellNext(&pEntry->node), i++)
2000-04-04 William 334 {
03:23:15 ' 335 CHAN *pDB = pEntry->pDB;
' 336 pvValue *pAccess = &pEntry->value;
' 337 void *pVal = (char *)pAccess + pDB->dbOffset;
' 338
' 339 printf("\nEntry #%d: channel name: \"%s\"\n",
' 340 i, pDB->dbName);
' 341 printf(" Variable name: \"%s\"\n", pDB->pVarName);
' 342 printValue(pVal, pDB->putType, 1);
' 343 /* was pDB->count */
' 344 printf(" Status = %d\n",
' 345 pAccess->timeStringVal.status);
' 346 printf(" Severity = %d\n",
' 347 pAccess->timeStringVal.severity);
' 348
' 349 /* Print time stamp in text format:
' 350 "yyyy/mm/dd hh:mm:ss.sss" */
2001-02-16 Marty 351 epicsTimeToStrftime(tsBfr, sizeof(tsBfr), "%Y/%m/%d "
2000-04-04 William 352 "%H:%M:%S.%03f", &pAccess->timeStringVal.stamp);
03:23:15 ' 353 printf(" Time stamp = %s\n", tsBfr);
' 354 }
' 355
' 356 n = wait_rtn();
' 357 if (n == 0)
' 358 return 0;
' 359 nque += n;
' 360 if (nque < 0)
' 361 nque = 0;
' 362 pQueue = pSP->pQueues + nque;
' 363 }
' 364
' 365 return 0;
' 366 }
' 367
' 368 /* Read from console until a RETURN is detected */
' 369 LOCAL int wait_rtn()
' 370 {
' 371 char bfr[10];
' 372 int i, n;
' 373
' 374 printf("Next? (+/- skip count)\n");
' 375 for (i = 0; i < 10; i++)
' 376 {
2001-02-16 W. 377 int c = getchar ();
21:45:18 ' 378 if (c == EOF)
' 379 break;
' 380 if ((bfr[i] = c) == '\n')
2000-04-04 William 381 break;
03:23:15 ' 382 }
' 383 bfr[i] = 0;
' 384 if (bfr[0] == 'q')
' 385 return 0; /* quit */
' 386
' 387 n = atoi(bfr);
' 388 if (n == 0)
' 389 n = 1;
' 390 return n;
' 391 }
' 392
' 393 /* Print the current internal value of a database channel */
' 394 LOCAL void printValue(pVal, type, count)
' 395 char *pVal;
' 396 int count, type;
' 397 {
' 398 int i;
' 399 char *c;
' 400 short *s;
' 401 long *l;
' 402 float *f;
' 403 double *d;
' 404
' 405 printf(" Value =");
' 406 for (i = 0; i < count; i++)
' 407 {
' 408 switch (type)
' 409 {
' 410 case pvTypeSTRING:
' 411 c = (char *)pVal;
' 412 for (i = 0; i < count; i++, c += sizeof(pvString))
' 413 {
' 414 printf(" %s", c);
' 415 }
' 416 break;
' 417
' 418 case pvTypeCHAR:
' 419 c = (char *)pVal;
' 420 for (i = 0; i < count; i++, c++)
' 421 {
' 422 printf(" %d", *c);
' 423 }
' 424 break;
' 425
' 426 case pvTypeSHORT:
' 427 s = (short *)pVal;
' 428 for (i = 0; i < count; i++, s++)
' 429 {
' 430 printf(" %d", *s);
' 431 }
' 432 break;
' 433
' 434 case pvTypeLONG:
' 435 l = (long *)pVal;
' 436 for (i = 0; i < count; i++, l++)
' 437 {
' 438 printf(" %ld", *l);
' 439 }
' 440 break;
' 441
' 442 case pvTypeFLOAT:
' 443 f = (float *)pVal;
' 444 for (i = 0; i < count; i++, f++)
' 445 {
' 446 printf(" %g", *f);
' 447 }
' 448 break;
' 449
' 450 case pvTypeDOUBLE:
' 451 d = (double *)pVal;
' 452 for (i = 0; i < count; i++, d++)
' 453 {
' 454 printf(" %g", *d);
' 455 }
' 456 break;
' 457 }
' 458 }
' 459
' 460 printf("\n");
' 461 }
' 462
' 463 /* Find a state program associated with a given thread id */
2001-02-16 Marty 464 LOCAL SPROG *seqQryFind(epicsThreadId tid)
2000-04-04 William 465 {
03:23:15 ' 466 SPROG *pSP;
' 467
' 468 if (tid == 0)
' 469 {
' 470 seqShowAll();
' 471 return NULL;
' 472 }
' 473
' 474 /* Find a state program that has this thread id */
' 475 pSP = seqFindProg(tid);
' 476 if (pSP == NULL)
' 477 {
' 478 printf("No state program exists for thread id %d\n", (int)tid);
' 479 return NULL;
' 480 }
' 481
' 482 return pSP;
' 483 }
' 484
' 485 LOCAL int seqProgCount;
' 486
' 487 /* This routine is called by seqTraverseProg() for seqShowAll() */
' 488 LOCAL void seqShowSP(pSP)
' 489 SPROG *pSP;
' 490 {
' 491 SSCB *pSS;
' 492 int nss;
' 493 char *progName;
' 494 char threadName[THREAD_NAME_SIZE];
' 495
' 496 if (seqProgCount++ == 0)
' 497 printf("Program Name Thread ID Thread Name SS Name\n\n");
' 498
' 499 progName = pSP->pProgName;
' 500 for (nss = 0, pSS = pSP->pSS; nss < pSP->numSS; nss++, pSS++)
' 501 {
' 502 if (pSS->threadId == 0)
' 503 strcpy(threadName,"(no thread)");
' 504 else
2001-02-16 Marty 505 epicsThreadGetName(pSS->threadId, threadName,
2000-04-04 William 506 sizeof(threadName));
2001-03-19 Marty 507 printf("%-16s %-10p %-16s %-16s\n", progName,
21:07:52 ' 508 pSS->threadId, threadName, pSS->pSSName );
2000-04-04 William 509 progName = "";
03:23:15 ' 510 }
' 511 printf("\n");
' 512 }
' 513
' 514 /* Print a brief summary of all state programs */
' 515 LOCAL void seqShowAll()
' 516 {
' 517
' 518 seqProgCount = 0;
' 519 seqTraverseProg(seqShowSP, 0);
' 520 if (seqProgCount == 0)
' 521 printf("No active state programs\n");
' 522 return;
' 523 }