Experimental Physics and Industrial Control System
I see the problem. What you are doing was not anticipated. You do not make a copy, the data is owned by the record all the time, so dbfl_has_copy correctly returns false. But then the code in dbAccess.c assumes that it has to ask the record for things like the actual number of elements etc, so it calls get_array_info for the dbAddr. For actual record fields this is precisely what we want. In your case I guess this is where things start to go wrong. Indeed you have set no_elements and field_type in the pfl. I am not sure how to fix this properly. Adding a dummy dtor means we lie to dbAccess, telling it we have made a copy in order to make it use the meta data in the pfl instead of trying to query the record about it. While this works I find it a bit obscure...
Diff comments:
> diff --git a/modules/database/src/std/filters/info.c b/modules/database/src/std/filters/info.c
> new file mode 100644
> index 0000000..7bdb2c3
> --- /dev/null
> +++ b/modules/database/src/std/filters/info.c
> @@ -0,0 +1,161 @@
> +/*************************************************************************\
> +* Copyright (c) 2021 Paul Scherrer Institute
> +* SPDX-License-Identifier: EPICS
> +* EPICS BASE is distributed subject to a Software License Agreement found
> +* in file LICENSE that is included with this distribution.
> +\*************************************************************************/
> +
> +/*
> + * Author: Dirk Zimoch <dirk.zimoch at psi.ch>
> + */
> +
> +#include <stdio.h>
> +#include <string.h>
> +
> +#include "chfPlugin.h"
> +#include "dbStaticLib.h"
> +#include "dbAccessDefs.h"
> +#include "dbExtractArray.h"
> +#include "db_field_log.h"
> +#include "dbLock.h"
> +#include "epicsExit.h"
> +#include "freeList.h"
> +#include "epicsExport.h"
> +
> +typedef struct myStruct {
> + char name[52]; /* arbitrary size, we better had dynamic strings */
> + DBENTRY dbentry;
> + int longstr;
> +} myStruct;
> +
> +static void *myStructFreeList;
> +
> +static const
> +chfPluginEnumType longstrEnum[] = {{"no",0}, {"off",0}, {"yes",1}, {"on",1}, {"auto",2}, {NULL, 0}};
> +
> +static const chfPluginArgDef opts[] = {
> + chfString (myStruct, name, "name", 1, 0),
> + chfString (myStruct, name, "n", 1, 0),
> + chfEnum (myStruct, longstr, "longstr", 0, 1, longstrEnum),
> + chfEnum (myStruct, longstr, "l", 0, 1, longstrEnum),
> + chfPluginArgEnd
> +};
> +
> +static void * allocPvt(void)
> +{
> + myStruct *my = (myStruct*) freeListCalloc(myStructFreeList);
> + if (!my) return NULL;
> + my->longstr = 2;
> + return (void *) my;
> +}
> +
> +static void freePvt(void *pvt)
> +{
> + freeListFree(myStructFreeList, pvt);
> +}
> +
> +static int parse_ok(void *pvt)
> +{
> + myStruct *my = (myStruct*) pvt;
> + if (my->name[0] == 0) /* empty name */
> + return -1;
> + if (my->name[sizeof(my->name)-2] != 0) /* name buffer overrun */
> + return -1;
> + return 0;
> +}
> +
> +static db_field_log* filter(void* pvt, dbChannel *chan, db_field_log *pfl)
> +{
> + myStruct *my = (myStruct*) pvt;
> +
> + if (pfl->type == dbfl_type_ref && pfl->u.r.dtor)
> + pfl->u.r.dtor(pfl);
These two lines seem to be unnecessary, since you always have type and dtor set to fixed values
> + pfl->type = dbfl_type_ref;
> + pfl->u.r.dtor = NULL;
> + pfl->u.r.field = (void*)dbGetInfoString(&my->dbentry);
> +
> + if (my->longstr) {
> + pfl->field_size = 1;
> + pfl->field_type = DBF_CHAR;
> + pfl->no_elements = strlen((char*)pfl->u.r.field)+1;
> + } else {
> + pfl->field_size = MAX_STRING_SIZE;
> + pfl->field_type = DBF_STRING;
> + pfl->no_elements = 1;
> + }
> + return pfl;
> +}
> +
> +static long channel_open(dbChannel *chan, void *pvt)
> +{
> + myStruct *my = (myStruct*) pvt;
> + DBENTRY* pdbe = &my->dbentry;
> + int status;
> +
> + dbInitEntryFromAddr(&chan->addr, pdbe);
> + for (status = dbFirstInfo(pdbe); !status; status = dbNextInfo(pdbe))
> + if (strcmp(dbGetInfoName(pdbe), my->name) == 0)
> + return 0;
> + return -1;
> +}
> +
> +static void channelRegisterPre(dbChannel *chan, void *pvt,
> + chPostEventFunc **cb_out, void **arg_out, db_field_log *pfl)
> +{
> + myStruct *my = (myStruct*) pvt;
> + size_t len = strlen(dbGetInfoString(&my->dbentry)) + 1;
> + if (my->longstr == 2) {
> + my->longstr = len > MAX_STRING_SIZE;
> + }
> + if (my->longstr) {
> + pfl->field_size = 1;
> + pfl->field_type = DBF_CHAR;
> + pfl->no_elements = len;
> + } else {
> + pfl->field_size = MAX_STRING_SIZE;
> + pfl->field_type = DBF_STRING;
> + pfl->no_elements = 1;
> + }
> + *cb_out = filter;
> + *arg_out = pvt;
> +}
> +
> +static void channel_report(dbChannel *chan, void *pvt, int level,
> + const unsigned short indent)
> +{
> + myStruct *my = (myStruct*) pvt;
> + printf("%*sInfo: name=%s\n", indent, "",
> + my->name);
> +}
> +
> +static chfPluginIf pif = {
> + allocPvt,
> + freePvt,
> +
> + NULL, /* parse_error, */
> + parse_ok,
> +
> + channel_open,
> + channelRegisterPre,
> + NULL, /* channelRegisterPost, */
> + channel_report,
> + NULL /* channel_close */
> +};
> +
> +static void infoShutdown(void* ignore)
> +{
> + if(myStructFreeList)
> + freeListCleanup(myStructFreeList);
> + myStructFreeList = NULL;
> +}
> +
> +static void infoInitialize(void)
> +{
> + if (!myStructFreeList)
> + freeListInitPvt(&myStructFreeList, sizeof(myStruct), 64);
> +
> + chfPluginRegister("info", &pif, opts);
> + epicsAtExit(infoShutdown, NULL);
> +}
> +
> +epicsExportRegistrar(infoInitialize);
--
https://code.launchpad.net/~dirk.zimoch/epics-base/+git/epics-base/+merge/399414
Your team EPICS Core Developers is requested to review the proposed merge of ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0.
- References:
- [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0 Dirk Zimoch via Core-talk
- Navigate by Date:
- Prev:
Re: [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0 Dirk Zimoch via Core-talk
- Next:
Re: [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0 Dirk Zimoch via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
<2021>
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0 Dirk Zimoch via Core-talk
- Next:
Re: [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0 Dirk Zimoch via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
<2021>
2022
2023
2024