240 lines
8.6 KiB
C
240 lines
8.6 KiB
C
/*************************************************************************\
|
|
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
|
* National Laboratory.
|
|
* Copyright (c) 2010 Brookhaven National Laboratory.
|
|
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
|
|
* fuer Materialien und Energie GmbH.
|
|
* SPDX-License-Identifier: EPICS
|
|
* EPICS BASE is distributed subject to a Software License Agreement found
|
|
* in file LICENSE that is included with this distribution.
|
|
\*************************************************************************/
|
|
|
|
#ifndef INC_dbChannel_H
|
|
#define INC_dbChannel_H
|
|
|
|
/** \file dbChannel.h
|
|
* @brief Declarations for the @ref dbChannel "dbChannel" record type
|
|
*
|
|
* Author: Andrew Johnson <anj@aps.anl.gov>
|
|
* Ralph Lange <Ralph.Lange@bessy.de>
|
|
*/
|
|
|
|
#include "dbDefs.h"
|
|
#include "dbAddr.h"
|
|
#include "ellLib.h"
|
|
#include "epicsTypes.h"
|
|
#include "errMdef.h"
|
|
#include "db_field_log.h"
|
|
#include "dbEvent.h"
|
|
#include "dbCoreAPI.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
* event subscription
|
|
*/
|
|
typedef struct evSubscrip {
|
|
ELLNODE node;
|
|
struct dbChannel *chan;
|
|
EVENTFUNC *user_sub;
|
|
void *user_arg;
|
|
struct event_que *ev_que;
|
|
db_field_log **pLastLog;
|
|
unsigned long npend; /* n times this event is on the queue */
|
|
unsigned long nreplace; /* n times replacing event on the queue */
|
|
unsigned char select;
|
|
char useValque;
|
|
char callBackInProgress;
|
|
char enabled;
|
|
} evSubscrip;
|
|
|
|
typedef struct chFilter chFilter;
|
|
|
|
/* A dbChannel points to a record field, and can have multiple filters */
|
|
typedef struct dbChannel {
|
|
const char *name;
|
|
dbAddr addr; /* address structure for record/field */
|
|
long final_no_elements; /* final number of elements (arrays) */
|
|
short final_field_size; /* final size of element */
|
|
short final_type; /* final type of database field */
|
|
ELLLIST filters; /* list of filters as created from JSON */
|
|
ELLLIST pre_chain; /* list of filters to be called pre-event-queue */
|
|
ELLLIST post_chain; /* list of filters to be called post-event-queue */
|
|
} dbChannel;
|
|
|
|
/**
|
|
* Prototype for the channel event function that is called in filter stacks
|
|
*
|
|
* When invoked the scan lock for the record associated with 'chan' _may_ be locked.
|
|
* Unless dbfl_has_copy(pLog), it must call dbScanLock before accessing the data,
|
|
* as this indicates the data is still owned by the record.
|
|
*
|
|
* This function has ownership of the field log pLog, if it wishes to discard
|
|
* this update it should free the field log with db_delete_field_log() and
|
|
* then return NULL.
|
|
*/
|
|
typedef db_field_log* (chPostEventFunc)(void *pvt, dbChannel *chan, db_field_log *pLog);
|
|
|
|
/** Return values from chFilterIf->parse_*- routines: */
|
|
typedef enum {
|
|
parse_stop, parse_continue
|
|
} parse_result;
|
|
|
|
/** These routines must be implemented by each filter plug-in */
|
|
typedef struct chFilterIf {
|
|
/**
|
|
* cleanup pointer passed to ::dbRegisterFilter ().
|
|
* Called during DB shutdown
|
|
*/
|
|
void (* priv_free)(void *puser);
|
|
/** Parsing event handlers: */
|
|
parse_result (* parse_start)(chFilter *filter);
|
|
/** If parse_start() returns parse_continue for a filter, one of
|
|
* parse_abort() or parse_end() will later be called for that same
|
|
* filter.
|
|
*/
|
|
void (* parse_abort)(chFilter *filter);
|
|
/** If parse_abort() is called it should release any memory allocated
|
|
* for this filter; no further parse_...() calls will be made;
|
|
*/
|
|
parse_result (* parse_end)(chFilter *filter);
|
|
/** If parse_end() returns parse_stop it should have released any
|
|
* memory allocated for this filter; no further parse_...() calls will
|
|
* be made in this case.
|
|
*/
|
|
|
|
parse_result (* parse_null)(chFilter *filter);
|
|
parse_result (* parse_boolean)(chFilter *filter, int boolVal);
|
|
parse_result (* parse_integer)(chFilter *filter, long integerVal);
|
|
parse_result (* parse_double)(chFilter *filter, double doubleVal);
|
|
parse_result (* parse_string)(chFilter *filter, const char *stringVal,
|
|
size_t stringLen); /* NB: stringVal is not zero-terminated: */
|
|
|
|
parse_result (* parse_start_map)(chFilter *filter);
|
|
parse_result (* parse_map_key)(chFilter *filter, const char *key,
|
|
size_t stringLen); /* NB: key is not zero-terminated: */
|
|
parse_result (* parse_end_map)(chFilter *filter);
|
|
|
|
parse_result (* parse_start_array)(chFilter *filter);
|
|
parse_result (* parse_end_array)(chFilter *filter);
|
|
|
|
/** Channel operations: */
|
|
long (* channel_open)(chFilter *filter);
|
|
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, int level, const unsigned short indent);
|
|
void (* channel_close)(chFilter *filter);
|
|
} chFilterIf;
|
|
|
|
/** A chFilterPlugin holds data for a filter plugin */
|
|
typedef struct chFilterPlugin {
|
|
ELLNODE node;
|
|
const char *name;
|
|
const chFilterIf *fif;
|
|
void *puser;
|
|
} chFilterPlugin;
|
|
|
|
/** A chFilter holds data for a single filter instance */
|
|
struct chFilter {
|
|
ELLNODE list_node;
|
|
ELLNODE pre_node;
|
|
ELLNODE post_node;
|
|
dbChannel *chan;
|
|
const chFilterPlugin *plug;
|
|
chPostEventFunc *pre_func;
|
|
void *pre_arg;
|
|
chPostEventFunc *post_func;
|
|
void *post_arg;
|
|
void *puser;
|
|
};
|
|
|
|
struct dbCommon;
|
|
struct dbFldDes;
|
|
|
|
DBCORE_API void dbChannelInit (void);
|
|
DBCORE_API void dbChannelExit(void);
|
|
DBCORE_API long dbChannelTest(const char *name);
|
|
DBCORE_API dbChannel * dbChannelCreate(const char *name);
|
|
DBCORE_API long dbChannelOpen(dbChannel *chan);
|
|
|
|
/**Following is also defined in db_convert.h*/
|
|
DBCORE_API extern unsigned short dbDBRnewToDBRold[];
|
|
|
|
/** In the following macros pChan is dbChannel* */
|
|
|
|
/** evaluates to const char* */
|
|
#define dbChannelName(pChan) ((pChan)->name)
|
|
|
|
/** evaluates to struct dbCommon* */
|
|
#define dbChannelRecord(pChan) ((pChan)->addr.precord)
|
|
|
|
/** evaluates to struct dbFldDes* */
|
|
#define dbChannelFldDes(pChan) ((pChan)->addr.pfldDes)
|
|
|
|
/** evaluates to long */
|
|
#define dbChannelElements(pChan) ((pChan)->addr.no_elements)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelFieldType(pChan) ((pChan)->addr.field_type)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelExportType(pChan) ((pChan)->addr.dbr_field_type)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelExportCAType(pChan) (dbDBRnewToDBRold[dbChannelExportType(pChan)])
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelFieldSize(pChan) ((pChan)->addr.field_size)
|
|
|
|
/** evaluates to long */
|
|
#define dbChannelFinalElements(pChan) ((pChan)->final_no_elements)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelFinalFieldType(pChan) ((pChan)->final_type)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelFinalCAType(pChan) (dbDBRnewToDBRold[(pChan)->final_type])
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelFinalFieldSize(pChan) ((pChan)->final_field_size)
|
|
|
|
/** evaluates to short */
|
|
#define dbChannelSpecial(pChan) ((pChan)->addr.special)
|
|
|
|
/** Channel filters do not get to interpose here since there are many
|
|
* places where the field pointer is compared with the address of a
|
|
* specific record field, so they can't modify the pointer value.
|
|
*/
|
|
/** evaluates to void* */
|
|
#define dbChannelField(pChan) ((pChan)->addr.pfield)
|
|
|
|
|
|
DBCORE_API long dbChannelGet(dbChannel *chan, short type,
|
|
void *pbuffer, long *options, long *nRequest, void *pfl);
|
|
DBCORE_API long dbChannelGetField(dbChannel *chan, short type,
|
|
void *pbuffer, long *options, long *nRequest, void *pfl);
|
|
DBCORE_API long dbChannelPut(dbChannel *chan, short type,
|
|
const void *pbuffer, long nRequest);
|
|
DBCORE_API long dbChannelPutField(dbChannel *chan, short type,
|
|
const void *pbuffer, long nRequest);
|
|
DBCORE_API void dbChannelShow(dbChannel *chan, int level,
|
|
const unsigned short indent);
|
|
DBCORE_API void dbChannelFilterShow(dbChannel *chan, int level,
|
|
const unsigned short indent);
|
|
DBCORE_API void dbChannelDelete(dbChannel *chan);
|
|
|
|
DBCORE_API void dbRegisterFilter(const char *key, const chFilterIf *fif, void *puser);
|
|
DBCORE_API db_field_log* dbChannelRunPreChain(dbChannel *chan, db_field_log *pLogIn);
|
|
DBCORE_API db_field_log* dbChannelRunPostChain(dbChannel *chan, db_field_log *pLogIn);
|
|
DBCORE_API const chFilterPlugin * dbFindFilter(const char *key, size_t len);
|
|
DBCORE_API void dbChannelGetArrayInfo(dbChannel *chan,
|
|
void **pfield, long *no_elements, long *offset);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* INC_dbChannel_H */
|