// extern "C" int epicsShareAPI ca_build_and_connect ( const char *name_str, chtype get_type, arrayElementCount get_count, chid * chan, void *pvalue, caCh *conn_func, void *puser ) { if ( get_type != TYPENOTCONN && pvalue != 0 && get_count != 0 ) { return ECA_ANACHRONISM; } return ca_search_and_connect ( name_str, chan, conn_func, puser ); }
/* * create a channel entry, and lookup all details */ Channel * build_PV(char * name) { Channel *chan; int st; chan = (Channel *) calloc( 1, sizeof *chan); if( !chan) return 0; chan->chan_name = strdup(name); chan->initData = 1; chan->createData = 1; chan->monitor = 1; chan->outstanding = 1; st = ca_search_and_connect(name, &(chan->chan_id), connect_callback, chan); DEBUGP printf("ca_search_and_connect = %d\n", st); ca_flush_io(); return chan; }
Channel * init_PV(char *name, chtype chan_type, void *dataptr, int size) { Channel *chan; int st; DEBUGP printf("init_PV(%s, ...)\n", name); chan = (Channel *) calloc( 1, sizeof (Channel)); if( !chan) return 0; DEBUGP printf("Channel Allocated %p\n", chan); chan->chan_name = strdup(name); chan->chan_type = chan_type; chan->dataval = dataptr; chan->maxelement = size; chan->outstanding = 1; st = ca_search_and_connect(name, &(chan->chan_id), connect_callback, chan); DEBUGP printf("ca_search_and_connect = %d\n", st); ca_flush_io(); return chan; }
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; }
/* Find an unconnected PV and attempt to connect to it. That should * restart the searches for all other unresolved PVs. */ void retryConnections(void) { int i,j; const char *pvname=NULL; chid retryChid; int status; #if DEBUG_RETRY print("retryConnections:\n"); print(" freeListSize=%d freeListCount=%d\n", caTask.freeListSize,caTask.freeListCount); print(" pageSize=%d pageCount=%d\n", caTask.pageSize,caTask.pageCount); print(" nextpage=%d nextFree=%d\n", caTask.nextPage,caTask.nextFree); print(" channelCount=%d channelConnected=%d\n", caTask.channelCount,caTask.channelConnected); if(caTask.nextPage != caTask.pageCount-1) { print(" caTask.nextPage != caTask.pageCount-1\n"); } #else /* Check if all channels are connected */ if(caTask.channelCount == caTask.channelConnected) { medmPostMsg(1,"retryConnections: All channels are connected\n"); XBell(display, 50); return; } #endif /* Find an unconnected PV */ for(i=0; i < caTask.pageCount; i++) { int jmax=(i == caTask.nextPage)?caTask.nextFree:CA_PAGE_SIZE; for(j=0; j < jmax; j++) { Channel *pCh=&caTask.pages[i][j]; if(pCh->chid && ca_state(pCh->chid) != cs_conn) { pvname=ca_name(pCh->chid); break; } } if(pvname) break; } #if DEBUG_RETRY print(" Found %s\n",pvname?pvname:"Not found"); if(!pvname) return; #else if(!pvname) { medmPostMsg(1,"retryConnections: Failed to find unconnected PV\n"); return; } #endif /* Search */ status=ca_search_and_connect(pvname,&retryChid,NULL,NULL); if(status != ECA_NORMAL) { medmPostMsg(1,"retryConnections: ca_search failed for %s: %s\n", pvname, ca_message(status)); } /* Wait. The searches will only continue for this time. Keep the * time short as the interface is frozen, and most of the searches * occur at the start of the sequence. Testing indicated: * * RETRY_TIMEOUT Searches * 30 15 * 5 10 * 3 9 * 2 9 * 1 8 * * but this may vary owing to tuning and may change with new releases. */ ca_pend_io(RETRY_TIMEOUT); /* Clear the channel */ status = ca_clear_channel(retryChid); if(status != ECA_NORMAL) { medmPostMsg(1,"retryConnections: ca_clear_channel failed for %s: %s\n", pvname, ca_message(status)); } }
static int caAdd(char *name, Record *pr) { Channel *pCh; int status; if((caTask.freeListCount < 1) && (caTask.nextFree >= CA_PAGE_SIZE)) { /* if not enough pages, increase number of pages */ if(caTask.pageCount >= caTask.pageSize) { caTask.pageSize += CA_PAGE_COUNT; #if defined(__cplusplus) && !defined(__GNUG__) caTask.pages = (Channel **)realloc((malloc_t)caTask.pages, sizeof(Channel *)*caTask.pageSize); #else caTask.pages = (Channel **)realloc(caTask.pages, sizeof(Channel *)*caTask.pageSize); #endif if(caTask.pages == NULL) { medmPostMsg(1,"caAdd: Memory allocation error\n"); return -1; } } /* add one more page */ caTask.pages[caTask.pageCount] = (Channel *)malloc(sizeof(Channel) * CA_PAGE_SIZE); if(caTask.pages[caTask.pageCount] == NULL) { medmPostMsg(1,"caAdd: Memory allocation error\n"); return -1; } caTask.pageCount++; caTask.nextPage++; caTask.nextFree=0; } if(caTask.nextFree < CA_PAGE_SIZE) { pCh = &((caTask.pages[caTask.nextPage])[caTask.nextFree]); pCh->caId = caTask.nextPage * CA_PAGE_SIZE + caTask.nextFree; caTask.nextFree++; } else { int index; caTask.freeListCount--; index = caTask.freeList[caTask.freeListCount]; pCh = &((caTask.pages[index/CA_PAGE_SIZE])[index % CA_PAGE_SIZE]); pCh->caId = index; } pCh->data = NULL; pCh->chid = NULL; pCh->evid = NULL; pCh->size = 0; pCh->pr = pr; pCh->previouslyConnected = False; /* Do the search */ status = ca_search_and_connect(name, &(pCh->chid), medmConnectEventCb, pCh); if(status != ECA_NORMAL) { medmPostMsg(1,"caAdd: ca_search_and_connect failed: %s\n", ca_message(status)); } else { /* Cast to avoid warning from READONLY */ pCh->pr->name = (char *)ca_name(pCh->chid); } caTask.channelCount++; #if DEBUG_ADD print("caAdd: %3d name=%s\n", caTask.channelCount, name); #endif return pCh->caId; }