static void exCB(struct exception_handler_args args) { #define MAX_EXCEPTIONS 25 static int nexceptions=0; static int ended=0; if(ended) return; if(nexceptions++ > MAX_EXCEPTIONS) { ended=1; fprintf(stderr,"exCB Exception: Channel Access Exception:\n" "Too many exceptions [%d]\n" "No more will be handled\n" "Please fix the problem and restart camonitorpv", MAX_EXCEPTIONS); ca_add_exception_event(NULL, NULL); return; } fprintf(stderr,"exCB Exception: Channel Access Exception:\n" " Channel Name: %s\n" " Native Type: %s\n" " Native Count: %lu\n" " Access: %s%s\n" " IOC: %s\n" " Message: %s\n" " Context: %s\n" " Requested Type: %s\n" " Requested Count: %ld\n" " Source File: %s\n" " Line number: %u", args.chid?ca_name(args.chid):"Unavailable", args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable", args.chid?ca_element_count(args.chid):0, args.chid?(ca_read_access(args.chid)?"R":""):"Unavailable", args.chid?(ca_write_access(args.chid)?"W":""):"", args.chid?ca_host_name(args.chid):"Unavailable", ca_message(args.stat)?ca_message(args.stat):"Unavailable", args.ctx?args.ctx:"Unavailable", dbf_type_to_text(args.type), args.count, args.pFile?args.pFile:"Unavailable", args.pFile?args.lineNo:0); }
void dbSubscriptionIO::show ( epicsGuard < epicsMutex > & guard, unsigned level ) const { guard.assertIdenticalMutex ( this->mutex ); printf ( "Data base subscription IO at %p\n", static_cast <const void *> ( this ) ); if ( level > 0u ) { short tmpType; if ( this->type < SHRT_MAX ) { tmpType = static_cast < short > ( this->type ); printf ( "\ttype %s, count %lu, channel at %p\n", dbf_type_to_text ( tmpType ), this->count, static_cast <void *> ( &this->chan ) ); } else { printf ( "strange type !, count %lu, channel at %p\n", this->count, static_cast <void *> ( &this->chan ) ); } } }
static void medmConnectEventCb(struct connection_handler_args args) { int status; Channel *pCh = (Channel *)ca_puser(args.chid); int count; /* Increment the event counter */ caTask.caEventCount++; /* Check for valid values */ if(globalDisplayListTraversalMode != DL_EXECUTE) return; if(!pCh || !pCh->chid || !pCh->pr) { medmPostMsg(0,"medmConnectEventCb: Invalid channel information\n"); return; } /* Do a get every time a channel is connected or reconnected and has * read access. The get will cause the graphical info callback to * be called */ if(args.op == CA_OP_CONN_UP && ca_read_access(pCh->chid)) { status = ca_array_get_callback( dbf_type_to_DBR_CTRL(ca_field_type(args.chid)), 1, args.chid, medmUpdateGraphicalInfoCb, NULL); if(status != ECA_NORMAL) { medmPostMsg(0,"medmConnectEventCb: " "ca_array_get_callback [%s]:\n %s\n", ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown", ca_message(status)); #if DEBUG_CONNECTION # if 0 system("netstat | grep iocacis"); # endif print(" pCh->chid %s args.chid\n", pCh->chid == args.chid?"==":"!="); print( " Channel Name: %s\n" " State: %s\n" " Native Type: %s\n" " Native Count: %hu\n" " Access: %s%s\n" " IOC: %s\n", args.chid?ca_name(args.chid):"Unavailable", args.chid?ca_state(args.chid) == cs_never_conn?"Never": ca_state(args.chid) == cs_prev_conn?"Prev": ca_state(args.chid) == cs_conn?"Conn": ca_state(args.chid) == cs_closed?"Closed":"Unknown":"Unavailable", args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable", args.chid?ca_element_count(args.chid):0, args.chid?(ca_read_access(args.chid)?"R":"None"):"Unavailable", args.chid?(ca_write_access(args.chid)?"W":""):"", args.chid?ca_host_name(args.chid):"Unavailable"); #endif } } /* Handle four cases: connected or not and previously connected or not */ if(args.op == CA_OP_CONN_UP) { /* Connected */ if(pCh->previouslyConnected == False) { /* Connected and not previously connected */ /* Set these first so they will be right for the updateValueCb */ pCh->pr->elementCount = ca_element_count(pCh->chid); pCh->pr->dataType = ca_field_type(args.chid); pCh->pr->connected = True; caTask.channelConnected++; /* Add the access-rights-change callback and the significant-change (value, alarm or severity) callback. Don't call the updateValueCb because ca_replace_access_rights_event will call it. */ status = ca_replace_access_rights_event( pCh->chid,medmReplaceAccessRightsEventCb); if(status != ECA_NORMAL) { medmPostMsg(0,"medmConnectEventCb: " "ca_replace_access_rights_event [%s]: %s\n", ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown", ca_message(status)); } if(pCh->pr->currentCount == -2) { count=0; } else { count=ca_element_count(pCh->chid); } #ifdef __USING_TIME_STAMP__ status = ca_add_array_event( dbf_type_to_DBR_TIME(ca_field_type(pCh->chid)), count, pCh->chid, medmUpdateChannelCb, pCh, 0.0,0.0,0.0, &(pCh->evid)); #else status = ca_add_array_event( dbf_type_to_DBR_STS(ca_field_type(pCh->chid)), count, pCh->chid, medmUpdateChannelCb, pCh, 0.0,0.0,0.0, &(pCh->evid)); #endif if(status != ECA_NORMAL) { /* Set the pointer to NULL in case CA didn't. We don't want to use it or clear it later. */ #if DEBUG_CONNECTION if(!pCh->evid) { print("medmConnectEventCb: ca_add_array_event: \n" " status[%d] != ECA_NORMAL and pCh->evid != NULL\n", status); } #endif pCh->evid = NULL; medmPostMsg(0,"medmConnectEventCb: " "ca_add_array_event [%s]:\n %s\n", ca_name(pCh->chid)?ca_name(pCh->chid):"Unknown", ca_message(status)); #if DEBUG_CONNECTION # if 0 system("netstat | grep iocacis"); # endif print(" pCh->chid %s args.chid\n", pCh->chid == args.chid?"==":"!="); print( " Channel Name: %s\n" " State: %s\n" " Native Type: %s\n" " Native Count: %hu\n" " Access: %s%s\n" " IOC: %s\n", args.chid?ca_name(args.chid):"Unavailable", args.chid?ca_state(args.chid) == cs_never_conn?"Never": ca_state(args.chid) == cs_prev_conn?"Prev": ca_state(args.chid) == cs_conn?"Conn": ca_state(args.chid) == cs_closed?"Closed":"Unknown":"Unavailable", args.chid?dbf_type_to_text(ca_field_type(args.chid)):"Unavailable", args.chid?ca_element_count(args.chid):0, args.chid?(ca_read_access(args.chid)?"R":"None"):"Unavailable", args.chid?(ca_write_access(args.chid)?"W":""):"", args.chid?ca_host_name(args.chid):"Unavailable"); #endif } /* Set this one last so ca_replace_access_rights_event can use the old value */ pCh->previouslyConnected = True; } else { /* Connected and previously connected */ pCh->pr->connected = True; caTask.channelConnected++; if(pCh->pr->updateValueCb) pCh->pr->updateValueCb((XtPointer)pCh->pr); } } else { /* Not connected */ if(pCh->previouslyConnected == False) { /* Not connected and not previously connected */ /* Probably doesn't happen -- if CA can't connect, this * routine never gets called */ pCh->pr->connected = False; } else { /* Not connected but previously connected */ pCh->pr->connected = False; caTask.channelConnected--; if(pCh->pr->updateValueCb) pCh->pr->updateValueCb((XtPointer)pCh->pr); } } }
static void pvInfoWriteInfo(void) { time_t now; struct tm *tblock; char timeStampStr[TIME_STRING_MAX]; Record *pR; chid chId; char *descVal; #if defined(DBR_CLASS_NAME) && DO_RTYP char *rtypVal; #endif DlElement *pE; char *elementType; static char noType[]="Unknown"; struct dbr_time_string timeVal; char string[1024]; /* Danger: Fixed length */ XmTextPosition curpos = 0; int i, j; /* Free the timeout */ if(pvInfoTimerOn) { XtRemoveTimeOut(pvInfoTimeoutId); pvInfoTimerOn = False; } /* Just clean up and abort if we get called with no pvInfo * (Shouldn't happen) */ if(!pvInfo) return; /* Get timestamp */ time(&now); tblock = localtime(&now); strftime(timeStampStr, TIME_STRING_MAX, STRFTIME_FORMAT"\n", tblock); timeStampStr[TIME_STRING_MAX-1]='\0'; /* Get element type */ pE = pvInfoElement; if(pE && pE->type >= MIN_DL_ELEMENT_TYPE && pE->type <= MAX_DL_ELEMENT_TYPE) { elementType=elementType(pE->type); } else { elementType=noType; } /* Heading */ sprintf(string, " PV Information\n\nObject: %s\n%s\n", elementType, timeStampStr); XmTextSetInsertionPosition(pvInfoMessageBox, 0); XmTextSetString(pvInfoMessageBox, string); curpos+=strlen(string); /* Loop over the records to print information */ for(i=0; i < nPvInfoPvs; i++) { /* Check for a valid record */ if(!pvInfo[i].pvOk) continue; chId = pvInfo[i].pvChid; timeVal = pvInfo[i].timeVal; pR = pvInfo[i].record; /* Name */ sprintf(string, "%s\n" "======================================\n", ca_name(chId)); /* DESC */ descVal = pvInfo[i].descVal; if(pvInfo[i].descOk && descVal) { sprintf(string, "%sDESC: %s\n", string, descVal); } else { sprintf(string, "%sDESC: %s\n", string, NOT_AVAILABLE); } if(pvInfo[i].descChid) ca_clear_channel(pvInfo[i].descChid); #if defined(DBR_CLASS_NAME) && DO_RTYP /* RTYP */ rtypVal = pvInfo[i].rtypVal; if(pvInfo[i].rtypOk && rtypVal && *rtypVal) { sprintf(string, "%sRTYP: %s\n", string, rtypVal); } else { sprintf(string, "%sRTYP: %s\n", string, NOT_AVAILABLE); } #endif /* Items from chid */ sprintf(string, "%sTYPE: %s\n", string, dbf_type_to_text(ca_field_type(chId))); /* ca_element_count is defined differently in 3.14 vs. 3.13 */ sprintf(string, "%sCOUNT: %lu\n", string, (unsigned long)ca_element_count(chId)); sprintf(string, "%sACCESS: %s%s\n", string, ca_read_access(chId)?"R":"", ca_write_access(chId)?"W":""); sprintf(string, "%sIOC: %s\n", string, ca_host_name(chId)); if(timeVal.value) { char fracPart[10]; /* Do the value */ if(ca_element_count(chId) == 1) { sprintf(string, "%sVALUE: %s\n", string, timeVal.value); } else { sprintf(string, "%sFIRST VALUE: %s\n", string, timeVal.value); } /* Convert the seconds part of the timestamp to UNIX time */ now = timeVal.stamp.secPastEpoch + 631152000ul; tblock = localtime(&now); strftime(timeStampStr, TIME_STRING_MAX, "%a %b %d, %Y %H:%M:%S", tblock); timeStampStr[TIME_STRING_MAX-1]='\0'; /* Get the fractional part. This assumes strftime truncates seconds rather than rounding them, which seems to be the case. */ sprintf(fracPart, "%09d",timeVal.stamp.nsec); /* Truncate to 3 figures */ fracPart[3]='\0'; sprintf(timeStampStr,"%s.%s", timeStampStr, fracPart); timeStampStr[TIME_STRING_MAX-1]='\0'; sprintf(string, "%sSTAMP: %s\n", string, timeStampStr); #if DEBUG_TIMESTAMP /* This prints 9 significant figures and requires 3.13 base */ { char tsTxt[32]; sprintf(string,"%sSTAMP: %s\n",string, tsStampToText(&timeVal.stamp,TS_TEXT_MONDDYYYY,tsTxt)); } #endif } else { sprintf(string, "%sVALUE: %s\n", string, NOT_AVAILABLE); sprintf(string, "%sSTAMP: %s\n", string, NOT_AVAILABLE); } XmTextInsert(pvInfoMessageBox, curpos, string); curpos+=strlen(string); /* Alarms */ switch(pR->severity) { case NO_ALARM: sprintf(string, "ALARM: NO\n"); break; case MINOR_ALARM: sprintf(string, "ALARM: MINOR\n"); break; case MAJOR_ALARM: sprintf(string, "ALARM: MAJOR\n"); break; case INVALID_ALARM: sprintf(string, "ALARM: INVALID\n"); break; default: sprintf(string, "ALARM: Unknown\n"); break; } XmTextInsert(pvInfoMessageBox, curpos, string); curpos+=strlen(string); /* Items from record */ sprintf(string, "\n"); switch(ca_field_type(chId)) { case DBF_STRING: break; case DBF_ENUM: sprintf(string, "%sSTATES: %d\n", string, (int)(pR->hopr+1.1)); /* KE: Bad way to use a double */ if(pR->hopr) { for (j=0; j <= pR->hopr; j++) { sprintf(string, "%sSTATE %2d: %s\n", string, j, pR->stateStrings[j]); } } break; case DBF_CHAR: case DBF_INT: case DBF_LONG: sprintf(string, "%sHOPR: %g LOPR: %g\n", string, pR->hopr, pR->lopr); break; case DBF_FLOAT: case DBF_DOUBLE: if(pR->precision >= 0 && pR->precision <= 17) { sprintf(string, "%sPRECISION: %d\n", string, pR->precision); } else { sprintf(string, "%sPRECISION: %d [Bad Value]\n", string, pR->precision); } sprintf(string, "%sHOPR: %g LOPR: %g\n", string, pR->hopr, pR->lopr); break; default: break; } sprintf(string, "%s\n", string); XmTextInsert(pvInfoMessageBox, curpos, string); curpos+=strlen(string); } /* Pop it up unless we have left EXECUTE mode */ if(globalDisplayListTraversalMode == DL_EXECUTE) { XtSetSensitive(pvInfoS, True); XtPopup(pvInfoS, XtGrabNone); } /* Free space */ if(pvInfo) free((char *)pvInfo); pvInfo = NULL; pvInfoElement = NULL; }