Change mechanism to detect data type/size changes by plugins

* Remove "probe" type from db_field_log
* Supply probe when registering plugin chains
* Minor refactoring (rename) in dbfl_type and chFilter
This commit is contained in:
Ralph Lange
2012-04-27 13:21:55 -04:00
committed by Michael Davidsaver
parent c41fcef260
commit ec7dfb1890
9 changed files with 68 additions and 63 deletions

View File

@@ -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)

View File

@@ -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.
*

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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;
}

View File

@@ -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");
}