epics-base / pva2pva

PV Access gateway/proxy and EPICS Process Database integration
https://epics-base.github.io/pva2pva/
Other
4 stars 13 forks source link

Support for long DBF_STRING fields #22

Open anjohnson opened 5 years ago

anjohnson commented 5 years ago

Since QSRV talks directly to dbAccess it could determine how long a DBF_STRING field's buffer is (they are allowed to be longer than MAX_STRING_SIZE, e.g. the NAME field, and the VAL fields of the lsi, lso and printf record types). QSRV could thus provide access to long string fields without truncation, although it doesn't at the moment.

This is using pvaSrv, which handles this long string's value (although possibly more by luck than by design):

epics> dba this-is-a-long-prefix-to-test-pvaSrv:BaseVersion.NAME
Record Address: 0x77a130 Field Address: 0x77a130 Field Description: 0x7710b0
   No Elements: 1
   Record Type: stringin
    Field Type: 0 = DBF_STRING
    Field Size: 61
       Special: 1
DBR Field Type: 0 = DBR_STRING

tux% pvget this-is-a-long-prefix-to-test-pvaSrv:BaseVersion.NAME
this-is-a-long-prefix-to-test-pvaSrv:BaseVersion.NAME this-is-a-long-prefix-to-test-pvaSrv:BaseVersion

This is using QSRV, which truncates the long string's value at 39 characters:

epics> dba this-is-a-long-prefix-to-test-qsrv:BaseVersion.NAME
Record Address: 0x1104d08 Field Address: 0x1104d08 Field Description: 0x10f1970
   No Elements: 1
   Record Type: stringin
    Field Type: 0 = DBF_STRING
    Field Size: 61
       Special: 1
DBR Field Type: 0 = DBR_STRING

tux% pvget this-is-a-long-prefix-to-test-qsrv:BaseVersion.NAME
this-is-a-long-prefix-to-test-qsrv:BaseVersion.NAME this-is-a-long-prefix-to-test-qsrv:Base
mdavidsaver commented 5 years ago

I'm not clear on how this would work. I guess you mean to use dbChannelFinalFieldSize(chan) instead of MAX_STRING_SIZE? Can I do this through dbGet()?

anjohnson commented 5 years ago

For monitors and gets using dbChannelFinalFieldSize(chan) would allow any filters to modify the string (not that we have any filters that do string processing yet to my knowledge), so yes. For puts you could use dbChannelFieldSize(chan) to determine the max length if you need it.

This may be harder than I thought to do properly though, and we might want to change dbAccess to make it simpler. As I showed above a pvget from pvaSrv works, but that's because the code just copies an unlimited zero-terminated string from static_cast<char *>(dbChannelField(chan)). For most uses that should work, but it isn't bullet-proof against an unterminated string. I don't see a problem with copying up to a zero-terminator as long as you take no more than dbChannelFinalFieldSize(chan) bytes.

The code for dbGet(chan, DBF_STRING, pbuffer 0, 0, 0) can't handle long strings because there's no way to tell it how big pbuffer is, so it uses the smaller of MAX_STRING_SIZE or chan->addr.field_size. I already added special routines for handling long strings to dbLink.c in 3.15, and we might want to do something similar in dbAccess.c for dbGet() and dbPut().

mdavidsaver commented 5 years ago

This may be harder than I thought to do properly though

This was my reading of the situation :)

we might want to do something similar in dbAccess.c

I would prefer this to filling up QSRV with workarounds for limitations in this API.