1171 lines
33 KiB
C
1171 lines
33 KiB
C
/*
|
|
***************************************************
|
|
* File: /home/lando/slentz/sync/unix_gsd_sync.c
|
|
* Modifications:
|
|
* 09/18/90 ges creation
|
|
* 09/21/90 ges desk check
|
|
* 10/15/90 ges add gsd_copy_buffer routine
|
|
* 10/17/90 ges clean-up and add to documentation
|
|
* add timeout parameter to gsd_sync_read
|
|
* 11/01/90 ges add gsd_sync_clear function
|
|
* 11/05/90 ges add linked list event data approach
|
|
* 11/16/90 ges make special UNIX version for OPI
|
|
* 11/20/90 ges make gsd_sync_init return VOID * for consistency
|
|
* between UNIX and VxWorks versions
|
|
* 11/26/90 ges use ca_build_and_connect in gsd_sync_init
|
|
* 11/27/90 ges add NULL ptr return 0 to gsd_tss_eq
|
|
* add NULL ptr return 0 to gsd_tss_gtr
|
|
* change from (gsd_tss_gtr) to (gsd_tss_gtr ||
|
|
* gsd_tss_eq) in gsd_findlargest_ts
|
|
* 12/14/90 ges add events at gsd_sync_read instead of gsd_sync_init
|
|
* return most recent chan data if chan failed to
|
|
* produce data with the associated time stamp
|
|
* 09/03/91 joh fixed includes for V5 vxWorks
|
|
* 06/26/92 joh now uses ca_printf instead of printf
|
|
*
|
|
*
|
|
* Compile:
|
|
* for Unix:
|
|
* compile:
|
|
* make
|
|
* execute:
|
|
* unix_gsd_sync
|
|
*-------------------------------------------------
|
|
* Usage:
|
|
* 1) A single initial call to gsd_sync_init must be made before
|
|
* any additional calls to gsd_sync_read".
|
|
* 2) Calls to UNIX version of "gsd_sync_read":
|
|
* 1) returns 1 if done, either timed out or has valid
|
|
* synchronous data on all channels of interest
|
|
* returns 0 if not done, allowing the calling program
|
|
* to continue polling for done by repeated
|
|
* calls to gsd_sync_read
|
|
* 2) with NEXTSET_SYNC_DATA: Pushes any currently saved valid
|
|
* event data down to the "previous" level store.
|
|
* At invocation, time stamp data monitors are established
|
|
* for each channel named.
|
|
* All event data is then received and stored in sequence
|
|
* until either:
|
|
* 1) event data containg identical time stamps has been
|
|
* received from all channels named (this time stamp
|
|
* is selected to be associated with this sync
|
|
* data call) or
|
|
* 2) time out occurs (in this case the most recent
|
|
* time stamp of all the collected event data
|
|
* is selected as the time stamp associated with
|
|
* this sync data call)
|
|
* Data that has the associated time stamp
|
|
* will be marked as valid and will be copied to the
|
|
* synchronous data buffers. If a channel has no data with
|
|
* the associated time stamp, then its most recent received
|
|
* data will be copied to the synchronous data buffers and
|
|
* will be marked not valid.
|
|
* 3) with PREVIOUS_SYNC_DATA: yields the collected and
|
|
* saved data that currently reside in the "previous"
|
|
* level store.
|
|
* 3) Interpretation of flags:
|
|
* 1) gsd_sync_data.svalid: is 1 if new sync event data has come in
|
|
* over that channel during its synchronous read window.
|
|
* The pointer gsd_sync_data.pSdata points to the
|
|
* DBR_TIME_XXXX structure containing this new data.
|
|
* : is 0 if no new synchronous
|
|
* event data has come in
|
|
* over that channel during its synchronous read window.
|
|
* The pointer gsd_sync_data.pSdata points the the
|
|
* DBR_TIME_XXXX structure and will contain the remaining
|
|
* old residual data unchanged from the most recent
|
|
* successful synchronous event.
|
|
* 2) gsd_sync_data.pSdata: is 0 (i.e. NULL) if that channel
|
|
* has never established network connection. If NULL then
|
|
* no DBR_TIME_XXXX data is yet available.
|
|
***************************************************
|
|
*/
|
|
|
|
static char *sccsId = "@(#)gsd_sync_subr.c 1.8\t11/5/92";
|
|
|
|
#if defined(UNIX)
|
|
# include <sys/types.h>
|
|
# include <stdio.h>
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
#else
|
|
# if defined(vxWorks)
|
|
# define abort(A) taskSuspend(taskIdSelf())
|
|
# ifdef V5vxWorks
|
|
# include <Vxtypes.h>
|
|
# else
|
|
# include <types.h>
|
|
# endif
|
|
# if 0 /* needed ?? */
|
|
# include <stdioLib.h>
|
|
# include <sys/time.h>
|
|
# include <time.h>
|
|
# endif
|
|
# else
|
|
@@@@ dont compile in this case @@@@
|
|
# endif
|
|
#endif
|
|
|
|
#include <cadef.h>
|
|
#include <gsd_sync_defs.h>
|
|
|
|
|
|
|
|
/*
|
|
*--------------------------------------------
|
|
* Function prototypes
|
|
*--------------------------------------------
|
|
*/
|
|
VOID gsd_fd_register();
|
|
VOID gsd_ca_service();
|
|
|
|
VOID gsd_ca_task_initialize();
|
|
VOID gsd_ca_pend_event();
|
|
VOID *gsd_sync_init();
|
|
VOID gsd_connevent_handler();
|
|
VOID gsd_event_handler();
|
|
int gsd_sync_read();
|
|
TS_STAMP *gsd_complete_set();
|
|
VOID gsd_copy_buffer();
|
|
int gsd_timeout();
|
|
VOID gsd_sync_clear();
|
|
int gsd_tss_within_delta();
|
|
int gsd_tss_eq();
|
|
int gsd_tss_gtr();
|
|
TS_STAMP *gsd_findlargest_ts();
|
|
VOID gsd_freeevent_mem();
|
|
VOID gsd_syncset_findcopy();
|
|
TS_STAMP *gsd_get_ts();
|
|
|
|
|
|
/*-------------------------------------------*/
|
|
|
|
struct gsd_sync_linked {
|
|
struct gsd_sync_linked *pNstruct; /* ptr to next gsd_sync_linked struct */
|
|
VOID *pNdata; /* ptr to event TBR_TIME_xxxx data */
|
|
};
|
|
|
|
struct gsd_sync_ctrl {
|
|
struct gsd_sync_data *pDstruct; /* ptr to assoc gsd_sync_data struc */
|
|
int nvalid; /* next data's valid flag */
|
|
int avalid; /* already data's valid flag */
|
|
VOID *pNdata; /* ptr to next data set */
|
|
VOID *pAdata; /* ptr to immediately previous (already) data set */
|
|
struct gsd_sync_linked *pNstruct; /* ptr to head linked data sets */
|
|
int en_event; /* enable the storage of event data */
|
|
evid event_id; /* event id storage for this channel */
|
|
};
|
|
|
|
struct gsd_sync_compctrl {
|
|
struct timeval start_time; /* sys time store at initial call */
|
|
struct gsd_sync_ctrl *pCtrl; /* ptr to gsd_sync_ctrl array */
|
|
};
|
|
|
|
/*---------------------------------------------*/
|
|
#define ONESEC_IN_TICKS (sysClkRateGet())
|
|
#define PEND_EVENT_DELAY 0.0001 /* standard 0.0001sec event delay */
|
|
#define USEC_TIME_OUT 100 /* 100 usec timeval's timeout */
|
|
|
|
|
|
|
|
|
|
/* test only !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|
|
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|
|
/*
|
|
*------------------------------------------------------
|
|
* For stand-alone operation remove the comments that bracket this
|
|
* mainline driver and call:
|
|
* main()
|
|
*------------------------------------------------------
|
|
*/
|
|
#define CHAN_COUNT 4 /* 4 channels for this example test code */
|
|
#define SYNC_TIMEOUT 1.0 /* timeout for data reception in float secs */
|
|
|
|
struct gsd_sync_data sync_data_array[CHAN_COUNT];
|
|
struct gsd_sync_data *pSync_data_array = &sync_data_array[0];
|
|
/*
|
|
main()
|
|
{
|
|
VOID *pfdctx = NULL;
|
|
struct gsd_sync_compctrl *pSync_compctrl;
|
|
struct gsd_sync_ctrl *pSync_ctrl;
|
|
int i;
|
|
|
|
sync_data_array[0].pName = "IOC21:CALC:S00:00";
|
|
sync_data_array[1].pName = "IOC21:CALC:S00:01";
|
|
sync_data_array[2].pName = "BSD_41N:00:00";
|
|
sync_data_array[3].pName = "BSD_21:00:00";
|
|
|
|
SEVCHK(ca_task_initialize(),
|
|
"main: C.A. initialize failure.\n");
|
|
pSync_compctrl = (struct gsd_sync_compctrl *)
|
|
gsd_sync_init(pSync_data_array, CHAN_COUNT, &pfdctx, NULL);
|
|
if(NULL == pSync_compctrl) {
|
|
ca_printf("unable to continue, gsd_sync_init failed\n");
|
|
return 1;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
|
|
|
|
gsd_sync_read(PREVIOUS_SYNC_DATA, pSync_compctrl, CHAN_COUNT, &pfdctx,
|
|
SYNC_TIMEOUT);
|
|
ca_printf("result of sync_read(PREVIOUS_SYNC_DATA)\n");
|
|
for (i = 0; i < CHAN_COUNT; ++i) {
|
|
ca_printf("%s valid = %d ptr = %d \n",
|
|
(pSync_ctrl->pDstruct)->pName, (pSync_ctrl->pDstruct)->svalid,
|
|
(pSync_ctrl->pDstruct)->pSdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata) {
|
|
ca_printf("ts sec = %ld ts nsec = %ld value = %f\n",
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.nsec,
|
|
((struct dbr_time_float*)
|
|
((pSync_ctrl->pDstruct)->pSdata))->value);
|
|
}
|
|
++pSync_ctrl;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
ca_printf("\n");
|
|
|
|
|
|
while(!gsd_sync_read(NEXTSET_SYNC_DATA, pSync_compctrl, CHAN_COUNT, &pfdctx,
|
|
SYNC_TIMEOUT)) {
|
|
;
|
|
}
|
|
ca_printf("result of sync_read(NEXTSET_SYNC_DATA)\n");
|
|
for (i = 0; i < CHAN_COUNT; ++i) {
|
|
ca_printf("%s valid = %d ptr = %d \n",
|
|
(pSync_ctrl->pDstruct)->pName, (pSync_ctrl->pDstruct)->svalid,
|
|
(pSync_ctrl->pDstruct)->pSdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata) {
|
|
ca_printf("ts sec = %ld ts nsec = %ld value = %f\n",
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.nsec,
|
|
((struct dbr_time_float*)
|
|
((pSync_ctrl->pDstruct)->pSdata))->value);
|
|
}
|
|
++pSync_ctrl;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
ca_printf("\n");
|
|
|
|
|
|
gsd_sync_read(PREVIOUS_SYNC_DATA, pSync_compctrl, CHAN_COUNT, &pfdctx,
|
|
SYNC_TIMEOUT);
|
|
ca_printf("result of sync_read(PREVIOUS_SYNC_DATA)\n");
|
|
for (i = 0; i < CHAN_COUNT; ++i) {
|
|
ca_printf("%s valid = %d ptr = %d \n",
|
|
(pSync_ctrl->pDstruct)->pName, (pSync_ctrl->pDstruct)->svalid,
|
|
(pSync_ctrl->pDstruct)->pSdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata) {
|
|
ca_printf("ts sec = %ld ts nsec = %ld value = %f\n",
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.nsec,
|
|
((struct dbr_time_float*)
|
|
((pSync_ctrl->pDstruct)->pSdata))->value);
|
|
}
|
|
++pSync_ctrl;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
ca_printf("\n");
|
|
|
|
|
|
while(!gsd_sync_read(NEXTSET_SYNC_DATA, pSync_compctrl, CHAN_COUNT, &pfdctx,
|
|
SYNC_TIMEOUT)) {
|
|
;
|
|
}
|
|
ca_printf("result of sync_read(NEXTSET_SYNC_DATA)\n");
|
|
for (i = 0; i < CHAN_COUNT; ++i) {
|
|
ca_printf("%s valid = %d ptr = %d \n",
|
|
(pSync_ctrl->pDstruct)->pName, (pSync_ctrl->pDstruct)->svalid,
|
|
(pSync_ctrl->pDstruct)->pSdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata) {
|
|
ca_printf("ts sec = %ld ts nsec = %ld value = %f\n",
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.nsec,
|
|
((struct dbr_time_float*)
|
|
((pSync_ctrl->pDstruct)->pSdata))->value);
|
|
}
|
|
++pSync_ctrl;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
ca_printf("\n");
|
|
|
|
|
|
gsd_sync_read(PREVIOUS_SYNC_DATA, pSync_compctrl, CHAN_COUNT, &pfdctx,
|
|
SYNC_TIMEOUT);
|
|
ca_printf("result of sync_read(PREVIOUS_SYNC_DATA)\n");
|
|
for (i = 0; i < CHAN_COUNT; ++i) {
|
|
ca_printf("%s valid = %d ptr = %d \n",
|
|
(pSync_ctrl->pDstruct)->pName, (pSync_ctrl->pDstruct)->svalid,
|
|
(pSync_ctrl->pDstruct)->pSdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata) {
|
|
ca_printf("ts sec = %ld ts nsec = %ld value = %f\n",
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *)
|
|
((pSync_ctrl->pDstruct)->pSdata))->stamp.nsec,
|
|
((struct dbr_time_float*)
|
|
((pSync_ctrl->pDstruct)->pSdata))->value);
|
|
}
|
|
++pSync_ctrl;
|
|
}
|
|
pSync_ctrl = pSync_compctrl->pCtrl;
|
|
ca_printf("\n");
|
|
|
|
|
|
gsd_sync_clear(pSync_compctrl, CHAN_COUNT);
|
|
ca_printf("End of test and demo.\n\n");
|
|
|
|
return 0;
|
|
}
|
|
*/
|
|
/* end test!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|
|
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
|
|
|
|
/*
|
|
*******************************************************
|
|
* Description:
|
|
* 1) Entry with pSync containing the base address of the array of
|
|
* gsd_sync_data structures (chan_count of these)
|
|
* 2) Alloc memory for a composite control structure instance and
|
|
* an array of gsd_sync_ctrl structures,
|
|
* one for each gsd_sync_data structure
|
|
* 3) Establish a connection event handler
|
|
* 4) For each gsd_sync_ctrl structure
|
|
* 1) init pCtrl->Dstruct to point to its associated
|
|
* gsd_sync_data structure
|
|
* 2) init to NULL the pSdata ptr in associated pSync
|
|
* (this is used as a flag to indicate if channel has
|
|
* ever been up in function "gsd_connevent_handler")
|
|
* 3) broadcast chan access search
|
|
* 5) Flush i/o for channel access
|
|
* 6) Returns pCompctrl, the address of the composite control struct
|
|
* which must be used for any subsequent gsd_sync_read(flag,pCtrl,
|
|
* chan_count) calls
|
|
* pCompctrl == NULL: error, unable to allocate memory.
|
|
* pCompctrl != NULL: success, normal execution.
|
|
*******************************************************
|
|
*/
|
|
|
|
|
|
VOID *gsd_sync_init(pSync, chan_count, pfdctx, pMac_pairs)
|
|
struct gsd_sync_data *pSync;
|
|
unsigned int chan_count;
|
|
VOID **pfdctx;
|
|
char *pMac_pairs[];
|
|
{
|
|
int i;
|
|
struct gsd_sync_compctrl *pCompctrl;
|
|
struct gsd_sync_ctrl *pCtrl;
|
|
|
|
if(*pfdctx == NULL) {
|
|
gsd_ca_task_initialize(pfdctx);
|
|
}
|
|
|
|
pCompctrl = (struct gsd_sync_compctrl *)
|
|
calloc(1, sizeof(struct gsd_sync_compctrl));
|
|
if(pCompctrl == NULL) {
|
|
ca_printf("gsd_sync_init: mem alloc failed\n");
|
|
return NULL;
|
|
}
|
|
|
|
pCtrl = (struct gsd_sync_ctrl *) calloc(chan_count, sizeof(struct gsd_sync_ctrl));
|
|
if(pCtrl == NULL) {
|
|
ca_printf("gsd_sync_init: mem alloc failed\n");
|
|
free(pCompctrl);
|
|
return NULL;
|
|
}
|
|
pCompctrl->pCtrl = pCtrl;
|
|
|
|
for(i = 0; i < chan_count; i++) {
|
|
pCtrl->pDstruct = pSync;
|
|
pSync->pSdata = NULL;
|
|
if(strlen(pSync->pName) > 0){
|
|
char name_str[db_name_dim];
|
|
if(pMac_pairs != NULL){
|
|
gsdl_main_macro(name_str, pSync->pName, pMac_pairs, db_name_dim);
|
|
strcpy(pSync->pName, name_str);
|
|
}
|
|
/* ca_printf("new_str = %s\n", pSync->pName);*/
|
|
SEVCHK(ca_build_and_connect(pSync->pName, TYPENOTCONN, 0,
|
|
&(pSync->pChid), (VOID *) NULL,
|
|
gsd_connevent_handler, (VOID *) pCtrl),
|
|
"gs_sync_init: broadcast search failed\n");
|
|
ca_flush_io();
|
|
}
|
|
++pSync;
|
|
++pCtrl;
|
|
}
|
|
|
|
gsd_ca_pend_event(pfdctx);
|
|
return (VOID *) pCompctrl;
|
|
}
|
|
/*
|
|
****************************************************
|
|
* Description:
|
|
* 1) If first time channel connect has been up (i.e. no valid
|
|
* memory address for pSdata) then
|
|
* 1) Allocate memory for the sync data and fill pSdata
|
|
* with its address. If fail, return. (no monitor started)
|
|
* 2) Allocate memory for the next data. If fail,
|
|
* free memory gotten so far, and return.
|
|
* (no monitor started)
|
|
* 3) Allocate memory for the already data. If fail,
|
|
* free memory gotten so far, and return.
|
|
* (no monitor started)
|
|
* 4) Start event monitor on channel
|
|
* 5) Flush i/o for channel access
|
|
*****************************************************
|
|
*/
|
|
VOID gsd_connevent_handler(args)
|
|
struct connection_handler_args args;
|
|
{
|
|
struct gsd_sync_ctrl *pCtrl = ca_puser(args.chid);
|
|
struct gsd_sync_data *pSync = pCtrl->pDstruct;
|
|
|
|
if(args.op == CA_OP_CONN_UP) {
|
|
if(pSync->pSdata == NULL) {
|
|
|
|
pSync->pSdata = (VOID *) calloc(1, dbr_size_n(
|
|
dbf_type_to_DBR_TIME(ca_field_type(args.chid)),
|
|
ca_element_count(args.chid)));
|
|
if(pSync->pSdata == NULL) {
|
|
ca_printf("gsd_connevent_handler: mem alloc fail\n");
|
|
return;
|
|
}
|
|
pCtrl->pNdata = (VOID *) calloc(1, dbr_size_n(
|
|
dbf_type_to_DBR_TIME(ca_field_type(args.chid)),
|
|
ca_element_count(args.chid)));
|
|
if(pCtrl->pNdata == NULL) {
|
|
free(pSync->pSdata);
|
|
pSync->pSdata = NULL;
|
|
ca_printf("gsd_connevent_handler: mem alloc fail\n");
|
|
return;
|
|
}
|
|
pCtrl->pAdata = (VOID *) calloc(1, dbr_size_n(
|
|
dbf_type_to_DBR_TIME(ca_field_type(args.chid)),
|
|
ca_element_count(args.chid)));
|
|
if(pCtrl->pAdata == NULL) {
|
|
free(pSync->pSdata);
|
|
pSync->pSdata = NULL;
|
|
free(pCtrl->pNdata);
|
|
pCtrl->pNdata = NULL;
|
|
ca_printf("gsd_connevent_handler: mem alloc fail\n");
|
|
return;
|
|
}
|
|
|
|
pSync->time_type = dbf_type_to_DBR_TIME(
|
|
ca_field_type(pSync->pChid));
|
|
pSync->count = ca_element_count(pSync->pChid);
|
|
|
|
/*
|
|
ca_printf("%s type = %d count = %d\n",
|
|
pSync->pName, pSync->time_type, pSync->count);
|
|
*/
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
/*
|
|
***********************************************************
|
|
* Description:
|
|
* 1) if (event is enabled) then
|
|
* 1) if (event is the 1st for this channel (pN == NULL)) then
|
|
* 1) alloc mem for a gsd_sync_linked structure and
|
|
* place its addr into the pN ptr
|
|
* else
|
|
* 1) traverse linked list until pN points to last
|
|
* gsd_sync_linked structure
|
|
* 2) allocate memory for a new gsd_sync_linked
|
|
* structure and append it to end of linked list
|
|
* 3) Update pN to point to this new last structure
|
|
* 2) allocate memory to hold the data
|
|
* 3) copy the data into this buffer
|
|
***********************************************************
|
|
*/
|
|
VOID gsd_event_handler(args)
|
|
struct event_handler_args args;
|
|
{
|
|
struct gsd_sync_ctrl *pCtrl = args.usr;
|
|
struct gsd_sync_linked *pN = pCtrl->pNstruct;
|
|
struct gsd_sync_linked *pAlloc_linked;
|
|
VOID *pAlloc_data;
|
|
|
|
if(pCtrl->en_event) {
|
|
pAlloc_linked = (struct gsd_sync_linked *) calloc(1,
|
|
sizeof(struct gsd_sync_linked));
|
|
pAlloc_data = (VOID *) calloc(1, dbr_size_n(args.type,args.count));
|
|
if((NULL == pAlloc_linked) || (NULL == pAlloc_data)) {
|
|
ca_printf("gsd_event_handler: mem alloc failed.\n");
|
|
/* clean-up unused memory */
|
|
if(pAlloc_linked != NULL) free(pAlloc_linked);
|
|
if(pAlloc_data != NULL) free(pAlloc_data);
|
|
return;
|
|
}
|
|
|
|
if(pN == NULL) {
|
|
pCtrl->pNstruct = pAlloc_linked;
|
|
pN = pAlloc_linked;
|
|
}
|
|
else {
|
|
while(pN->pNstruct) pN = pN->pNstruct;
|
|
pN->pNstruct = pAlloc_linked;
|
|
pN = pN->pNstruct;
|
|
}
|
|
|
|
pN->pNdata = pAlloc_data;
|
|
|
|
gsd_copy_buffer(args.dbr, pN->pNdata, dbr_size_n(args.type,
|
|
args.count));
|
|
|
|
/*
|
|
ca_printf("%s ts sec = %ld ts nsec = %ld value = %f\n",
|
|
(pCtrl->pDstruct)->pName,
|
|
((struct dbr_time_float *) (pN->pNdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *) (pN->pNdata))->stamp.nsec,
|
|
((struct dbr_time_float *) (pN->pNdata))->value);
|
|
*/
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*****************************************************
|
|
* Description:
|
|
* 1) if (PREVIOUS_SYNC_DATA) then
|
|
* 1) for each channel
|
|
* 1) if channel has ever been up then
|
|
* 1) copy already data to sync data
|
|
* 2) copy already valid flag to sync valid flag
|
|
* else
|
|
* 1) place NULL in sync data ptr
|
|
* 2) clear sync valid flag to zero
|
|
* 2) if (NEXTSET_SYNC_DATA) then
|
|
* 1) if first call indicated by 0 start time then
|
|
* 1) for each channel
|
|
* 1) if channel has ever been up then
|
|
* 1) copy old next data to already level data
|
|
* copy old next valid flags to already
|
|
* level valid flags
|
|
* 2) clear next valid flags
|
|
* 3) enable capture of monitor data until
|
|
* a full set is acquired or timeout
|
|
* 4) add monitor event
|
|
* 2) fill with system time
|
|
* 3) return 0 indicating not done
|
|
* 2) if complete set received or timed out then
|
|
* 1) clear start time to 0 to prepare for
|
|
* possible next call
|
|
* 2) for each channel
|
|
* 1) disable further capture of data
|
|
* 2) clear monitor event
|
|
* 3) copy chosen time stamp data to next level
|
|
* (if no data received, don't over copy to
|
|
* next level, but clear valid flag on next levl
|
|
* 4) for each channel
|
|
* 1) if channel has ever been up then
|
|
* 1) copy next level data to sync data
|
|
* 2) copy next level valid flag to
|
|
* sync valid flag
|
|
* 3) free memory of linked list and
|
|
* its associated data buffer
|
|
* else
|
|
* 1) place NULL in sync data ptr
|
|
* 2) set sync valid flag to zero
|
|
* 5) return 1 indicating done
|
|
* 3) return 0 indicating not done
|
|
* 3) return 1 indicating done with unknown request
|
|
*****************************************************
|
|
*/
|
|
|
|
|
|
int gsd_sync_read(flag, pCompctrl,chan_count, pfdctx, timeout_secs)
|
|
char flag;
|
|
struct gsd_sync_compctrl *pCompctrl;
|
|
unsigned int chan_count;
|
|
VOID *pfdctx;
|
|
float timeout_secs;
|
|
{
|
|
struct gsd_sync_ctrl *pCtrl = pCompctrl->pCtrl;
|
|
TS_STAMP *pTs;
|
|
struct timezone zone;
|
|
int i;
|
|
|
|
if(NULL == pCompctrl) {
|
|
ca_printf("gsd_sync_read: error NULL arg for pCompctrl\n");
|
|
return 0;
|
|
}
|
|
|
|
if(flag == PREVIOUS_SYNC_DATA) {
|
|
for (i = 0; i < chan_count; i++) {
|
|
if(pCtrl->pAdata != NULL) {
|
|
gsd_copy_buffer(pCtrl->pAdata,
|
|
(pCtrl->pDstruct)->pSdata,
|
|
dbr_size_n((pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count));
|
|
(pCtrl->pDstruct)->svalid = pCtrl->avalid;
|
|
}
|
|
else {
|
|
(pCtrl->pDstruct)->pSdata = NULL;
|
|
(pCtrl->pDstruct)->svalid = 0;
|
|
}
|
|
++pCtrl;
|
|
}
|
|
return 1; /* done with PREVIOUS_SYNC_DATA request */
|
|
}
|
|
|
|
if(flag == NEXTSET_SYNC_DATA) {
|
|
if(((pCompctrl->start_time).tv_sec == 0) &&
|
|
((pCompctrl->start_time).tv_usec == 0)) {
|
|
for (i = 0; i < chan_count; i++) {
|
|
if(pCtrl->pNdata != NULL) {
|
|
gsd_copy_buffer(pCtrl->pNdata,
|
|
pCtrl->pAdata,
|
|
dbr_size_n((pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count));
|
|
pCtrl->avalid = pCtrl->nvalid;
|
|
pCtrl->nvalid = 0;
|
|
pCtrl->en_event = 1;
|
|
|
|
SEVCHK(ca_add_array_event(
|
|
(pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count,
|
|
(pCtrl->pDstruct)->pChid, gsd_event_handler,
|
|
pCtrl, (float) 0, (float) 0, (float) 0,
|
|
&(pCtrl->event_id)),
|
|
"gsd_connevent_handler: add event failed\n");
|
|
}
|
|
++pCtrl;
|
|
}
|
|
ca_flush_io();
|
|
gettimeofday(&(pCompctrl->start_time), &zone);
|
|
return 0; /* not done */
|
|
}
|
|
|
|
if((pTs = gsd_complete_set(pCompctrl->pCtrl, chan_count)) ||
|
|
(gsd_timeout(pCompctrl, timeout_secs, pfdctx))) {
|
|
|
|
(pCompctrl->start_time).tv_sec = 0;
|
|
(pCompctrl->start_time).tv_usec = 0;
|
|
|
|
pCtrl = pCompctrl->pCtrl;
|
|
for (i = 0; i < chan_count; ++i) {
|
|
pCtrl->en_event = 0;
|
|
if(pCtrl->event_id) ca_clear_event(pCtrl->event_id);
|
|
++pCtrl;
|
|
}
|
|
ca_flush_io();
|
|
|
|
pCtrl = pCompctrl->pCtrl;
|
|
|
|
if(pTs != NULL) {
|
|
/*
|
|
ca_printf("got sync data set\n");
|
|
*/
|
|
gsd_syncset_findcopy(pCtrl,
|
|
chan_count, pTs);
|
|
}
|
|
else {
|
|
/*
|
|
ca_printf("settle for last \n");
|
|
*/
|
|
pTs = gsd_findlargest_ts(pCtrl,
|
|
chan_count);
|
|
gsd_syncset_findcopy(pCtrl, chan_count,
|
|
pTs);
|
|
}
|
|
|
|
for(i = 0; i < chan_count; i++) {
|
|
if(pCtrl->pNdata != NULL) {
|
|
gsd_copy_buffer(pCtrl->pNdata,
|
|
(pCtrl->pDstruct)->pSdata,
|
|
dbr_size_n((pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count));
|
|
(pCtrl->pDstruct)->svalid = pCtrl->nvalid;
|
|
gsd_freeevent_mem(pCtrl);
|
|
}
|
|
else {
|
|
(pCtrl->pDstruct)->pSdata = NULL;
|
|
(pCtrl->pDstruct)->svalid = 0;
|
|
}
|
|
++pCtrl;
|
|
}
|
|
return 1; /* done with NEXT_SYNC_DATA request, */
|
|
/* either fullset or timeout */
|
|
}
|
|
|
|
return 0; /* not done with NEXT_SYNC_DATA request */
|
|
}
|
|
return 1; /* done, unknown request */
|
|
}
|
|
/*
|
|
************************************************
|
|
* Description:
|
|
* 1) If a set of identically time stamped data is found in
|
|
* each channel of interest then
|
|
* 1) return a ptr to one of the identical time stamps
|
|
* 2) Otherwise return NULL ptr
|
|
************************************************
|
|
*/
|
|
TS_STAMP *gsd_complete_set(pCtrl, chan_count)
|
|
struct gsd_sync_ctrl *pCtrl;
|
|
unsigned int chan_count;
|
|
{
|
|
struct gsd_sync_linked *pNfirst_chan = pCtrl->pNstruct;
|
|
struct gsd_sync_linked *pNchan = NULL;
|
|
TS_STAMP *pEqual = NULL;
|
|
|
|
int i;
|
|
struct gsd_sync_ctrl *pCtrl_copy;
|
|
|
|
while(pNfirst_chan != NULL) { /* for every data rec receiv in 1st chn*/
|
|
pCtrl_copy = pCtrl;
|
|
for(i = 0; i < chan_count; ++i) { /* for every channel in chan array */
|
|
pEqual = NULL;
|
|
|
|
pNchan = pCtrl_copy->pNstruct;
|
|
while(pNchan != NULL) {
|
|
/* for every data record received by this channel */
|
|
/* may want to use gsd_tss_within_delta instead of eq */
|
|
if(gsd_tss_eq(
|
|
gsd_get_ts((pCtrl->pDstruct)->time_type,
|
|
pNfirst_chan->pNdata),
|
|
gsd_get_ts((pCtrl_copy->pDstruct)->time_type,
|
|
pNchan->pNdata))) {
|
|
pEqual = gsd_get_ts(
|
|
(pCtrl->pDstruct)->time_type,
|
|
pNfirst_chan->pNdata);
|
|
break;
|
|
}
|
|
pNchan = pNchan->pNstruct;
|
|
}
|
|
if(NULL == pEqual) break;
|
|
/* no ts match in this chan, exit the for, */
|
|
/* and try next 1st channel time stamp */
|
|
pCtrl_copy++;
|
|
}
|
|
if(pEqual != NULL) return pEqual; /* success */
|
|
pNfirst_chan = pNfirst_chan->pNstruct;
|
|
/* try next data record of 1st channel */
|
|
}
|
|
return NULL; /* failed, returning NULL ptr */
|
|
}
|
|
/*
|
|
***************************
|
|
* Description:
|
|
* 1) returns ptr to the time stamp structure within the data buffer of
|
|
* types DBR_TIME_xxxx (an accessor routine)
|
|
******************************
|
|
*/
|
|
TS_STAMP *gsd_get_ts(time_type, pNdata)
|
|
int time_type;
|
|
void *pNdata;
|
|
{
|
|
switch(time_type) {
|
|
case DBR_TIME_STRING:
|
|
return &(((struct dbr_time_string *) pNdata)->stamp);
|
|
case DBR_TIME_SHORT:
|
|
return &(((struct dbr_time_short *) pNdata)->stamp);
|
|
case DBR_TIME_FLOAT:
|
|
return &(((struct dbr_time_float *) pNdata)->stamp);
|
|
case DBR_TIME_ENUM:
|
|
return &(((struct dbr_time_enum *) pNdata)->stamp);
|
|
case DBR_TIME_CHAR:
|
|
return &(((struct dbr_time_char *) pNdata)->stamp);
|
|
case DBR_TIME_LONG:
|
|
return &(((struct dbr_time_long *) pNdata)->stamp);
|
|
case DBR_TIME_DOUBLE:
|
|
return &(((struct dbr_time_double *) pNdata)->stamp);
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
************************************************
|
|
* Description:
|
|
* 1) returns ptr to the largest time stamp found in
|
|
* all of the channel data collected. If no data then
|
|
* returns NULL.
|
|
************************************************
|
|
*/
|
|
TS_STAMP *gsd_findlargest_ts(pCtrl, chan_count)
|
|
struct gsd_sync_ctrl *pCtrl;
|
|
int chan_count;
|
|
{
|
|
TS_STAMP ts;
|
|
TS_STAMP *pTs = &ts;
|
|
struct gsd_sync_linked *pNchan;
|
|
int i;
|
|
|
|
ts.secPastEpoch = 0;
|
|
ts.nsec = 0;
|
|
for (i = 0; i < chan_count; ++i) {
|
|
pNchan = pCtrl->pNstruct;
|
|
while(pNchan != NULL) {
|
|
/*
|
|
ca_printf(" %ld %ld >? %ld %ld\n",
|
|
(gsd_get_ts((pCtrl->pDstruct)->time_type,
|
|
pNchan->pNdata))->secPastEpoch,
|
|
(gsd_get_ts((pCtrl->pDstruct)->time_type,
|
|
pNchan->pNdata))->nsec,
|
|
pTs->secPastEpoch, pTs->nsec);
|
|
*/
|
|
if(gsd_tss_gtr(
|
|
gsd_get_ts((pCtrl->pDstruct)->time_type,pNchan->pNdata),
|
|
pTs) ||
|
|
gsd_tss_eq(
|
|
gsd_get_ts((pCtrl->pDstruct)->time_type,
|
|
pNchan->pNdata), pTs)) {
|
|
pTs = gsd_get_ts((pCtrl->pDstruct)->time_type,pNchan->pNdata);
|
|
}
|
|
pNchan = pNchan->pNstruct;
|
|
}
|
|
pCtrl++;
|
|
}
|
|
if(pTs == &ts) {
|
|
return NULL;
|
|
}
|
|
else {
|
|
return pTs;
|
|
}
|
|
}
|
|
/*
|
|
*******************************************
|
|
* Description:
|
|
* 1) Frees all event memory that was allocated on the fly by
|
|
* following each channel's linked list of gsd_sync_linked structures
|
|
*******************************************
|
|
*/
|
|
VOID gsd_freeevent_mem(pCtrl)
|
|
struct gsd_sync_ctrl *pCtrl;
|
|
{
|
|
struct gsd_sync_linked *pN;
|
|
struct gsd_sync_linked *pN_copy;
|
|
|
|
pN = pCtrl->pNstruct;
|
|
|
|
while(pN != NULL) {
|
|
if(pN->pNdata != NULL) {
|
|
/*
|
|
ca_printf("free %s %ld %ld\n", (pCtrl->pDstruct)->pName,
|
|
((struct dbr_time_float *) (pN->pNdata))->stamp.secPastEpoch,
|
|
((struct dbr_time_float *) (pN->pNdata))->stamp.nsec);
|
|
*/
|
|
free(pN->pNdata);
|
|
}
|
|
pN_copy = pN;
|
|
pN = pN->pNstruct;
|
|
free(pN_copy);
|
|
}
|
|
pCtrl->pNstruct = NULL;
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*******************************************
|
|
* Description:
|
|
* 1) for every channel
|
|
* 1) If finds linked list data that is time stamped the
|
|
* same as pTs.
|
|
* 1) copies this data to the Next data buffer of
|
|
* the gsd_sync_ctrl structure
|
|
* 2) sets nvalid = 1
|
|
* else
|
|
* 1) copies most recently received data to the
|
|
* Next data buffer of the gsd_sync_ctrl structure
|
|
* 2) clears nvalid = 0
|
|
*******************************************
|
|
*/
|
|
VOID gsd_syncset_findcopy(pCtrl, chan_count, pTs)
|
|
struct gsd_sync_ctrl *pCtrl;
|
|
int chan_count;
|
|
TS_STAMP *pTs;
|
|
{
|
|
struct gsd_sync_linked *pNchan;
|
|
int i;
|
|
|
|
for (i = 0; i < chan_count; ++i) {
|
|
pCtrl->nvalid = 0;
|
|
pNchan = pCtrl->pNstruct;
|
|
while(pNchan != NULL) {
|
|
if(gsd_tss_eq(gsd_get_ts((pCtrl->pDstruct)->time_type,
|
|
pNchan->pNdata), pTs)) {
|
|
gsd_copy_buffer(pNchan->pNdata, pCtrl->pNdata,
|
|
dbr_size_n((pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count));
|
|
pCtrl->nvalid = 1;
|
|
break;
|
|
}
|
|
pNchan = pNchan->pNstruct;
|
|
}
|
|
|
|
if((pCtrl->nvalid) != 1) {
|
|
if(pNchan = pCtrl->pNstruct) {
|
|
while(pNchan->pNstruct) pNchan = pNchan->pNstruct;
|
|
gsd_copy_buffer(pNchan->pNdata, pCtrl->pNdata,
|
|
dbr_size_n((pCtrl->pDstruct)->time_type,
|
|
(pCtrl->pDstruct)->count));
|
|
}
|
|
}
|
|
|
|
pCtrl++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/*
|
|
*************************************************
|
|
* Description:
|
|
* 1) byte block transfer
|
|
*************************************************
|
|
*/
|
|
VOID gsd_copy_buffer(pFrom, pTo, byte_count)
|
|
char *pFrom;
|
|
char *pTo;
|
|
unsigned int byte_count;
|
|
{
|
|
unsigned int i;
|
|
for(i = 0; i < byte_count; ++i) {
|
|
*pTo++ = *pFrom++;
|
|
}
|
|
return;
|
|
}
|
|
/*
|
|
**********************************************
|
|
* Description:
|
|
* 1) Frees all allocated memory which resulted from calls to
|
|
* gsd_sync_init
|
|
* gsd_sync_read
|
|
**********************************************
|
|
*/
|
|
VOID gsd_sync_clear(pSync_compctrl, chan_count)
|
|
struct gsd_sync_compctrl *pSync_compctrl;
|
|
unsigned int chan_count;
|
|
{
|
|
int i;
|
|
struct gsd_sync_ctrl *pSync_ctrl = pSync_compctrl->pCtrl;
|
|
|
|
if(NULL == pSync_compctrl) {
|
|
ca_printf("gsd_sync_clear: error NULL pSync_compctrl\n");
|
|
return;
|
|
}
|
|
if(NULL == pSync_ctrl) {
|
|
free(pSync_compctrl);
|
|
ca_printf("gsd_sync_clear: error NULL pSync_ctrl\n");
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < chan_count; ++i) {
|
|
ca_clear_channel((pSync_ctrl->pDstruct)->pChid);
|
|
ca_flush_io();
|
|
|
|
if(pSync_ctrl->pNdata != NULL) free(pSync_ctrl->pNdata);
|
|
if(pSync_ctrl->pAdata != NULL) free(pSync_ctrl->pAdata);
|
|
if((pSync_ctrl->pDstruct)->pSdata != NULL)
|
|
free((pSync_ctrl->pDstruct)->pSdata);
|
|
(pSync_ctrl->pDstruct)->pSdata = NULL;
|
|
|
|
pSync_ctrl++;
|
|
}
|
|
|
|
free(pSync_compctrl->pCtrl);
|
|
free(pSync_compctrl);
|
|
|
|
return;
|
|
}
|
|
/*
|
|
**********************************************
|
|
* Description:
|
|
* 1) if the two time stamps are within delta of each other then
|
|
* 1) return 1
|
|
* 2) otherwise return 0
|
|
**********************************************
|
|
*/
|
|
int gsd_tss_within_delta(pTs_s, pTs_l, pDelta)
|
|
TS_STAMP *pTs_s;
|
|
TS_STAMP *pTs_l;
|
|
TS_STAMP *pDelta;
|
|
{
|
|
TS_STAMP temp;
|
|
TS_STAMP *pTemp;
|
|
|
|
if(gsd_tss_eq(pTs_s, pTs_l)) return 1; /* equal, so within delta */
|
|
/* ensure that *pTs_l is the larger time stamp */
|
|
if(gsd_tss_gtr(pTs_s, pTs_l)) {
|
|
pTemp = pTs_l;
|
|
pTs_l = pTs_s;
|
|
pTs_s = pTemp;
|
|
}
|
|
|
|
temp.secPastEpoch = pTs_s->secPastEpoch + pDelta->secPastEpoch;
|
|
temp.nsec = pTs_s->nsec + pDelta->nsec;
|
|
|
|
if((gsd_tss_gtr(&temp, pTs_l)) || (gsd_tss_eq(&temp, pTs_l)))
|
|
return 1; /* within delta */
|
|
return 0; /* not within delta */
|
|
}
|
|
/*
|
|
**********************************************
|
|
* Description:
|
|
* 1) if the two time stamps are equal then
|
|
* 1) return 1
|
|
* 2) otherwise return 0
|
|
**********************************************
|
|
*/
|
|
int gsd_tss_eq(pTs_s, pTs_l)
|
|
TS_STAMP *pTs_s;
|
|
TS_STAMP *pTs_l;
|
|
{
|
|
if((pTs_s == NULL) || (pTs_l == NULL)) return 0; /* not equal ts */
|
|
if((pTs_s->secPastEpoch == pTs_l->secPastEpoch) &&
|
|
(pTs_s->nsec == pTs_l->nsec)) return 1; /* equal time stamps */
|
|
return 0; /* not equal time stamps */
|
|
}
|
|
/*
|
|
**********************************************
|
|
* Description:
|
|
* 1) if time stamp 1 > time stamp 2 then
|
|
* 1) return 1
|
|
* 2) otherwise return 0
|
|
**********************************************
|
|
*/
|
|
int gsd_tss_gtr(pTs_l, pTs_s)
|
|
TS_STAMP *pTs_l;
|
|
TS_STAMP *pTs_s;
|
|
{
|
|
if((pTs_l == NULL) || (pTs_s == NULL)) return 0; /* not gtr than */
|
|
if(pTs_l->secPastEpoch > pTs_s->secPastEpoch) return 1; /* gtr than */
|
|
if((pTs_l->secPastEpoch == pTs_s->secPastEpoch) &&
|
|
(pTs_l->nsec > pTs_s->nsec)) return 1; /* greater than */
|
|
return 0; /* not greater than */
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Note: UNIX specific routines below: !!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
*/
|
|
/*
|
|
************************************************
|
|
* Description:
|
|
* 1) indicate when timeout occurs
|
|
* Note: UNIX gettimeofday apparently is the only C/system time
|
|
* routine to yield resolution below 1 second, but it is
|
|
* represented as being inaccurate in its usec element
|
|
* (see man gettimeofday)
|
|
************************************************
|
|
*/
|
|
int gsd_timeout(pCompctrl, timeout_secs, pfdctx)
|
|
struct gsd_sync_compctrl *pCompctrl;
|
|
float timeout_secs;
|
|
VOID **pfdctx;
|
|
{
|
|
struct timeval new_gmt;
|
|
struct timezone zone;
|
|
|
|
float dif_secs;
|
|
|
|
gsd_ca_pend_event(pfdctx); /* allow C.A. events to occur */
|
|
/* in the Unix environment */
|
|
|
|
gettimeofday(&new_gmt, &zone);
|
|
|
|
if(new_gmt.tv_usec >= (pCompctrl->start_time).tv_usec) {
|
|
/* no borrow */
|
|
dif_secs = ((float) (new_gmt.tv_sec - (pCompctrl->start_time).tv_sec)) +
|
|
(((float) (new_gmt.tv_usec - (pCompctrl->start_time).tv_usec)) /
|
|
1000000.0);
|
|
}
|
|
else {
|
|
/* borrow */
|
|
dif_secs = ((float) (new_gmt.tv_sec - (pCompctrl->start_time).tv_sec - 1)) +
|
|
(((float) (1000000 + new_gmt.tv_usec - (pCompctrl->start_time).tv_usec)) /
|
|
1000000.0);
|
|
}
|
|
|
|
if(dif_secs > timeout_secs) {
|
|
return 1;
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
/*
|
|
**********************************************
|
|
**********************************************
|
|
*/
|
|
void gsd_ca_task_initialize(pfdctx)
|
|
void **pfdctx;
|
|
{
|
|
*pfdctx = (void *) fdmgr_init();
|
|
if(!(*pfdctx)) {
|
|
ca_printf("gsd_ca_task_initialize: fdmgr_init failed.\n");
|
|
abort();
|
|
}
|
|
SEVCHK(ca_add_fd_registration(gsd_fd_register, *pfdctx),
|
|
"gsd_ca_task_initialize: Fd registration failed.\n");
|
|
return;
|
|
}
|
|
/*
|
|
**********************************************
|
|
**********************************************
|
|
*/
|
|
void gsd_ca_pend_event(pfdctx)
|
|
void **pfdctx;
|
|
{
|
|
static struct timeval timeout = {0, USEC_TIME_OUT};
|
|
fdmgr_pend_event(*pfdctx, &timeout);
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
************************************************
|
|
* NAME
|
|
* gsd_fd_register(pfdcts, fd, condition)
|
|
* DESCRIPTION
|
|
* 1) if (condition is true) then
|
|
* 1) add file descriptor to fd manager
|
|
* else
|
|
* 1) delete file descriptor from fd manager
|
|
************************************************
|
|
*/
|
|
void gsd_fd_register(pfdctx, fd, condition)
|
|
void **pfdctx;
|
|
int fd;
|
|
int condition;
|
|
{
|
|
if(condition) {
|
|
fdmgr_add_fd(pfdctx, fd, gsd_ca_service, NULL);
|
|
}
|
|
else {
|
|
fdmgr_clear_fd(pfdctx, fd);
|
|
}
|
|
}
|
|
|
|
/*
|
|
*************************************************
|
|
* NAME
|
|
* gsd_ca_service()
|
|
* DESCRIPTION
|
|
* 1) call ca_pend_event to allow event handler execution
|
|
***************************************************
|
|
*/
|
|
void gsd_ca_service()
|
|
{
|
|
ca_pend_event(PEND_EVENT_DELAY);
|
|
}
|
|
|