Files
pcas/src/ioc/db/chfPlugin.h
Ralph Lange ec7dfb1890 Change mechanism to detect data type/size changes by plugins
* Remove "probe" type from db_field_log
* Supply probe when registering plugin chains
* Minor refactoring (rename) in dbfl_type and chFilter
2012-04-27 13:21:55 -04:00

281 lines
9.6 KiB
C

/*************************************************************************\
* Copyright (c) 2010 Brookhaven National Laboratory.
* Copyright (c) 2010 Helmholtz-Zentrum Berlin
* fuer Materialien und Energie GmbH.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#ifndef CHFPLUGIN_H
#define CHFPLUGIN_H
#include <shareLib.h>
#include <dbDefs.h>
#include <epicsTypes.h>
#include <dbChannel.h>
struct db_field_log;
/* Based on the linkoptions utility by Michael Davidsaver (BNL) */
/** @file chfPlugin.h
* @brief Channel filter simplified plugins.
*
* Utility layer to allow an easier (reduced) interface for
* channel filter plugins.
*
* Parsing the configuration arguments of a channel filter plugin
* is done according to an argument description table provided by the plugin.
* The parser stores the results directly into a user supplied structure
* after appropriate type conversion.
*
* To specify the arguments, a chfPluginArgDef table must be defined
* for the user structure. This table has to be specified when the plugin registers.
*
* The plugin is responsible to register an init function using
* epicsExportRegistrar() and the accompanying registrar() directive in the dbd,
* and call chfPluginRegister() from within the init function.
*
* For example:
*
* typedef struct myStruct {
* ... other stuff
* epicsUInt32 ival;
* double dval;
* epicsUInt32 ival2;
* int enumval;
* char strval[20];
* } myStruct;
*
* static const
* chfPluginEnumType colorEnum[] = { {"Red",1}, {"Green",2}, {"Blue",3}, {NULL,0} };
*
* static const
* chfPluginDef myStructDef[] = {
* chfInt32 (myStruct, ival, "Integer" , 0, 0),
* chfInt32 (myStruct, ival2, "Second" , 1, 0),
* chfDouble(myStruct, dval, "Double" , 1, 0),
* chfString(myStruct, strval , "String" , 1, 0),
* chfEnum (myStruct, enumval, "Color" , 1, 0, colorEnum),
* chfPluginEnd
* };
*
* Note: The 4th argument specifies the parameter to be required (1) or optional (0),
* the 5th whether converting to the required type is allowed (1), or
* type mismatches are an error (0).
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Channel filter simplified plugin interface.
*
* The routines in this structure must be implemented by each filter plugin.
*/
typedef struct chfPluginIf {
/* Memory management */
/** @brief Allocate private resources.
*
* <em>Called before parsing starts.</em>
* The plugin should allocate its per-instance structures,
* returning a pointer to them or NULL requesting an abort of the operation.
*
* allocPvt may be set to NULL, if no resource allocation is needed.
*
* @return Pointer to private structure, NULL if operation is to be aborted.
*/
void * (* allocPvt) (void);
/** @brief Free private resources.
*
* <em>Called as part of abort or shutdown.</em>
* The plugin should release any resources allocated for this filter;
* no further calls through this interface will be made.
*
* freePvt may be set to NULL, if no resources need to be released.
*
* @param pvt Pointer to private structure.
*/
void (* freePvt) (void *pvt);
/* Parameter parsing results */
/** @brief A parsing error occurred.
*
* <em>Called after parsing failed with an error.</em>
*/
void (* parse_error) (void);
/** @brief Configuration has been parsed successfully.
*
* <em>Called after parsing has finished ok.</em>
* The plugin may check the validity of the parsed data,
* returning -1 to request an abort of the operation.
*
* @param pvt Pointer to private structure.
* @return 0 for success, -1 if operation is to be aborted.
*/
int (* parse_ok) (void *pvt);
/* Channel operations */
/** @brief Open channel.
*
* <em>Called as part of the channel connection setup.</em>
*
* @param chan dbChannel for which the connection is being made.
* @param pvt Pointer to private structure.
* @return 0 for success, -1 if operation is to be aborted.
*/
long (* channel_open) (dbChannel *chan, void *pvt);
/** @brief Register callbacks for pre-event-queue operation.
*
* <em>Called as part of the channel connection setup.</em>
*
* This function is called to establish the stack of plugins that an event
* is passed through between the database and the event queue.
*
* The plugin must set pe_out to point to its own post-event callback in order
* to be called when a data update is sent from the database towards the
* event queue.
*
* The plugin may find out the type of data it will receive by looking at 'probe'.
* If the plugin will change the data type and/or size, it must update 'probe'
* accordingly.
*
* @param chan dbChannel for which the connection is being made.
* @param pvt Pointer to private structure.
* @param cb_out Pointer to this plugin's post-event callback (NULL to bypass
* this plugin).
* @param arg_out Argument that must be supplied when calling
* this plugin's post-event callback.
*/
void (* channelRegisterPre) (dbChannel *chan, void *pvt,
chPostEventFunc **cb_out, void **arg_out,
db_field_log *probe);
/** @brief Register callbacks for post-event-queue operation.
*
* <em>Called as part of the channel connection setup.</em>
*
* This function is called to establish the stack of plugins that an event
* is passed through between the event queue and the final user (CA server or
* database access).
*
* The plugin must set pe_out to point to its own post-event callback in order
* to be called when a data update is sent from the event queue towards the
* final user.
*
* The plugin may find out the type of data it will receive by looking at 'probe'.
* If the plugin will change the data type and/or size, it must update 'probe'
* accordingly.
*
* @param chan dbChannel for which the connection is being made.
* @param pvt Pointer to private structure.
* @param cb_out Pointer to this plugin's post-event callback (NULL to bypass
* this plugin).
* @param arg_out Argument that must be supplied when calling
* this plugin's post-event callback.
*/
void (* channelRegisterPost) (dbChannel *chan, void *pvt,
chPostEventFunc **cb_out, void **arg_out,
db_field_log *probe);
/** @brief Channel report request.
*
* <em>Called as part of show... routines.</em>
*
* @param chan dbChannel for which the report is requested.
* @param pvt Pointer to private structure.
* @param intro Line header string to be printed at the beginning of each line.
* @param level Interest level.
*/
void (* channel_report) (dbChannel *chan, void *pvt, const char *intro, int level);
/* FIXME: More filter routines here ... */
/** @brief Channel close request.
*
* <em>Called as part of connection shutdown.</em>
* @param chan dbChannel for which the connection is being shut down.
* @param pvt Pointer to private structure.
*/
void (* channel_close) (dbChannel *chan, void *pvt);
} chfPluginIf;
typedef enum chfPluginArg {
chfPluginArgInvalid=0,
chfPluginArgBoolean,
chfPluginArgInt32,
chfPluginArgDouble,
chfPluginArgString,
chfPluginArgEnum
} chfPluginArg;
typedef struct chfPluginEnumType {
const char *name;
const int value;
} chfPluginEnumType;
typedef struct chfPluginArgDef {
const char * name;
chfPluginArg optType;
int required:1;
int convert:1;
epicsUInt32 offset;
epicsUInt32 size;
const chfPluginEnumType *enums;
} chfPluginArgDef;
#define chfInt32(Struct, Member, Name, Req, Conv) \
{Name, chfPluginArgInt32, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
#define chfBoolean(Struct, Member, Name, Req, Conv) \
{Name, chfPluginArgBoolean, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
#define chfDouble(Struct, Member, Name, Req, Conv) \
{Name, chfPluginArgDouble, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
#define chfString(Struct, Member, Name, Req, Conv) \
{Name, chfPluginArgString, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
#define chfEnum(Struct, Member, Name, Req, Conv, Enums) \
{Name, chfPluginArgEnum, Req, Conv, OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), Enums}
#define chfPluginArgEnd {0}
/* Extra output when parsing and converting */
#define CHFPLUGINDEBUG 1
/** @brief Return the string associated with Enum index 'i'.
*
* @param Enums A null-terminated array of string/integer pairs.
* @param i An Enum index.
* @param def String to be returned when 'i' isn't a valid Enum index.
* @return The string associated with 'i'.
*/
epicsShareFunc
const char*
epicsShareAPI
chfPluginEnumString(const chfPluginEnumType *Enums, int i, const char* def);
/** @brief Register a plugin.
*
* @param key The plugin name key that clients will use.
* @param pif Pointer to the plugin's interface.
* @param opts Pointer to the configuration argument description table.
*/
epicsShareFunc
int
epicsShareAPI
chfPluginRegister(const char* key, const chfPluginIf *pif, const chfPluginArgDef* opts);
#ifdef __cplusplus
}
#endif
#endif // CHFPLUGIN_H