diff --git a/src/ioc/db/dbEvent.c b/src/ioc/db/dbEvent.c index 51ae1fec6..58ff8e5dd 100644 --- a/src/ioc/db/dbEvent.c +++ b/src/ioc/db/dbEvent.c @@ -626,13 +626,14 @@ int epicsShareAPI db_post_extra_labor (dbEventCtx ctx) * NOTE: This assumes that the db scan lock is already applied * (as it copies data from the record) */ -static db_field_log* db_create_event_log (struct evSubscrip *pevent) +db_field_log* epicsShareAPI db_create_event_log (struct evSubscrip *pevent) { db_field_log *pLog = (db_field_log *) freeListCalloc(dbevFieldLogFreeList); if (pLog) { struct dbChannel *chan = pevent->chan; struct dbCommon *prec = dbChannelRecord(chan); + pLog->ctx = dbfl_context_event; if (pevent->useValque) { pLog->type = dbfl_type_val; pLog->stat = prec->stat; @@ -655,6 +656,21 @@ static db_field_log* db_create_event_log (struct evSubscrip *pevent) return pLog; } +/* + * DB_CREATE_READ_LOG() + * + */ +db_field_log* epicsShareAPI db_create_read_log (struct dbChannel *chan) +{ + db_field_log *pLog = (db_field_log *) freeListCalloc(dbevFieldLogFreeList); + + if (pLog) { + pLog->ctx = dbfl_context_read; + pLog->type = dbfl_type_rec; + } + return pLog; +} + /* * DB_QUEUE_EVENT_LOG() * diff --git a/src/ioc/db/dbEvent.h b/src/ioc/db/dbEvent.h index 39da157f9..bbd4ff06b 100644 --- a/src/ioc/db/dbEvent.h +++ b/src/ioc/db/dbEvent.h @@ -73,6 +73,8 @@ epicsShareFunc void epicsShareAPI db_post_single_event (dbEventSubscription es); epicsShareFunc void epicsShareAPI db_event_enable (dbEventSubscription es); epicsShareFunc void epicsShareAPI db_event_disable (dbEventSubscription es); +epicsShareFunc struct db_field_log* epicsShareAPI db_create_event_log (struct evSubscrip *pevent); +epicsShareFunc struct db_field_log* epicsShareAPI db_create_read_log (struct dbChannel *chan); epicsShareFunc void epicsShareAPI db_delete_field_log (struct db_field_log *pfl); #define DB_EVENT_OK 0 diff --git a/src/ioc/db/db_field_log.h b/src/ioc/db/db_field_log.h index 49cdb9d34..53ea242d7 100644 --- a/src/ioc/db/db_field_log.h +++ b/src/ioc/db/db_field_log.h @@ -56,6 +56,12 @@ typedef enum dbfl_type { dbfl_type_ref } dbfl_type; +/* Context of db_field_log: event = subscription update, read = read reply */ +typedef enum dbfl_context { + dbfl_context_read = 0, + dbfl_context_event +} dbfl_context; + #define dbflTypeStr(t) (t==dbfl_type_val?"val":t==dbfl_type_rec?"rec":"ref") struct dbfl_val { @@ -69,7 +75,8 @@ struct dbfl_ref { }; typedef struct db_field_log { - enum dbfl_type type; /* type (union) selector */ + enum dbfl_type type:2; /* type (union) selector */ + enum dbfl_context ctx:1; /* context (operation type) */ epicsTimeStamp time; /* Time stamp */ unsigned short stat; /* Alarm Status */ unsigned short sevr; /* Alarm Severity */ diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 55ae0b15d..f43df2c77 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -508,6 +508,7 @@ static void read_reply ( void *pArg, struct dbChannel *dbch, int status; int v41; int autosize; + int local_fl = 0; long item_count; ca_uint32_t payload_size; dbAddr *paddr=&dbch->addr; @@ -565,8 +566,21 @@ static void read_reply ( void *pArg, struct dbChannel *dbch, return; } + /* If filters are involved in a read, create field log and run filters */ + if (!pfl && (ellCount(&dbch->pre_chain) || ellCount(&dbch->post_chain))) { + pfl = db_create_read_log(dbch); + if (pfl) { + local_fl = 1; + pfl = dbChannelRunPreChain(dbch, pfl); + pfl = dbChannelRunPostChain(dbch, pfl); + } + } + status = dbChannel_get_count ( dbch, pevext->msg.m_dataType, pPayload, &item_count, pfl); + + if (local_fl) db_delete_field_log(pfl); + if ( status < 0 ) { /* * I cant wait to redesign this protocol from scratch! @@ -647,6 +661,8 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p void *pPayload; int status; int v41; + int local_fl = 0; + db_field_log *pfl = NULL; if ( ! pciu ) { logBadId ( pClient, mp, 0 ); @@ -689,8 +705,21 @@ static int read_action ( caHdrLargeArray *mp, void *pPayloadIn, struct client *p return RSRV_OK; } + /* If filters are involved in a read, create field log and run filters */ + if (ellCount(&pciu->dbch->pre_chain) || ellCount(&pciu->dbch->post_chain)) { + pfl = db_create_read_log(pciu->dbch); + if (pfl) { + local_fl = 1; + pfl = dbChannelRunPreChain(pciu->dbch, pfl); + pfl = dbChannelRunPostChain(pciu->dbch, pfl); + } + } + status = dbChannel_get ( pciu->dbch, mp->m_dataType, - pPayload, mp->m_count, 0 ); + pPayload, mp->m_count, pfl ); + + if (local_fl) db_delete_field_log(pfl); + if ( status < 0 ) { send_err ( mp, ECA_GETFAIL, pClient, RECORD_NAME ( pciu->dbch ) ); SEND_UNLOCK ( pClient );