void SessionSummaryThr::run() { if ( mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION ) { cerr<< "Library/header version number mismatch" << endl; return; }; MyNode mynode(mpSession); //mynode.prevshotnum = startshot; SEVCHK(ca_context_create(ca_disable_preemptive_callback),"ca_context_create"); SEVCHK(ca_add_exception_event(exceptionCallback,NULL), "ca_add_exception_event"); //string pvnames[]={"CCS_SHOT_NUMBER","CCS_PERFORM_SHOT_SUMMARY"}; //Test.. //SEVCHK(ca_create_channel("DDS2_getState",connectionCallback, // &mynode,10,(oldChannelNotify**)&mynode.summary_chid), "ca_create_channel"); SEVCHK(ca_create_channel("CCS_PERFORM_SHOT_SUMMARY",connectionCallback, &mynode,10,(oldChannelNotify**)&mynode.summary_chid), "ca_create_channel"); SEVCHK(ca_replace_access_rights_event(mynode.summary_chid, accessRightsCallback), "ca_replace_access_rights_event"); ca_create_subscription (DBR_TIME_LONG, 0, mynode.summary_chid, DBE_VALUE|DBE_ALARM, eventCallback, (void*)&mynode, NULL); /*Should never return from following call*/ SEVCHK(ca_pend_event(0.0),"ca_pend_event"); }
static void caDelete(Record *pr) { int status; Channel *pCh; if(!pr) return; pCh = &((caTask.pages[pr->caId/CA_PAGE_SIZE]) [pr->caId % CA_PAGE_SIZE]); if(ca_state(pCh->chid) == cs_conn) caTask.channelConnected--; #if 0 /* KE: This is not necessary according to Jeff */ ca_change_connection_event(pCh->chid,NULL); ca_replace_access_rights_event(pCh->chid,NULL); #endif if(pCh->evid) { status = ca_clear_event(pCh->evid); if(status != ECA_NORMAL) { medmPostMsg(1,"caDelete: ca_clear_event failed: %s\n", ca_message(status)); return; } } pCh->evid = NULL; if(pCh->chid) { status = ca_clear_channel(pCh->chid); if(status != ECA_NORMAL) { medmPostMsg(1,"caDelete: ca_clear_channel failed: %s\n", ca_message(status)); return; } } pCh->chid = NULL; if(pCh->data) { free((char *)pCh->data); pCh->data = NULL; } if(caTask.freeListCount >= caTask.freeListSize) { caTask.freeListSize += CA_PAGE_SIZE; #if defined(__cplusplus) && !defined(__GNUG__) caTask.freeList = (int *) realloc((malloc_t)caTask.freeList, sizeof(int)*caTask.freeListSize); #else caTask.freeList = (int *) realloc(caTask.freeList, sizeof(int)*caTask.freeListSize); #endif if(caTask.freeList == NULL) { medmPostMsg(1,"caDelete: Memory allocation error\n"); return; } } caTask.freeList[caTask.freeListCount] = pCh->caId; caTask.freeListCount++; caTask.channelCount--; #if DEBUG_ADD print("caAdd: channelCount=%3d\n",caTask.channelCount); #endif }
int main(int argc, char** argv) { fd_set rfds; int tot; struct timeval tv; if(argc!=3) { fprintf(stderr,"Usage: %s PV_to_monitor script_to_run\n\n",argv[0]); fprintf(stderr,"This program monitored PV PV_to_monitor and\n"); fprintf(stderr,"runs and executes script_to_run, which can be\n"); fprintf(stderr,"any program or executable script.\n"); fprintf(stderr,"The script or program gets invoked with the first\n"); fprintf(stderr,"argument as the PV name and the second argument\n"); fprintf(stderr,"as the value of the PV\n"); fprintf(stderr,"The program or shell script script_to_run is\n"); fprintf(stderr,"run as a separate child process of this program\n"); fprintf(stderr,"This means that your script or program will not\n"); fprintf(stderr,"stop this process from running, if fact your\n"); fprintf(stderr,"script or program can be invoked many times if\n"); fprintf(stderr,"the value of the PV is changing rapidly and\n"); fprintf(stderr,"several instances of your program could be running\n"); fprintf(stderr,"simultaneously.\n"); return -1; } strcpy(pv_name,argv[1]); script_name=argv[2]; pv_value[0]='\0'; if(access(script_name,X_OK)<0) { fprintf(stderr,"Script %s not found or not executable\n",script_name); return -1; } signal(SIGINT,sig_func); signal(SIGQUIT,sig_func); signal(SIGTERM,sig_func); signal(SIGHUP,sig_func); signal(SIGCHLD,sig_chld); FD_ZERO(&all_fds); SEVCHK(ca_task_initialize(),"task initialize"); SEVCHK(ca_add_fd_registration(fdCB,&all_fds),"add fd registration"); SEVCHK(ca_add_exception_event(exCB,NULL),"add exception event"); SEVCHK(ca_search_and_connect(pv_name,&id,conCB,NULL), "search and connect"); SEVCHK(ca_replace_access_rights_event(id,accCB), "replace access rights event"); /* SEVCHK(ca_add_event(DBR_TIME_STRING,data.id,evCB,&data,&data.event), "add event"); */ ca_pend_event(REALLY_SMALL); /* fprintf(stderr,"Monitoring <%s>\n",pv_name); */ while(do_not_exit) { rfds=all_fds; tv.tv_sec=1; tv.tv_usec=0; /*200000*/; switch(tot=select(FD_SETSIZE,&rfds,NULL,NULL,&tv)) { /* case -1: perror("select error - bad"); break; */ case 0: ca_pend_event(REALLY_SMALL); break; default: /* fprintf(stderr,"select data ready\n"); */ ca_pend_event(REALLY_SMALL); break; } } fprintf(stderr,"PV monitor program is exiting!\n"); ca_task_exit(); return 0; }
/* * callback from connection handler: change the state of the channel valid * flag depending on the connection being up or down. * ASSUMPTIONS: chan_id is valid. */ static void connect_callback(struct connection_handler_args args) { Connector *conp; Channel *chan = ca_puser( args.chid); int status; DEBUGP printf("connect callback %p\n", chan); switch( args.op) { case CA_OP_CONN_UP: if( chan->initData == 1) { chan->maxelement = ca_element_count(chan->chan_id); chan->chan_type = ca_field_type(chan->chan_id); chan->initData = 0; } /* * note that a dropped and recreated connection can cause a free and alloc. This * is not always redundant, as software may have restarted with different sizes * for the field! */ if( chan->createData == 1 ) { if( chan->dataval) free( chan->dataval); chan->dataval = calloc(dbr_size[chan->chan_type], chan->maxelement+1); } chan->readAccess = ca_read_access( chan->chan_id); chan->writeAccess = ca_write_access( chan->chan_id); status = ca_array_get_callback( dbf_type_to_DBR_CTRL(ca_field_type(chan->chan_id)), 1, chan->chan_id, getChanInfo, (void*)chan); SEVCHK(status, "connect_callback : ca_get_DBR_CTRL_event failed"); status = ca_replace_access_rights_event( chan->chan_id, getAccessRights); SEVCHK(status, "connect_callback : ca_replace_access_rights_event failed"); chan->valid = 1; chan->outstanding = 0; if( chan->monitor) { chan->status = 100; /* MAGIC: an absurd status */ status = ca_add_array_event(dbf_type_to_DBR_STS(chan->chan_type), chan->maxelement, chan->chan_id, monitorCallback, chan, (double) 0.0, (double) 0.0, (double) 0.0, &(chan->eventId)); SEVCHK(status, "connect_callback : ca_add_event failed"); status = ca_flush_io(); SEVCHK(status, "connect_callback : ca_flush_io failed"); } break; case CA_OP_CONN_DOWN: if( chan->valid && chan->eventId) ca_clear_event(chan->eventId); chan->valid = 0; chan->status = 99; /* * update the access rights and severity for all the connectors */ for(conp=chan->first_connector; conp ; conp=conp->next) { if(conp->newAccess) (*conp->newAccess)(conp); if( conp->newState) (*conp->newState)(conp); } break; default: break; } return; }
void SinglePlotThread::run() { #if 0 // event gathering //printchannel(); //for Debug mutex.lock(); mynode.plot = m_plot; chid unit_chid; dbr_string_t units; QString unitch = m_pvname + ".EGU"; ca_create_channel(unitch.toStdString().c_str(), 0, 0, 0, &unit_chid); ca_pend_io(0.1); ca_get(DBR_STRING, unit_chid, (void *)&units); ca_pend_io(0.1); m_plot->SetUnit(units); ca_create_channel(m_pvname.toStdString().c_str(), connectionCallback, &mynode, 0, (oldChannelNotify**)&mynode.mychid); ca_replace_access_rights_event(mynode.mychid, accessRightsCallback); ca_create_subscription (DBR_TIME_DOUBLE, 0, mynode.mychid, DBE_VALUE|DBE_ALARM, eventCallback, &mynode, &mynode.myevid); //ca_add_event(DBR_GR_DOUBLE, mynode.mychid, eventCallback, &mynode, &mynode.myevid); mutex.unlock(); ca_pend_event(0.0); #else //periodic gathering mutex.lock(); chid unit_chid, val_chid; dbr_string_t units; QString unitch = m_pvname + ".EGU"; ca_create_channel(unitch.toStdString().c_str(), 0, 0, 0, &unit_chid); ca_pend_io(0.2); ca_get(DBR_STRING, unit_chid, (void *)&units); ca_pend_io(0.2); m_plot->SetUnit(units); struct dbr_time_double data; ca_create_channel(m_pvname.toStdString().c_str(), 0, 0, 0, &val_chid); ca_pend_io(0.2); epicsTime stamp; struct local_tm_nano_sec tm; int totsec = 0; //for periodic single plot local time int year, month, day, hour, min, sec; int factor = 1; switch(mperiodic) { case PointOne: factor *= 0.1; break; case PointFive: factor *= 0.5; break; case FiveSec: factor *= 5; break; case TenSec: factor *= 10; break; case OneSec: default: break; }; while(getStop()==false) { ca_get(DBR_TIME_DOUBLE, val_chid, (void *)&data); ca_pend_io(0.2); //qDebug("%s : %f\n",ca_name(val_chid), data.value); Epoch2Datetime(year, month, day, hour, min, sec); #if 0 stamp = data.stamp; tm = (local_tm_nano_sec) stamp; totsec = tm.ansi_tm.tm_hour*3600+tm.ansi_tm.tm_min*60+tm.ansi_tm.tm_sec; m_plot->GetValue(data.value, totsec,tm.ansi_tm.tm_year,tm.ansi_tm.tm_mon, tm.ansi_tm.tm_mday ); #else totsec = hour*3600+min*60+sec; m_plot->GetValue(data.value, totsec, year, month, day); #endif usleep(1000000*factor); }; //ca_clear_channel(unit_chid); //ca_clear_channel(val_chid); ca_context_destroy(); mutex.unlock(); exit(); qDebug("SinglePlot Exit"); #endif }
static void dbCaTask(void *arg) { taskwdInsert(0, NULL, NULL); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "dbCaTask calling ca_context_create"); dbCaClientContext = ca_current_context (); SEVCHK(ca_add_exception_event(exceptionCallback,NULL), "ca_add_exception_event"); epicsEventSignal(startStopEvent); /* channel access event loop */ while (TRUE){ do { epicsEventMustWait(workListEvent); } while (dbCaCtl == ctlPause); while (TRUE) { /* process all requests in workList*/ caLink *pca; short link_action; int status; epicsMutexMustLock(workListLock); if (!(pca = (caLink *)ellGet(&workList))){ /* Take off list head */ epicsMutexUnlock(workListLock); if (dbCaCtl == ctlExit) goto shutdown; break; /* workList is empty */ } link_action = pca->link_action; pca->link_action = 0; if (link_action & CA_CLEAR_CHANNEL) --removesOutstanding; epicsMutexUnlock(workListLock); /* Give back immediately */ if (link_action & CA_CLEAR_CHANNEL) { /* This must be first */ dbCaLinkFree(pca); /* No alarm is raised. Since link is changing so what? */ continue; /* No other link_action makes sense */ } if (link_action & CA_CONNECT) { status = ca_create_channel( pca->pvname,connectionCallback,(void *)pca, CA_PRIORITY_DB_LINKS, &(pca->chid)); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_create_channel %s\n", ca_message(status)); printLinks(pca); continue; } dbca_chan_count++; status = ca_replace_access_rights_event(pca->chid, accessRightsCallback); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask replace_access_rights_event %s\n", ca_message(status)); printLinks(pca); } continue; /*Other options must wait until connect*/ } if (ca_state(pca->chid) != cs_conn) continue; if (link_action & CA_WRITE_NATIVE) { assert(pca->pputNative); if (pca->putType == CA_PUT) { status = ca_array_put( pca->dbrType, pca->nelements, pca->chid, pca->pputNative); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( pca->dbrType, pca->nelements, pca->chid, pca->pputNative, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutNative = FALSE; epicsMutexUnlock(pca->lock); } if (link_action & CA_WRITE_STRING) { assert(pca->pputString); if (pca->putType == CA_PUT) { status = ca_array_put( DBR_STRING, 1, pca->chid, pca->pputString); } else if (pca->putType==CA_PUT_CALLBACK) { status = ca_array_put_callback( DBR_STRING, 1, pca->chid, pca->pputString, putCallback, pca); } else { status = ECA_PUTFAIL; } if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_array_put %s\n", ca_message(status)); printLinks(pca); } epicsMutexMustLock(pca->lock); if (status == ECA_NORMAL) pca->newOutString = FALSE; epicsMutexUnlock(pca->lock); } /*CA_GET_ATTRIBUTES before CA_MONITOR so that attributes available * before the first monitor callback */ if (link_action & CA_GET_ATTRIBUTES) { status = ca_get_callback(DBR_CTRL_DOUBLE, pca->chid, getAttribEventCallback, pca); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_get_callback %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_NATIVE) { size_t element_size; element_size = dbr_value_size[ca_field_type(pca->chid)]; epicsMutexMustLock(pca->lock); pca->pgetNative = dbCalloc(pca->nelements, element_size); epicsMutexUnlock(pca->lock); status = ca_add_array_event( ca_field_type(pca->chid)+DBR_TIME_STRING, ca_element_count(pca->chid), pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } if (link_action & CA_MONITOR_STRING) { epicsMutexMustLock(pca->lock); pca->pgetString = dbCalloc(1, MAX_STRING_SIZE); epicsMutexUnlock(pca->lock); status = ca_add_array_event(DBR_TIME_STRING, 1, pca->chid, eventCallback, pca, 0.0, 0.0, 0.0, 0); if (status != ECA_NORMAL) { errlogPrintf("dbCaTask ca_add_array_event %s\n", ca_message(status)); printLinks(pca); } } } SEVCHK(ca_flush_io(), "dbCaTask"); } shutdown: taskwdRemove(0); if (dbca_chan_count == 0) ca_context_destroy(); else fprintf(stderr, "dbCa: chan_count = %d at shutdown\n", dbca_chan_count); epicsEventSignal(startStopEvent); }
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); } } }