/* * cagft() * * ca get field test * * test ca get over the range of CA data types */ static int cagft(char *pname) { const unsigned maxTries = 1000ul; unsigned ntries = 0u; chid chan_id; int status; int i; /* * convert name to chan id */ status = ca_search(pname, &chan_id); SEVCHK(status,NULL); status = ca_pend_io(5.0); if(status != ECA_NORMAL){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("Not Found %s\n", pname); return -1; } printf("name:\t%s\n", ca_name(chan_id)); printf("native type:\t%s\n", dbr_type_to_text(ca_field_type(chan_id))); printf("native count:\t%lu\n", ca_element_count(chan_id)); /* * fetch as each type */ for(i=0; i<=LAST_BUFFER_TYPE; i++){ if(ca_field_type(chan_id)==DBR_STRING) { if( (i!=DBR_STRING) && (i!=DBR_STS_STRING) && (i!=DBR_TIME_STRING) && (i!=DBR_GR_STRING) && (i!=DBR_CTRL_STRING)) { continue; } } /* ignore write only types */ if ( i == DBR_PUT_ACKT || i == DBR_PUT_ACKS ) { continue; } status = ca_array_get_callback( i, ca_element_count(chan_id), chan_id, printit, NULL); SEVCHK(status, NULL); outstanding++; } /* * wait for the operation to complete * before returning */ while ( ntries < maxTries ) { unsigned long oldOut; oldOut = outstanding; ca_pend_event ( 0.05 ); if ( ! outstanding ) { SEVCHK ( ca_clear_channel ( chan_id ), NULL ); printf ( "\n\n" ); return 0; } if ( outstanding == oldOut ) { ntries++; } } SEVCHK ( ca_clear_channel ( chan_id ), NULL ); return -1; }
static void getCB(EVENT_ARGS args) { /* void* node=(void*)ca_puser(args.chid); */ struct dbr_gr_enum* edb; char* cdb; if(args.status==ECA_NORMAL) { if(pv_type==DBF_ENUM) { edb=(struct dbr_gr_enum*)args.dbr; cdb=&edb->strs[edb->value][0]; /* strncpy(pv_value,cdb,MAX_ENUM_STRING_SIZE); */ SEVCHK(ca_add_event(DBR_GR_ENUM,id,evCB,NULL,&event), "add event"); } else { cdb=(char*)args.dbr; /* strncpy(pv_value,cdb,MAX_STRING_SIZE); */ SEVCHK(ca_add_event(DBR_STRING,id,evCB,NULL,&event), "add event"); } } else fprintf(stderr,"PV <%s> get failed\n",pv_name); }
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"); }
void putCallback(struct event_handler_args args) { gotCallback = TRUE; printf("putCallback "); if(args.chid) printf(" pv=%s",ca_name(args.chid)); SEVCHK(args.status,"putCallback"); }
static void conCB(CONNECT_ARGS args) { /* void* node=(void*)ca_puser(args.chid); */ long rc; /* fprintf(stderr,"exCB: -------------------------------\n"); fprintf(stderr,"conCB: name=%s\n",ca_name(args.chid)); fprintf(stderr,"conCB: type=%d\n",ca_field_type(args.chid)); fprintf(stderr,"conCB: number elements=%d\n",ca_element_count(args.chid)); fprintf(stderr,"conCB: host name=%s\n",ca_host_name(args.chid)); fprintf(stderr,"conCB: read access=%d\n",ca_read_access(args.chid)); fprintf(stderr,"conCB: write access=%d\n",ca_write_access(args.chid)); fprintf(stderr,"conCB: state=%d\n",ca_state(args.chid)); */ if(ca_state(args.chid)==cs_conn) { if (never_connected) { never_connected=0; /* issue a get */ if(ca_field_type(args.chid)==DBF_ENUM) { pv_type=DBF_ENUM; rc=ca_array_get_callback(DBR_GR_ENUM,1,id,getCB,NULL); } else { pv_type=DBF_STRING; rc=ca_array_get_callback(DBR_STRING,1,id,getCB,NULL); } SEVCHK(rc,"get with callback bad"); } } else fprintf(stderr,"PV <%s> not connected\n",pv_name); }
int main(int argc,char **argv) { chid mychid; unsigned short value; if(argc!=3) { printf("usage: caputackt pvname value\n"); exit(1); } sscanf(argv[2],"%hu",&value); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(argv[1],&mychid), "ca_search"); ca_pend_io(5.0); SEVCHK(ca_put(DBR_PUT_ACKT,mychid,&value),"ca_put"); ca_pend_event(1.0); /* ca_task_exit(); */ return(0); }
int main(int argc,char **argv) { int status; double value=1.0; double newvalue=0.0; char *pvname; double blockTime; if(argc!=3) { printf("usage: testsyncgroup <pvname> <blockTime>\n"); exit(1); } pvname = argv[1]; sscanf(argv[2],"%le",&blockTime); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); SEVCHK(ca_pend_io(1.0),"ca_pend_io"); SEVCHK(ca_sg_create(&gid),"ca_sg_create"); SEVCHK(ca_sg_array_put(gid,DBR_DOUBLE,1,mychid,(void *)&value), "ca_sg_array_put"); SEVCHK(ca_sg_array_get(gid,DBR_DOUBLE,1,mychid,(void *)&newvalue), "ca_sg_array_put"); status = ca_sg_block(gid,blockTime); printf("ca_sg_block status=%s\n",ca_message(status)); status = ca_sg_test(gid); printf("ca_sg_test status=%s\n",ca_message(status)); printf("newvalue=%f\n",newvalue); return(0); }
int channel_put_ackt(Channel *chan, int acknowledge) { short s_acknowledge = acknowledge; int status; if(! chan->valid) return -1; status = ca_array_put( DBR_PUT_ACKT, 1, chan->chan_id, &s_acknowledge); SEVCHK(status, "channel_put : ca_array_put ACKT failed"); ca_flush_io(); return 0; }
int channel_put_acks(Channel *chan, int severity) { short s_severity = severity; int status; if(! chan->valid) return -1; status = ca_array_put( DBR_PUT_ACKS, 1, chan->chan_id, &s_severity); SEVCHK(status, "channel_put : ca_array_put ACKS failed"); ca_flush_io(); return 0; }
int main(int argc,char **argv) { int status; double value=1.0; char *pvname; double pendEventTime; int maxTrys = 3; if(argc!=3) { printf("usage: testputnotify <pvname> <pendEventTime>\n"); exit(1); } pvname = argv[1]; sscanf(argv[2],"%le",&pendEventTime); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); SEVCHK(ca_pend_io(1.0),"ca_pend_io"); while(TRUE) { SEVCHK(ca_array_put_callback(DBR_DOUBLE,1,mychid, (void *)&value,putCallback,NULL), "ca_put_callback"); ntrys=0; gotCallback=FALSE; while(!gotCallback && ntrys <=maxTrys) { status = ca_pend_event(pendEventTime); if(status!=ECA_NORMAL && status!=ECA_TIMEOUT) printf("ca_pend_event status=%s\n",ca_message(status)); ntrys++; if(ntrys==maxTrys) { printf(" Never got callback\n"); break; } } printf(" number ca_pend_event = %d\n",ntrys); } return(0); }
int channel_put(Channel *chan, int count) { int status; DEBUGP printf("channel_put %s %d %s\n", chan->chan_name, count, chan->valid?"valid":"invalid"); if(! chan->valid) return -1; if( count > chan->maxelement) count = chan->maxelement; status = ca_array_put(chan->chan_type, count, chan->chan_id, chan->dataval); SEVCHK(status, "channel_put : ca_array_put failed"); ca_flush_io(); return 0; }
int channel_put_callback( Channel *chan, int count, CHANNEL_USERFUNC func, void *arg) { int status; DEBUGP printf("channel_put_callback %s %d %s\n", chan->chan_name, count, chan->valid?"valid":"invalid"); if( !chan->valid) return -1; if( count > chan->maxelement) count = chan->maxelement; chan->outstanding = 1; status = ca_array_put_callback( chan->chan_type, count, chan->chan_id, chan->dataval, func, arg); SEVCHK(status, "channel_put_callback : ca_array_put_callback failed"); ca_flush_io(); return 0; }
/* * VERIFY_VALUE * * initiate print out the values in a database access interface structure */ static void verify_value(chid chan_id, chtype type) { int status; /* * issue a get which calls back `printit' * upon completion */ status = ca_array_get_callback( type, ca_element_count(chan_id), chan_id, printit, NULL); SEVCHK(status, NULL); outstanding++; }
void ChannelAccessThr::ClearEventsOnPage(const int page) { if(getClearEvents()==true) return; //qDebug("ClearEvents-Page[%d]",page); for(size_t i = 0; i < vecnode.size(); i++) { CHNODE *pNode = &vecnode.at(i); if(pNode == NULL) continue; int state = ca_state(pNode->ch_id); ca_pend_event(0.001); if(state == 0) { qDebug("Not Conntected - pv(%s)", pNode->pvname.toStdString().c_str()); continue; }; SEVCHK(ca_clear_event(pNode->ev_id), NULL); }; setClearEvents(true); }
int main(int argc,char **argv) { int indval,field; SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search("enumCputDTYP",&putCchid[0]),"ca_search failure"); SEVCHK(ca_search("enumCputPRIO",&putCchid[1]),"ca_search failure"); SEVCHK(ca_search("enumCputVAL" ,&putCchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMDbputDTYP",&putMDbchid[0]),"ca_search failure"); SEVCHK(ca_search("enumMDbputPRIO",&putMDbchid[1]),"ca_search failure"); SEVCHK(ca_search("enumMDbputVAL" ,&putMDbchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMCaputDTYP",&putMCachid[0]),"ca_search failure"); SEVCHK(ca_search("enumMCaputPRIO",&putMCachid[1]),"ca_search failure"); SEVCHK(ca_search("enumMCaputVAL" ,&putMCachid[2]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.DTYP" ,&getCchid[0]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.PRIO" ,&getCchid[1]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.VAL" ,&getCchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.DTYP" ,&getMDbchid[0]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.PRIO" ,&getMDbchid[1]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.VAL" ,&getMDbchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.DTYP" ,&getMCachid[0]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.PRIO" ,&getMCachid[1]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.VAL" ,&getMCachid[2]),"ca_search failure"); SEVCHK(ca_pend_io(5.0),"ca_pend_io failure"); for(indval=0; indval<2; indval++) { SEVCHK(ca_put(DBR_STRING,putCchid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putCchid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putCchid[2],valValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[2],valValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[2],valValue[indval]),"ca_put"); /*Wait until evertthing updated*/ ca_pend_event(2.0); for(field=0; field<3; field++) { SEVCHK(ca_get(DBR_STRING,getCchid[field],&getCvalue[field]), "ca_get"); SEVCHK(ca_get(DBR_STRING,getMDbchid[field],&getMDbvalue[field]), "ca_get"); SEVCHK(ca_get(DBR_STRING,getMCachid[field],&getMCavalue[field]), "ca_get"); } SEVCHK(ca_pend_io(5.0),"ca_pend_io failure"); printReport(indval); } return(0); }
int main(int argc,char **argv) { char *pval; double sleepSecs = 0.0; int clearEvery = 0; int indValue = 1; int indNumberCallback = 1; while((argc>1) && (argv[1][0] == '-')) { int i; char option; int narg; option = toupper((argv[1])[1]); pval = argv[2]; argc -= 1; narg = 1; if(option=='S') { sscanf(pval,"%lf",&sleepSecs); argc -= 1; ++narg; } else if(option=='C') { sscanf(pval,"%d",&clearEvery); argc -= 1; ++narg; } else if(option=='V') { verbose = 1; } else { usageExit(); } for(i=1; i<argc; i++) argv[i] = argv[i + narg]; } if(argc != 4) usageExit(); pvname = argv[1]; pvalue1 = argv[2]; pvalue2 = argv[3]; pevent = epicsEventCreate(epicsEventEmpty); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "ca_task_initialize"); while(1) { SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); if(ca_pend_io(3.0)!=ECA_NORMAL) { epicsThreadSleep(5.0); continue; } while(1) { epicsEventWaitStatus status; if(indValue==0) { indValue = 1; pvalue = pvalue2; } else { indValue = 0; pvalue=pvalue1; } if(++indNumberCallback >= MAXnumberCallback) indNumberCallback=0; numberCallback[indNumberCallback] = ++expectedCallback; status = ca_array_put_callback(DBR_STRING,1,mychid, pvalue,putCallback,&numberCallback[indNumberCallback]); if(status!=ECA_NORMAL) { printf("ca_array_put_callback %s\n",ca_message(status)); epicsThreadSleep(2.0); continue; } if((clearEvery>0) && ((expectedCallback % clearEvery)==0)) { ca_flush_io(); epicsThreadSleep(sleepSecs); SEVCHK(ca_clear_channel(mychid),"ca_clear_channel"); ca_flush_io(); expectedCallback = 0; epicsThreadSleep(sleepSecs); if(verbose) { printTime(); printf("Issued ca_clear_channel expectedCallback %d\n", expectedCallback); } break; } ca_flush_io(); if(verbose) { printTime(); printf("Issued ca_put_callback expectedCallback %d\n", expectedCallback); } while(1) { status = epicsEventWaitWithTimeout(pevent,10.0); if(status==epicsEventWaitTimeout) { if(verbose) { printTime(); printf("timeout after 10 seconds\n"); } continue; } break; } if(status!=epicsEventWaitOK) { int i; printTime(); printf("eventWait status %d\n",status); for(i=0; i<MAXnumberCallback; i++) numberCallback[i]=0; } epicsThreadSleep(sleepSecs); } } 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; }
/* * capft * * test ca_put() over a range of data types * */ static int capft( char *pname, char *pvalue ) { dbr_short_t shortvalue; dbr_long_t longvalue; dbr_float_t floatvalue; dbr_char_t charvalue; dbr_double_t doublevalue; unsigned long ntries = 10ul; int status; chid chan_id; if (((*pname < ' ') || (*pname > 'z')) || ((*pvalue < ' ') || (*pvalue > 'z'))){ printf("\nusage \"pv name\",\"value\"\n"); return -1; } /* * convert name to chan id */ status = ca_search(pname, &chan_id); SEVCHK(status,NULL); status = ca_pend_io(5.0); if(status != ECA_NORMAL){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("Not Found %s\n", pname); return -1; } printf("name:\t%s\n", ca_name(chan_id)); printf("native type:\t%d\n", ca_field_type(chan_id)); printf("native count:\t%lu\n", ca_element_count(chan_id)); /* * string value ca_put */ status = ca_put( DBR_STRING, chan_id, pvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_STRING); if(ca_field_type(chan_id)==0)goto skip_rest; if(sscanf(pvalue,"%hd",&shortvalue)==1) { /* * short integer ca_put */ status = ca_put( DBR_SHORT, chan_id, &shortvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_SHORT); status = ca_put( DBR_ENUM, chan_id, &shortvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_ENUM); charvalue=(dbr_char_t)shortvalue; status = ca_put( DBR_CHAR, chan_id, &charvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_CHAR); } if(sscanf(pvalue,"%d",&longvalue)==1) { /* * long integer ca_put */ status = ca_put( DBR_LONG, chan_id, &longvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_LONG); } if(epicsScanFloat(pvalue, &floatvalue)==1) { /* * single precision float ca_put */ status = ca_put( DBR_FLOAT, chan_id, &floatvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_FLOAT); } if(epicsScanDouble(pvalue, &doublevalue)==1) { /* * double precision float ca_put */ status = ca_put( DBR_DOUBLE, chan_id, &doublevalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_DOUBLE); } skip_rest: /* * wait for the operation to complete * (outstabnding decrements to zero) */ while(ntries){ ca_pend_event(1.0); if(!outstanding){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("\n\n"); return 0; } ntries--; } SEVCHK(ca_clear_channel(chan_id),NULL); return -1; }
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; }
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); }