Transformer SDK For C  6.2.11.309924
demo-userdata2.c

This module calculates High & Low for a set of symbols and publishes them to DataSource, as well as caching them in the core. It is designed as an example of how to associate module related data with symbols held within the Transformer cache.

This is a similar example to previous example except that the cached parameters persist over a Transformer restart.

Note
This example has been written using the legacy API.

Sample configuration:

symbols  /DEMO/*

Source code:

/*
* Transformer - Sample Module
*
* Copyright CAPLIN Systems Ltd 2000-2006
*
* This module calculates High & Low for a set of symbols and publishes them to DataSource,
* as well as caching them in the core. It is designed as an example of how to tag module
* related data with symbols held within the Transformer core memory.
*
* This modules implements userdata in a more advanced way that permits persistence over
* Transformer restarts
*/
#include "transformer.h"
/* Each module should have a unique identifier (unless of course data is to be shared between
* modules). Conventionally, this is formed by taking an abbreviated version of the module
* name and turning into a 32 bit hex number. The least significant byte is usually 0. Though
* if several types of information are required for a module then this is usually incremented
* to permit rudimentary type checking
*/
#define MODULE_ID 0x444d4f00 /* DMO\0 */
/* This structure is that which is associated with the symbol within the Transformer core */
typedef struct {
double high;
double low;
} demodata_t;
static char **symbols = NULL;
static int symbols_num = 0;
static void demo_filewrite(FILE *fp, void *data);
static void *demo_fileread(FILE *fp, char *name);
static int demo_print(char *buf, size_t size, void *data);
static void demo_recv_update(int feed, ds_data_t *pkt, time_t arr_tim, int id, void *data);
void mod_init(char *module_name)
{
userinfo_t funcs;
char buf[1024];
int i;
/* Add a configuration option to obtain the symbols we wish to process */
ds_config_add_array_option("symbols","Symbols to process",DS_CONFIG_STR_ARRAY,&symbols,&symbols_num);
/* Load a config file based on the name of the module */
snprintf(buf,sizeof(buf),"%s.conf",module_name);
/* Check whether any symbols are required, if not then log this condition to the main Transformer
log file
*/
if ( symbols_num == 0 ) {
ds_printf_time(rtas_log,"(%s) No symbols required\n",module_name);
return;
}
/* Now register an interest in the symbols */
for ( i = 0; i < symbols_num; i++ ) {
register_interest(symbols[i],demo_recv_update,0,NULL);
}
/* Register handlers for userdata */
funcs.id = MODULE_ID; /* The unique module identifier */
funcs.ident = "DEMO"; /* A short name */
funcs.desc = "Demo Module"; /* A more descriptive name */
funcs.filewrite = demo_filewrite; /* Function to write out userdata to file */
funcs.strprint = demo_print; /* Function to display userdata as diagnostics */
funcs.fileread = demo_fileread; /* Funciton to read in userdata from file */
register_userdata_funcs(&funcs); /* Register the handler functions */
return;
}
void mod_exit()
{
int i;
/* We have to loop over all known symbols and remove the associated userdata */
for ( i = 0; i < symbols_num; i++ ) {
/* Call the function to remove all references to userdata with a tag of MODULE_ID.
* symbol_remove_alluserdata() makes a call to the third argument (which has
* a prototype void (*dataremover(void *data) to free up the memory. Since we
* have just a simple structure in this case, we can use the system free() function
*/
symbol_remove_alluserdata(symbols[i],MODULE_ID,free);
/* Deregister interests in this symbol wildcard */
deregister_interest(symbols[i],demo_recv_update,0,NULL);
}
/* Deregister function handlers for this modules userdata */
return;
}
static void demo_filewrite(FILE *fp, void *data)
{
demodata_t *user = data;
fprintf(fp,"%f %f\n",user->high,user->low);
}
static void *demo_fileread(FILE *fp, char *name)
{
demodata_t *user;
user = calloc(1,sizeof(*user));
fscanf(fp,"%lf %lf",&user->high,&user->low);
return (user);
}
static int demo_print(char *buf, size_t size, void *data)
{
demodata_t *user = data;
if ( data == NULL )
return 0;
snprintf(buf,size,"High %lf Low %lf",user->high,user->low);
return 1;
}
static void demo_recv_update(int feed, ds_data_t *pkt, time_t arr_tim, int id, void *data)
{
ds_data_t *dsdata;
demodata_t *user;
double val;
char *value;
/* Try and obtain the userdata for this symbol. If it is not present then
* we create it
*/
if ( ( user = symbol_get_userdata(pkt->subject,MODULE_ID) ) == NULL ) {
user = calloc(1,sizeof(*user));
/* Initialise high and low with some improbable values */
user->high = 0.0;
user->low = 99999999.0;
/* Register the userdata in the system */
symbol_set_userdata(pkt->subject,MODULE_ID,user);
}
/* Pick up the "Last" field within the update */
if ( ( value = packet_get_field_byname(pkt,"dLast") ) != NULL ) {
/* Create an update packet for High and Low */
dsdata = ds_init_data(pkt->subject,DS_RECORD_TYPE,F_CREATEPARENT|F_CREATEOBJECT);
val = atof(value);
/* If the new value for Last is the highest so far, then add it to the update */
if ( val > user->high ) {
user->high = val;
ds_add_record_float(dsdata,"High",val);
}
/* If the new value for Last is the lowest so far, then add it do the update */
if ( val < user->low ) {
user->low = val;
ds_add_record_float(dsdata,"Low",val);
}
/* If we've come across either a new High or a new Low then dsdata->count != 0 */
if ( dsdata->count ) {
packet_merge(pkt,dsdata,NULL); /* Merge into the packet going to other modules */
/* Contribute the High/Low to DataSource and cache it in core */
}
ds_free_data(dsdata);
}
return;
}

Generated on Sat Aug 26 2017 12:36:31 for Transformer SDK For C