diff --git a/src/ioc/db/chfPlugin.c b/src/ioc/db/chfPlugin.c index 3548b6d6e..f249d854b 100644 --- a/src/ioc/db/chfPlugin.c +++ b/src/ioc/db/chfPlugin.c @@ -481,23 +481,23 @@ static long channel_open(chFilter *filter) } static void channel_register_pre(chFilter *filter, - chPostEventFunc **cb_out, void **arg_out) + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { chfPlugin *p = (chfPlugin*) filter->plug->puser; chfFilter *f = (chfFilter*) filter->puser; if (p->pif->channelRegisterPre) - p->pif->channelRegisterPre(filter->chan, f->puser, cb_out, arg_out); + p->pif->channelRegisterPre(filter->chan, f->puser, cb_out, arg_out, probe); } static void channel_register_post(chFilter *filter, - chPostEventFunc **cb_out, void **arg_out) + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { chfPlugin *p = (chfPlugin*) filter->plug->puser; chfFilter *f = (chfFilter*) filter->puser; if (p->pif->channelRegisterPost) - p->pif->channelRegisterPost(filter->chan, f->puser, cb_out, arg_out); + p->pif->channelRegisterPost(filter->chan, f->puser, cb_out, arg_out, probe); } static void channel_report(chFilter *filter, const char *intro, int level) diff --git a/src/ioc/db/chfPlugin.h b/src/ioc/db/chfPlugin.h index e95852d41..d6762481a 100644 --- a/src/ioc/db/chfPlugin.h +++ b/src/ioc/db/chfPlugin.h @@ -141,6 +141,10 @@ typedef struct chfPluginIf { * to be called when a data update is sent from the database towards the * event queue. * + * The plugin may find out the type of data it will receive by looking at 'probe'. + * If the plugin will change the data type and/or size, it must update 'probe' + * accordingly. + * * @param chan dbChannel for which the connection is being made. * @param pvt Pointer to private structure. * @param cb_out Pointer to this plugin's post-event callback (NULL to bypass @@ -149,7 +153,8 @@ typedef struct chfPluginIf { * this plugin's post-event callback. */ void (* channelRegisterPre) (dbChannel *chan, void *pvt, - chPostEventFunc **cb_out, void **arg_out); + chPostEventFunc **cb_out, void **arg_out, + db_field_log *probe); /** @brief Register callbacks for post-event-queue operation. * @@ -163,9 +168,9 @@ typedef struct chfPluginIf { * to be called when a data update is sent from the event queue towards the * final user. * - * The plugin must call the supplied 'st_in' function (from within - * its own set-type callback) with 'arg_in' as first argument after changing - * the data type and/or array size of 'chan'. + * The plugin may find out the type of data it will receive by looking at 'probe'. + * If the plugin will change the data type and/or size, it must update 'probe' + * accordingly. * * @param chan dbChannel for which the connection is being made. * @param pvt Pointer to private structure. @@ -175,7 +180,8 @@ typedef struct chfPluginIf { * this plugin's post-event callback. */ void (* channelRegisterPost) (dbChannel *chan, void *pvt, - chPostEventFunc **cb_out, void **arg_out); + chPostEventFunc **cb_out, void **arg_out, + db_field_log *probe); /** @brief Channel report request. * diff --git a/src/ioc/db/dbAccess.c b/src/ioc/db/dbAccess.c index 5fabc7290..9a7cc4137 100644 --- a/src/ioc/db/dbAccess.c +++ b/src/ioc/db/dbAccess.c @@ -840,7 +840,7 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType, localAddr.field_type = pfl->field_type; localAddr.field_size = pfl->element_size; localAddr.no_elements = pfl->no_elements; - if (pfl->type == dbfl_type_value) + if (pfl->type == dbfl_type_val) localAddr.pfield = (char *) &pfl->u.v.field; else localAddr.pfield = (char *) pfl->u.r.field; @@ -876,7 +876,7 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType, localAddr.field_type = pfl->field_type; localAddr.field_size = pfl->element_size; localAddr.no_elements = pfl->no_elements; - if (pfl->type == dbfl_type_value) + if (pfl->type == dbfl_type_val) localAddr.pfield = (char *) &pfl->u.v.field; else localAddr.pfield = (char *) pfl->u.r.field; diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index aaf150ba7..ca81540a9 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -44,7 +44,7 @@ static void chf_value(parseContext *parser, parse_result *presult) parser->filter = NULL; if (filter->plug->fif->parse_end(filter) == parse_continue) { - ellAdd(&parser->chan->filters, &filter->node); + ellAdd(&parser->chan->filters, &filter->list_node); } else { free(filter); // FIXME: Use free-list *presult = parse_stop; @@ -445,57 +445,57 @@ long dbChannelOpen(dbChannel *chan) chPostEventFunc *func; void *arg; long status; + ELLNODE *node; - filter = (chFilter *) ellFirst(&chan->filters); - while (filter) { - /* - * Call channel_open for all filters - */ + for (node = ellFirst(&chan->filters); node; node = ellNext(node)) { + filter = CONTAINER(node, chFilter, list_node); + /* Call channel_open */ status = 0; if (filter->plug->fif->channel_open) status = filter->plug->fif->channel_open(filter); if (status) return status; - - /* - * Build up the pre- and post-event-queue filter chains - */ - func = NULL; - arg = NULL; - if (filter->plug->fif->channel_register_post) { - filter->plug->fif->channel_register_post(filter, &func, &arg); - if (func) { - ellAdd(&chan->post_chain, &filter->post_node); - filter->post_func = func; - filter->post_arg = arg; - } - } - func = NULL; - arg = NULL; - if (filter->plug->fif->channel_register_pre) { - filter->plug->fif->channel_register_pre(filter, &func, &arg); - if (func) { - ellAdd(&chan->pre_chain, &filter->pre_node); - filter->pre_func = func; - filter->pre_arg = arg; - } - } - - filter = (chFilter *) ellNext(&filter->node); } /* Set up type probe */ db_field_log probe; - db_field_log *pfl; - probe.type = dbfl_type_probe; + db_field_log p; probe.field_type = dbChannelFieldType(chan); probe.no_elements = dbChannelElements(chan); probe.element_size = dbChannelElementSize(chan); + p = probe; - /* Call filter chains to determine data type/size changes */ - pfl = dbChannelRunPreChain(chan, &probe); - if (pfl != &probe) return -1; - pfl = dbChannelRunPostChain(chan, &probe); - if (pfl != &probe) return -1; + /* + * Build up the pre- and post-event-queue filter chains + * Separate loops because the probe must reach the filters in the right order. + */ + for (node = ellFirst(&chan->filters); node; node = ellNext(node)) { + filter = CONTAINER(node, chFilter, list_node); + func = NULL; + arg = NULL; + if (filter->plug->fif->channel_register_pre) { + filter->plug->fif->channel_register_pre(filter, &func, &arg, &p); + if (func) { + ellAdd(&chan->pre_chain, &filter->pre_node); + filter->pre_func = func; + filter->pre_arg = arg; + probe = p; + } + } + } + for (node = ellFirst(&chan->filters); node; node = ellNext(node)) { + filter = CONTAINER(node, chFilter, list_node); + func = NULL; + arg = NULL; + if (filter->plug->fif->channel_register_post) { + filter->plug->fif->channel_register_post(filter, &func, &arg, &p); + if (func) { + ellAdd(&chan->post_chain, &filter->post_node); + filter->post_func = func; + filter->post_arg = arg; + probe = p; + } + } + } /* Save probe results */ chan->final_no_elements = probe.no_elements; @@ -634,7 +634,7 @@ void dbChannelFilterShow(dbChannel *chan, const char *intro, int level) chFilter *filter = (chFilter *) ellFirst(&chan->filters); while (filter) { filter->plug->fif->channel_report(filter, intro, level); - filter = (chFilter *) ellNext(&filter->node); + filter = (chFilter *) ellNext(&filter->list_node); } } diff --git a/src/ioc/db/dbChannel.h b/src/ioc/db/dbChannel.h index e5c8c1040..04f571fd0 100644 --- a/src/ioc/db/dbChannel.h +++ b/src/ioc/db/dbChannel.h @@ -97,8 +97,8 @@ typedef struct chFilterIf { /* Channel operations: */ long (* channel_open)(chFilter *filter); - void (* channel_register_pre) (chFilter *filter, chPostEventFunc **cb_out, void **arg_out); - void (* channel_register_post)(chFilter *filter, chPostEventFunc **cb_out, void **arg_out); + void (* channel_register_pre) (chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe); + void (* channel_register_post)(chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe); void (* channel_report)(chFilter *filter, const char *intro, int level); /* FIXME: More filter routines here ... */ void (* channel_close)(chFilter *filter); @@ -114,7 +114,7 @@ typedef struct chFilterPlugin { /* A chFilter holds data for a single filter instance */ struct chFilter { - ELLNODE node; + ELLNODE list_node; ELLNODE pre_node; ELLNODE post_node; dbChannel *chan; diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index c652bdd5a..51ae1fec6 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -634,7 +634,7 @@ static db_field_log* db_create_event_log (struct evSubscrip *pevent) struct dbChannel *chan = pevent->chan; struct dbCommon *prec = dbChannelRecord(chan); if (pevent->useValque) { - pLog->type = dbfl_type_value; + pLog->type = dbfl_type_val; pLog->stat = prec->stat; pLog->sevr = prec->sevr; pLog->time = prec->time; diff --git a/src/ioc/db/db_field_log.h b/src/ioc/db/db_field_log.h index fb5ebed5f..49cdb9d34 100644 --- a/src/ioc/db/db_field_log.h +++ b/src/ioc/db/db_field_log.h @@ -52,12 +52,11 @@ typedef void (dbfl_freeFunc)(struct db_field_log *pfl); /* Types of db_field_log: rec = use record, val = val inside, ref = reference inside */ typedef enum dbfl_type { dbfl_type_rec = 0, - dbfl_type_value, - dbfl_type_ref, - dbfl_type_probe + dbfl_type_val, + dbfl_type_ref } dbfl_type; -#define dbflTypeStr(t) (t==dbfl_type_value?"val":t==dbfl_type_rec?"rec":t==dbfl_type_probe?"prb":"ref") +#define dbflTypeStr(t) (t==dbfl_type_val?"val":t==dbfl_type_rec?"rec":"ref") struct dbfl_val { union native_value field; /* Field value */ diff --git a/src/ioc/db/test/chfPluginTest.c b/src/ioc/db/test/chfPluginTest.c index bba5f29ca..7c2613c44 100644 --- a/src/ioc/db/test/chfPluginTest.c +++ b/src/ioc/db/test/chfPluginTest.c @@ -166,13 +166,13 @@ static long channel_open(dbChannel *chan, void *user) } static void channelRegisterPre(dbChannel *chan, void *user, - chPostEventFunc **cb_out, void **arg_out) + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { myStruct *my = (myStruct*)user; } static void channelRegisterPost(dbChannel *chan, void *user, - chPostEventFunc **cb_out, void **arg_out) + chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { myStruct *my = (myStruct*)user; } diff --git a/src/ioc/db/test/dbChannelTest.c b/src/ioc/db/test/dbChannelTest.c index ed69d6d84..df49c1183 100644 --- a/src/ioc/db/test/dbChannelTest.c +++ b/src/ioc/db/test/dbChannelTest.c @@ -116,11 +116,11 @@ long c_open(chFilter *filter) testOk(e & e_open, "channel_open called"); return 0; } -void c_reg_pre(chFilter *filter, chPostEventFunc **cb_out, void **arg_out) +void c_reg_pre(chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { testOk(e & e_reg_pre, "channel_register_pre called"); } -void c_reg_post(chFilter *filter, chPostEventFunc **cb_out, void **arg_out) +void c_reg_post(chFilter *filter, chPostEventFunc **cb_out, void **arg_out, db_field_log *probe) { testOk(e & e_reg_post, "channel_register_post called"); }