EPICS Home

Experimental Physics and Industrial Control System


 
2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024  Index 2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  <20212022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: [Merge] ~dirk.zimoch/epics-base:FilterForInfoFields into epics-base:7.0
From: Ben Franksen via Core-talk <core-talk at aps.anl.gov>
To: mp+399414 at code.launchpad.net
Date: Wed, 10 Mar 2021 14:58:18 -0000
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  <20212022  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  <20212022  2023  2024