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:
committed by
Michael Davidsaver
parent
c41fcef260
commit
ec7dfb1890
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user