mfd-access-unsorted-external-defines.m2i
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:40k
源码类别:
SNMP编程
开发平台:
Unix_Linux
- ############################################################# -*- c -*-
- ## generic include for XXX. Do not use directly.
- ##
- ## $Id: mfd-access-unsorted-external-defines.m2i,v 1.12 2004/10/08 23:39:17 rstory Exp $
- ########################################################################
- ##
- @eval $mfd_aue_wrap_param = "wrap_ctx"@
- @eval $mfd_aue_wrap_param_type = "${context}_interface_ctx *"@
- @eval $mfd_aue_wrap_param_decl = "$mfd_aue_wrap_param_type $mfd_aue_wrap_param"@
- ##
- @eval $mfd_aue_param = "${context}_reg"@
- @eval $mfd_aue_param_type = "${context}_registration_ptr"@
- @eval $mfd_aue_param_decl = "$mfd_aue_param_type $mfd_aue_param"@
- @eval $mfd_aue_param_cmt = "$mfd_aue_param Pointer to a $mfd_aue_param_type"
- ##
- @if $m2c_mark_boundary == 1@
- /** START code generated by $RCSfile: mfd-access-unsorted-external-defines.m2i,v $ $Revision: 1.12 $ */
- @end@
- ##//####################################################################
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @if $m2c_processing_type eq 'h'@
- ##
- @if $m2c_include_examples == 1@
- $example_start
- /* *********************************************************************
- * Since we have no idea how you really access your data, we'll go with
- * a worst case example: a flat text file.
- @ if $m2c_data_transient != 2@
- @ print Example code is for fully transient data. Either turn off@
- @ print m2c_include_examples or set m2c_data_transient to 2.@
- @ exit@
- @ end@
- */
- #define MAX_LINE_SIZE 256
- $example_end
- @end@
- /**
- * loop context
- *
- * TODO:
- * define loop context structure
- *
- * Since the actual loop is in the MFD handler, a loop contex parameter
- * is provided to help you keep track of where you are in between calls
- * to functions that you wrote and the master MFD handler calls. The
- * structure of this context is user defineable, and is defined in the
- * file ${table}_data_access.h.
- *
- * E.G., if your data is stored in a linked list, the obvious thing you
- * want to know from one function call to the next is your current
- * position in the linked list. Thus the easiest context to use is a
- * pointer within the linked list. For an array, the current index to
- * that array would be easiest.
- *
- * The funtion calls are actually passed a reference to the loop
- * context, to allow the loop context to be allocated memory. Here are
- * some simple examples definitions for various data formats. These
- * definitions are used in examples later on.
- *
- */
- typedef struct ${context}_loop_context_s {
- /*
- * temporary context used during iteration
- */
- ${context}_rowreq_ctx *rowreq_ctx;
- @if $m2c_include_examples == 1@
- /*
- * this example code is based on a data source that is a
- * text file to be read and parsed.
- */
- FILE *filep;
- char line[MAX_LINE_SIZE];
- @end@
- } ${context}_loop_context;
- /*
- * define a reference to the loop context
- *
- * NOTE: DO NOT ADD ITEMS TO THIS STRUCTURE!
- */
- typedef struct ${context}_ref_loop_ctx_s {
- ${context}_loop_context *loop_ctx;
- } ${context}_ref_loop_ctx;
- int ${context}_loop_get_first( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref);
- int ${context}_loop_get_next( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref);
- int ${context}_loop_get_data( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref);
- int ${context}_loop_save_position($mfd_aue_param_decl,
- ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_loop_ctx *save_loop_ctx_ref, int reuse);
- int ${context}_loop_cleanup_context( $mfd_aue_param_decl, ${context}_ref_loop_ctx *ref);
- ##
- @end@ // m2c_processing_type eq 'h'
- ########################################################################
- ##//####################################################################
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @if $m2c_processing_type eq 'i'@
- /**
- * @internal
- * wrapper around clean up a loop reference
- */
- static int
- _${context}_loop_cleanup_context( $mfd_aue_wrap_param_decl,
- ${context}_ref_loop_ctx *ref)
- {
- DEBUGMSGTL(("internal:${context}:_${context}_loop_cleanup_context","calledn"));
- return ${context}_loop_cleanup_context($mfd_aue_wrap_param->user_ctx, ref);
- } /* _${context}_loop_cleanup_context */
- /**
- * @internal
- * wrapper around save position
- */
- static int
- _${context}_loop_save_position( $mfd_aue_wrap_param_decl, ${context}_ref_loop_ctx *ref,
- ${context}_ref_loop_ctx *ref_copy, int reuse)
- {
- DEBUGMSGTL(("internal:${context}:_${context}_loop_save_position","calledn"));
- return ${context}_loop_save_position($mfd_aue_wrap_param->user_ctx, ref,
- ref_copy, reuse);
- } /* _${context}_loop_save_position */
- /**
- * @internal
- * wrapper around user get_first to setup the index oid
- */
- static int
- _${context}_loop_get_first_wrapper($mfd_aue_wrap_param_decl,
- ${context}_ref_loop_ctx * loop_ctx_ref,
- ${context}_ref_rowreq_ctx * rowreq_ctx_ref)
- {
- int rc;
- DEBUGMSGTL(("internal:${context}:_${context}_loop_get_first_wrapper","calledn"));
- rc = ${context}_loop_get_first($mfd_aue_wrap_param->user_ctx, loop_ctx_ref,
- rowreq_ctx_ref);
- /*
- * convert index to OID
- */
- if(SNMPERR_SUCCESS == rc ) {
- netsnmp_assert((NULL != rowreq_ctx_ref) &&
- (rowreq_ctx_ref->rowreq_ctx->oid_idx.oids == rowreq_ctx_ref->rowreq_ctx->oid_tmp));
- rowreq_ctx_ref->rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp);
- rc = ${context}_index_to_oid(&rowreq_ctx_ref->rowreq_ctx->oid_idx,
- &rowreq_ctx_ref->rowreq_ctx->tbl_idx);
- netsnmp_assert(rowreq_ctx_ref->rowreq_ctx->oid_idx.len !=
- sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp));
- }
- return rc;
- } /* _${context}_loop_get_first_wrapper */
- /**
- * @internal
- * wrapper around user get_next to setup the index oid
- */
- static int
- _${context}_loop_get_next_wrapper($mfd_aue_wrap_param_decl,
- ${context}_ref_loop_ctx * loop_ctx_ref,
- ${context}_ref_rowreq_ctx * rowreq_ctx_ref)
- {
- int rc;
- DEBUGMSGTL(("internal:${context}:_${context}_loop_get_next_wrapper","calledn"));
- rc = ${context}_loop_get_next($mfd_aue_wrap_param->user_ctx, loop_ctx_ref,
- rowreq_ctx_ref);
- /*
- * convert index to OID
- */
- if(SNMPERR_SUCCESS == rc ) {
- netsnmp_assert((NULL != rowreq_ctx_ref) &&
- (rowreq_ctx_ref->rowreq_ctx->oid_idx.oids == rowreq_ctx_ref->rowreq_ctx->oid_tmp));
- rowreq_ctx_ref->rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp);
- rc = ${context}_index_to_oid(&rowreq_ctx_ref->rowreq_ctx->oid_idx,
- &rowreq_ctx_ref->rowreq_ctx->tbl_idx);
- netsnmp_assert(rowreq_ctx_ref->rowreq_ctx->oid_idx.len !=
- sizeof(rowreq_ctx_ref->rowreq_ctx->oid_tmp));
- }
- return rc;
- } /* _${context}_loop_get_next_wrapper */
- @if $m2c_data_transient != 0@ #
- /**
- * @internal
- * get data wrapper to allocate context for the user
- */
- static int
- _${context}_loop_get_data_wrapper($mfd_aue_wrap_param_decl,
- ${context}_ref_loop_ctx * loop_ctx_ref,
- ${context}_ref_rowreq_ctx * rowreq_ctx_ref)
- {
- // ${context}_rowreq_ctx *orig_ctx = rowreq_ctx_ref->rowreq_ctx;
- DEBUGMSGTL(("internal:${context}:_${context}_loop_get_data_wrapper","calledn"));
- return ${context}_loop_get_data($mfd_aue_wrap_param->user_ctx, loop_ctx_ref, rowreq_ctx_ref);
- } /* _${context}_loop_get_data_wrapper */
- @end@ // transient != 0
- /**
- * @internal
- * initialize the iterator container with functions or wrappers
- */
- void
- _${context}_container_init(${context}_interface_ctx *if_ctx)
- {
- DEBUGMSGTL(("internal:${context}:_${context}_container_init","calledn"));
- if_ctx->container = netsnmp_container_iterator_get(/** registration */
- if_ctx,
- /** compare */
- NULL,
- /** get_first */
- (Netsnmp_Iterator_Loop_Key*)_${context}_loop_get_first_wrapper,
- /** get_next */
- (Netsnmp_Iterator_Loop_Key*)_${context}_loop_get_next_wrapper,
- /** get_data */
- @if $m2c_data_transient != 0@ #
- (Netsnmp_Iterator_Loop_Data*)_${context}_loop_get_data_wrapper,
- @else@
- NULL,
- @end@
- /** save_pos */
- (Netsnmp_Iterator_Ctx_Dup*)_${context}_loop_save_position,
- /** init_context */
- (Netsnmp_Iterator_Ctx*)NULL,
- /** cleanup_context */
- (Netsnmp_Iterator_Ctx*)_${context}_loop_cleanup_context,
- /** free_user_ctx */
- NULL,
- /** sorted */
- 0);
- } /* _${context}_container_init */
- ##
- @end@ // m2c_processing_type eq 'i'
- ########################################################################
- ##//####################################################################
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @if $m2c_processing_type eq 'c'@
- /**
- * unsorted-external overview
- *
- * The unsorted external data access code works by calling a few simple
- * functions to get the index value for each row. Once the agent determines
- * which row is needed to process an incoming request, another function
- * is called to retrieve the data for that row.
- *
- * A simplified version of the pseudo-code looks like this:
- *
- * ${context}_loop_get_first(loop,data)
- * while( no_error ) {
- * if( best_match(data, key)
- * ${context}_loop_save_position(loop,pos);
- * ${context}_loop_get_next(loop,data)
- * }
- * ${context}_loop_get_data(pos,data)
- * ${context}_loop_cleanup_context(loop)
- */
- /***********************************************************************
- *
- * ITERATION
- *
- ***********************************************************************/
- /**
- * get the first data index
- *
- * Summary
- * -------
- * This function is called to initialize the iterator loop context for a
- * new iteration loop and return the index(es) for the first
- * ${context}_data in the data set.
- *
- * Note that during the loop, the only important thing is the indexes.
- * If access to your data is cheap/fast (e.g. you have a pointer to a
- * structure in memory), it would make sense to update the data here.
- * If, however, the accessing the data invovles more work (e.g. parsing
- * some other existing data, or peforming calculations to derive the data),
- * then you should limit yourself to setting the indexes. Extracting the
- * can be put off until the desired row is found. See the notes on
- * ${context}_loop_get_data().
- *
- * Note that this function does not correspond to a SNMP GET pdu, and
- * you should return data items in whatever order they are already in.
- * (In fact, if your data is already ordered in the same order as the
- * SNMP indexes, you shouldn't be using the unsorted-access code).
- *
- * This function should update the table index (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
- * values for the raw data (rowreq_ctx_ref->rowreq_ctx->data).
- *
- * More Details
- * ------------
- * If there is currently no data available, return MFD_END_OF_DATA.
- * Otherwise, you should set rowreq_ctx_ref->rowreq_ctx and its indexes.
- *
- * rowreq_ctx_ref->rowreq_ctx will be NULL. You should allocate a new context
- * for this loop. [Alternatively, you could allocate one in
- * ${context}_loop_init_context, save it in your
- * ${context}_ref_loop_ctx, and use it here.]
- *
- * Once you have your context pointer, you should set the index (or indexes)
- * in rowreq_ctx_ref->rowreq_ctx->tbl_idx to the appropriate value for this row. [If you
- * use your loop_ctx_ref cleverly, you might be able to put this work in
- * ${context}_loop_get_next, and simply call that function.]
- *
- * @param $mfd_aue_param_cmt
- * @param loop_ctx_ref Pointer to your loop reference.
- * @param rowreq_ctx_ref Pointer to a context reference.
- *
- * @retval MFD_SUCCESS : success.
- * @retval MFD_END_OF_DATA : no data available
- * @retval MFD_ERROR : error.
- */
- int
- ${context}_loop_get_first( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref)
- {
- DEBUGMSGTL(("verbose:${context}:${context}_loop_get_first","calledn"));
- netsnmp_assert(rowreq_ctx_ref);
- netsnmp_assert(loop_ctx_ref);
- /*
- * allocate memory for new structure
- */
- loop_ctx_ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
- if(NULL == loop_ctx_ref->loop_ctx)
- return MFD_ERROR;
- /*
- * allocate a temporary context to use during iteration
- */
- @ eval $m2c_tmp = ""@
- @ if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
- @ eval $m2c_tmp = "NULL"@
- @ if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
- @ eval $m2c_tmp = "$m2c_tmp, NULL"@
- @ @end@
- @ end@
- loop_ctx_ref->loop_ctx->rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
- if(NULL == loop_ctx_ref->loop_ctx->rowreq_ctx) {
- SNMP_FREE(loop_ctx_ref->loop_ctx);
- return MFD_RESOURCE_UNAVAILABLE;
- }
- /*
- * TODO:
- * set up loop context
- */
- @if $m2c_include_examples == 1@
- $example_start
- /*
- * open our data file.
- */
- loop_ctx_ref->loop_ctx->filep = fopen("/etc/dummy.conf", "r");
- if(NULL == loop_ctx_ref->loop_ctx->filep) {
- return MFD_RESOURCE_UNAVAILABLE;
- }
- $example_end
- @end@
- @ifconf ${table}_update_idx.m2i@
- @ include ${table}_update_idx.m2i@
- @else@
- @ if $m2c_include_examples == 1@
- $example_start
- /*
- * in this example, after opening the file, get next does the same thing
- * as get first, we let's just call get next...
- */
- return ${context}_loop_get_next($mfd_aue_param, loop_ctx_ref, rowreq_ctx_ref);
- $example_end
- @ else@
- /*
- * we just need the index for now. Reuse the one in the loop context's
- * temporary row request context. (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
- */
- rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
- /*
- * TODO:
- * set local vars for index from loop_ctx_ref->loop_ctx
- * this can be done in one of two ways:
- */
- /*
- * 1) individually
- */
- @ foreach $node index@
- @ include m2c_setup_node.m2i@
- /*
- * TODO:
- * set rowreq_ctx_ref->rowreq_ctx->tbl_idx->$node
- @ if $m2c_node_needlength == 1@
- * and rowreq_ctx_ref->tbl_idx->${node}_len
- @ end@
- */
- @ end@ #foreach
- /*
- * OR
- */
- /*
- * 2) by calling ${context}_indexes_set()
- * ${context}_indexes_set(rowreq_ctx_ref->tbl_idx,
- @ foreach $node index@
- @ include m2c_setup_node.m2i@
- @ if $m2c_node_needlength == 1@
- * ${node}_ptr, ${node}_len
- @ else@
- * $node
- @ end@
- @ end@ # foreach index
- * );
- */
- @ end@ # example
- @end@ #ifconf
- return MFD_SUCCESS;
- } /* ${context}_loop_get_first */
- /**
- * get the next data index
- *
- * Summary
- * -------
- * This function returns the next data item in the data set. The same
- * caveat applies here as did above. The indexes are the important parts
- * during loop processing.
- *
- * Note that this function does not correspond to a SNMP GET-NEXT pdu, and
- * you should return data items in whatever order they are already in.
- * (In fact, if your data is already ordered in the same order as the
- * SNMP indexes, you shouldn't be using the unsorted-access code).
- *
- * More Details
- * ------------
- * rowreq_ctx_ref->rowreq_ctx will have been set in ${context}_loop_get_first.
- *
- * If there is currently no data available, return MFD_END_OF_DATA.
- * Otherwise, you should set the indexes in rowreq_ctx_ref->rowreq_ctx->tbl_idx.
- *
- * You should set the index (or indexes) in rowreq_ctx_ref->rowreq_ctx->tbl_idx to the
- * appropriate value for this row.
- *
- * @param $mfd_aue_param_cmt
- * @param loop_ctx_ref Pointer to your loop reference.
- * @param rowreq_ctx_ref Pointer to a context reference.
- *
- * @retval MFD_SUCCESS : success.
- * @retval MFD_END_OF_DATA : no more data available
- * @retval MFD_ERROR : error.
- */
- int
- ${context}_loop_get_next( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref)
- {
- DEBUGMSGTL(("verbose:${context}:${context}_loop_get_next","calledn"));
- netsnmp_assert(loop_ctx_ref && loop_ctx_ref->loop_ctx);
- netsnmp_assert(rowreq_ctx_ref);
- /*
- * we just need the index for now. Reuse the one in the loop context's
- * temporary row request context. (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
- */
- rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
- @ if $m2c_include_examples == 1@
- $example_start
- /*
- * get a line (skip blank lines)
- */
- do {
- if (!fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
- loop_ctx_ref->loop_ctx->filep)) {
- /* we're done */
- fclose(loop_ctx_ref->loop_ctx->filep);
- loop_ctx_ref->loop_ctx->filep = NULL;
- }
- } while (loop_ctx_ref->loop_ctx->filep && (loop_ctx_ref->loop_ctx->line[0] == 'n'));
- /*
- * check for end of data
- */
- if(NULL == loop_ctx_ref->loop_ctx->filep)
- return MFD_END_OF_DATA;
- /*
- * TODO:
- * set local vars for index from loop_ctx_ref->loop_ctx
- * this can be done in one of two ways:
- */
- /*
- * 1) individually
- */
- @ foreach $node index@
- @ include m2c_setup_node.m2i@
- /*
- * TODO:
- * set rowreq_ctx_ref->rowreq_ctx->tbl_idx->$node
- @ if $m2c_node_needlength == 1@
- * and rowreq_ctx_ref->tbl_idx->${node}_len
- @ end@
- */
- @ end@ #foreach
- /*
- * OR
- */
- /*
- * 2) by calling ${context}_indexes_set()
- * ${context}_indexes_set(rowreq_ctx_ref->tbl_idx,
- @ foreach $node index@
- @ include m2c_setup_node.m2i@
- @ if $m2c_node_needlength == 1@
- * ${node}_ptr, ${node}_len
- @ else@
- * $node
- @ end@
- @ end@ # foreach index
- * );
- */
- $example_end
- @ end@ # example
- return MFD_SUCCESS;
- } /* ${context}_loop_get_next */
- /**
- * duplicate the current loop reference
- *
- * Summary
- * -------
- * During loop iteration, the iterator keeps track of the row that
- * is the current best match. This function is called when the
- * current row is a better match than any previous row.
- *
- * You should save any information you need to be able to locate this row
- * again from the current loop context to a new loop context.
- *
- * At the end of the loop, when the best match has been found, the saved
- * loop context will be used to get the data for the row by calling
- * ${context}_loop_get_data().
- @if $m2c_data_transient != 0@ # persistent
- *
- * Since your data is transient, you need to make a copy of it before
- * the iterator moves on to the next row.
- @end@
- *
- @if $m2c_data_transient != 0@ # persistent
- * More Details
- * ------------
- @ if $m2c_data_transient == 1@ # short term
- * Since your data is semi-TRANSIENT data, you could just keep a pointer
- * to the data in the loop reference. The data should then be copied in
- * ${context}_loop_get_data().
- @ else@ # $m2c_data_transient == 2@ # copy immediately
- * One idea would be to copy it space allocated in the loop reference
- * structure. Another would be to simply have a pointer in the loop
- * reference structure, and allocate memory here.
- *
- @ end@
- @end@
- * @param $mfd_aue_param_cmt
- * @param loop_ctx_ref Reference to current loop context.
- * @param save_loop_ctx_ref Reference to a loop context for saving the current
- * position. If reuse is not set or
- * save_loop_ctx_ref->loop_ctx is NULL, allocate
- * a new one. If reuse is set, you may reuse the existing
- * loop_ctx.
- * @param reuse Indicates if an existing save_loop_ctx_ref->loop_ctx
- * may be reused.
- *
- * @retval MFD_SUCCESS : success.
- * @retval MFD_ERROR : error.
- */
- int
- ${context}_loop_save_position($mfd_aue_param_decl,
- ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_loop_ctx *save_loop_ctx_ref,
- int reuse)
- {
- DEBUGMSGTL(("verbose:${context}:${context}_loop_save_position","calledn"));
- netsnmp_assert(loop_ctx_ref && save_loop_ctx_ref);
- /*
- * TODO:
- * 1) allocate new loop context, unless you can reuse a previous pointer.
- * 2) save information for the position of loop_ctx_ref in save_loop_ctx_ref.
- */
- if((0 == reuse) || (NULL == save_loop_ctx_ref->loop_ctx))
- save_loop_ctx_ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
- if(NULL == save_loop_ctx_ref->loop_ctx) {
- snmp_log(LOG_ERR, "could not allocate memoryn");
- return MFD_ERROR;
- }
- /*
- * if you can reuse a previously saved contex, just swap
- * it out with the loop iterator
- */
- if(reuse && save_loop_ctx_ref->loop_ctx->rowreq_ctx) {
- ${context}_rowreq_ctx * tmp_rowreq_ctx = save_loop_ctx_ref->loop_ctx->rowreq_ctx;
- save_loop_ctx_ref->loop_ctx->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
- loop_ctx_ref->loop_ctx->rowreq_ctx = tmp_rowreq_ctx;
- }
- else {
- /*
- * take the current pointer
- */
- save_loop_ctx_ref->loop_ctx->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
- /*
- * allocate a new context to replace the one you just took.
- */
- @ eval $m2c_tmp = ""@
- @ if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
- @ eval $m2c_tmp = "NULL"@
- @ if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
- @ eval $m2c_tmp = "$m2c_tmp, NULL"@
- @ @end@
- @ end@
- loop_ctx_ref->loop_ctx->rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
- if(NULL == loop_ctx_ref->loop_ctx->rowreq_ctx) {
- SNMP_FREE(loop_ctx_ref->loop_ctx);
- return MFD_ERROR;
- }
- }
- @if $m2c_data_transient == 0@ # persistent
- /** non-TRANSIENT data: no need to copy */
- @elsif $m2c_data_transient == 1@ # short term
- /** semi-TRANSIENT data: will copy data when index found */
- /** only need to copy pertinent data from loop context */
- @elsif $m2c_data_transient == 2@ # copy immediately
- /*
- * TRANSIENT data: copy all the data.
- */
- @end@
- @if $m2c_include_examples == 1@
- $example_start
- @ if $m2c_data_transient == 1@ # short term
- /** save line to do that */
- memcpy(save_loop_ctx_ref->loop_ctx->line, loop_ctx_ref->loop_ctx->line,
- sizeof(loop_ctx_ref->loop_ctx->line));
- @ elsif $m2c_data_transient == 2@ # copy immediately
- @ foreach $node nonindex@
- @ include m2c_setup_node.m2i@
- /*
- * TODO:
- * set rowreq_ctx_ref->${m2c_data_item}$node
- * from the loop context
- */
- @ end@
- @ end@
- $example_end
- @end@ # example
- return MFD_SUCCESS;
- } /* ${context}_loop_save_position */
- @if $m2c_data_transient != 0@ # semi-transient
- /**
- * set ${context}_data from a data context
- *
- * Summary
- * -------
- * At the end of the loop, when the best match has been found, the saved
- * loop context will be used to get the data for the row by calling
- * ${context}_loop_get_data().
- *
- * You should return a fully populated row request context in
- * rowreq_ctx_ref->rowreq_ctx.
- *
- * More Details
- * ------------
- * @param $mfd_aue_param_cmt
- * @param loop_ctx_ref pointer to your loop reference.
- * @param rowreq_ctx_ref pointer to a context reference.
- */
- int
- ${context}_loop_get_data( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref,
- ${context}_ref_rowreq_ctx *rowreq_ctx_ref)
- {
- DEBUGMSGTL(("verbose:${context}:${context}_loop_get_data","calledn"));
- netsnmp_assert((NULL != loop_ctx_ref) && (NULL != loop_ctx_ref->loop_ctx));
- netsnmp_assert(NULL != rowreq_ctx_ref);
- netsnmp_assert(NULL != rowreq_ctx_ref->rowreq_ctx);
- /*
- * take temporary row request context from loop context
- */
- rowreq_ctx_ref->rowreq_ctx = loop_ctx_ref->loop_ctx->rowreq_ctx;
- loop_ctx_ref->loop_ctx->rowreq_ctx = NULL;
- /*
- * copy data to the data context (rowreq_ctx_ref->${m2c_data_item})
- @ if $m2c_include_examples == 1@
- * in loop_save_position, we saved line to do that
- @ end@
- */
- @ foreach $node nonindex@
- @ include m2c_setup_node.m2i@
- /*
- * $m2c_node_summary
- */
- @ eval $m2c_ctx_lh = "rowreq_ctx_ref->$m2c_ctx_rh"@
- @ eval $m2c_ctx_lhs = "rowreq_ctx_ref->$m2c_ctx_rhs"@
- @ eval $m2c_ctx_rh = "loop_ctx_ref->loop_ctx->$node"@
- @ eval $m2c_ctx_rhs = "loop_ctx_ref->loop_ctx->${node}_len"@
- @ include generic-value-map.m2i@
- @ end@
- return MFD_SUCCESS;
- } /* ${context}_loop_get_data */
- @end@ // if $m2c_data_transient != 0
- /**
- * clean up a loop reference
- *
- * Summary
- * -------
- * This function will be called once the loop iteration has completed
- * to release any memory or resources allocated for the loop context.
- *
- * More Details
- * ------------
- * @param $mfd_aue_param_cmt
- * @param loop_ctx_ref Pointer to your loop reference.
- *
- * @retval MFD_SUCCESS : success.
- * @retval MFD_ERROR : error.
- */
- int
- ${context}_loop_cleanup_context( $mfd_aue_param_decl, ${context}_ref_loop_ctx *loop_ctx_ref)
- {
- DEBUGMSGTL(("verbose:${context}:${context}_loop_cleanup_context","calledn"));
- netsnmp_assert(loop_ctx_ref);
- if(!loop_ctx_ref->loop_ctx)
- return MFD_ERROR;
- /*
- * release the row request context, if it wasn't taken
- */
- if(loop_ctx_ref->loop_ctx->rowreq_ctx)
- ${context}_release_rowreq_ctx(loop_ctx_ref->loop_ctx->rowreq_ctx);
- /*
- * TODO:
- * release resources
- */
- @if $m2c_include_examples == 1@
- $example_start
- /*
- * close file
- */
- if(loop_ctx_ref->loop_ctx->filep)
- fclose(loop_ctx_ref->loop_ctx->filep);
- $example_end
- @end@
- /*
- * free loop context
- */
- free(loop_ctx_ref->loop_ctx);
- return MFD_SUCCESS;
- } /* ${context}_loop_cleanup_context */
- @end@ // m2c_processing_type eq 'c'
- ########################################################################
- ##//####################################################################
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- ##//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- @if $m2c_processing_type eq 'r'@
- ##
- unsorted-external summary
- -------------------------
- The unsorted-external data access code is for cases when you data is
- kept UNSORTED and EXTERNAL to the agent/sub-agent.
- This code was generated based on the following assumptions or settings:
- 1) The raw data for this table is UNSORTED.
- @if $mfd_readme_verbose != 0@
- UNSORTED data is data that is not kept in the same order as the way
- SNMP expects the index(es) for the table to be kept. [It could very
- well be sorted in some other order, but for the purpose of SNMP, the
- order is incorrect.] If you're not sure if your data is sorted
- in an SNMP compliant way, its likely not.
- Because the raw data is unsorted, to satisfy a particular request, the
- entire data set must be examined to find the apropriate index. This
- is done via a simple loop. The MFD handler will call your get_first
- function and the call the get_next function repeatedly, until it
- returns SNMPERR_NO_VARS.
- @end@
- 2) The raw data for this table is EXTERNAL.
- @if $mfd_readme_verbose != 0@
- EXTERNAL data is data that is owned by some other process,
- device, file or mechanism. The agent must use some interface to
- read or modify the data. An external process may modify the data
- without the agent's knowledge. For example, the Net-SNMP agent
- implements the interface table (ifTable), which reports on
- network interfaces. The host operating system owns this data, and
- Net-SNMP must use system calls to report or manipulate the data.
- Examples of external data include data stored in kernel space, in
- files, in another non-memory shared process, and data stored in
- devices.
- @end@
- 3) The raw data for this table is TRANSIENT.
- @if $mfd_readme_verbose != 0@
- TRANSIENT data is data that may be overwritten by another funtion
- or process. For example, many OS functions return data in a
- static buffer that will be reused the next time the function is
- called. Because of this, we will assume that you will copy the
- raw data retrieved from these other sources to a generated
- structure for use within the Net-SNMP agent. (Don't worry, we'll
- help you)
- @end@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- The unsorted external data access code works by calling a few simple
- functions to get the index value for each row. Once the agent determines
- which row is needed to process an incoming request, another function
- is called to retrieve the data for that row.
- A simplified version of the pseudo-code looks like this:
- ${context}_loop_init_context(loop)
- ${context}_loop_get_first(loop,data)
- while( no_error ) {
- if( best_match(data, key)
- ${context}_loop_save_position(loop,pos);
- ${context}_loop_get_next(loop,data)
- }
- ${context}_loop_get_data(pos,data)
- ${context}_loop_cleanup_context(loop)
- ##
- ## end sync
- ##
- We will talk about each individual step below.
- ########################################################################
- Defining context for the loop
- -----------------------------
- TODO : typedef ${context}_loop_context
- WHERE: ${table}_data_access.h
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- Since the actual loop is in the MFD handler, a loop contex parameter
- is provided to help you keep track of where you are in between calls
- to functions that you wrote and the master MFD handler calls. The
- structure of this context is user defineable, and is defined in the
- file ${table}_data_access.h.
- E.G., if your data is stored in a linked list, the obvious thing you
- want to know from one function call to the next is your current
- position in the linked list. Thus the easiest context to use is a
- pointer within the linked list. For an array, the current index to
- that array would be easiest.
- The funtion calls are actually passed a reference to the loop
- context, to allow the loop context to be allocated memory. Here are
- some simple examples definitions for various data formats. These
- definitions are used in examples later on.
- ##
- ## end sync
- ##
- Linked list
- -----------
- typedef list_node ${context}_loop_context;
- Array
- -----
- typedef integer ${context}_loop_context;
- File
- ----
- typedef struct ${context}_loop_context_s {
- char * file_name;
- FILE * f;
- char line[128];
- } ${context}_loop_context;
- @end@
- ########################################################################
- Initialization
- --------------
- TODO : Initialization
- FUNC : ${context}_loop_init_data
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- The ${context}_loop_init_data function will be called during startup to
- allow for any initialization needed for the data access routines.
- @end@
- ########################################################################
- Preparing for the loop
- ----------------------
- TODO : initialize loop context
- FUNC : ${context}_loop_init_context
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- This function will be called before the start of a new itertion over
- the data. The loop context that is initialized here will be passed to
- ${context}_loop_get_first and ${context}_loop_get_next.
- Set the loop context variable ref->loop_ctx so that the iteration
- functions (get_first and get_next) can locate the apropriate data
- context.
- ##
- ## end sync
- ##
- The primary purpose of the loop_init_context call is to initialize
- the loop context data (ref). Here are some simple examples, based on the
- earlier example loop contexts.
- Linked list
- -----------
- ref->loop_ctx = my_table_head_ptr;
- Array
- -----
- /* instead of actually allocating memory, just use the pointer */
- /* as an integer */
- (integer)(ref->loop_ctx) = 0;
- File
- ----
- ref->loop_ctx = SNMP_MALLOC_TYPEDEF(${context}_loop_context);
- /* error checking here */
- ref->loop_ctx->file_name = (char*) reg->mfd_user_ctx;
- ref->loop_ctx->f = fopen( ref->loop_ctx->file_name, "r+" );
- @end@
- ########################################################################
- The Loop
- --------
- TODO : return raw data
- FUNC : ${context}_loop_get_first
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- This function is called to return set the index(es) for the first
- ${context}_data in the data set.
- Note that during the loop, the only important thing is the indexes.
- If access to your data is cheap/fast (e.g. you have a pointer to a
- structure in memory), it would make sense to update the data here.
- If, however, the accessing the data invovles more work (e.g. parsing
- some other existing data, or peforming calculations to derive the data),
- then you should limit yourslef to setting the indexes. Extracting the
- can be put off until the desired row is found See the notes on
- ${context}_loop_get_data().
- Note that this function does not correspond to a SNMP GET pdu, and
- you should return data items in whatever order they are already in.
- (In fact, if your data is already ordered in the same order as the
- SNMP indexes, you shouldn't be using the unsorted-access code).
- This function should update the table index (rowreq_ctx_ref->rowreq_ctx->tbl_idx)
- values for the raw data (rowreq_ctx_ref->rowreq_ctx->data).
- ##
- ## end sync
- ##
- Linked list
- -----------
- rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx;
- Array
- -----
- /* assuming registration has array of pointers */
- rowreq_ctx_ref->rowreq_ctx->data = reg->mfd_user_ctx[(integer)(ref->loop_ctx)];
- File
- ----
- fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
- loop_ctx_ref->loop_ctx->f);
- rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx->line;
- @end@
- TODO : return raw data
- FUNC : ${context}_loop_get_next
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- This function returns the next data item in the data set. The same
- caveat applies here as did above. The indexes are the important parts
- during loop processing.
- Note that this function does not correspond to a SNMP GET-NEXT pdu, and
- you should return data items in whatever order they are already in.
- (In fact, if your data is already ordered in the same order as the
- SNMP indexes, you shouldn't be using the unsorted-access code).
- ##
- ## end sync
- ##
- Linked list
- -----------
- loop_ctx_ref->loop_ctx = loop_ctx_ref->loop_ctx->next;
- rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx;
- Array
- -----
- ++((integer)(ref->loop_ctx));
- /* assuming registration has array of pointers */
- rowreq_ctx_ref->rowreq_ctx->data = reg->mfd_user_ctx[(integer)(ref->loop_ctx)];
- File
- ----
- fgets(loop_ctx_ref->loop_ctx->line, sizeof(loop_ctx_ref->loop_ctx->line),
- loop_ctx_ref->loop_ctx->f);
- rowreq_ctx_ref->rowreq_ctx->data = loop_ctx_ref->loop_ctx->line;
- @end@
- ########################################################################
- Updating the Index
- ------------------
- TODO : update index for the raw data
- FUNC : ${context}_indexes_set
- WHERE: ${table}_data_access.c
- This is a convenience function for setting the index context from
- the native C data. Where necessary, value mapping should be done.
- @if $mfd_readme_verbose == 1@
- This function should update the table index values (found in
- tbl_idx) for the given raw data.
- @end@
- ########################################################################
- Saving a position in the loop
- -----------------------------
- TODO : Saving a position in the loop
- FUNC : ${context}_loop_save_position
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- During loop iteration, the iterator keeps track of the row that
- is the current best match. This function is called when the
- current row is a better match than any previous row.
- You should save any information you need to be able to locate this row
- again from the current loop context to a new loop context.
- At the end of the loop, when the best match has been found, the saved
- loop context will be used to get the data for the row by calling
- ${context}_loop_get_data().
- @if $m2c_data_transient != 0@ # persistent
- Since your data is transient, you need to make a copy of it before
- the iterator moves on to the next row.
- @end@
- ##
- ## end sync
- ##
- @end@
- ########################################################################
- Returning Data For an Index
- ---------------------------
- TODO : copy transient raw data to generated structure
- FUNC : ${context}_loop_get_data
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- At the end of the loop, when the best match has been found, the saved
- loop context will be used to get the data for the row by calling
- ${context}_loop_get_data().
- ##
- ## end sync
- ##
- @end@
- ########################################################################
- Cleaning up after the loop
- --------------------------
- TODO : release any allocated memory
- FUNC : ${context}_loop_cleanup_context
- WHERE: ${table}_data_access.c
- @if $mfd_readme_verbose != 0@
- ##
- ## this should be syncronized with master version of comments in
- ## mfd-access-unsorted-external-body.m2i You should be able to copy
- ## the comments here and replace " * " with " ".
- ##
- This function will be called once the loop iteration has completed
- to release any memory allocated for loop reference.
- ##
- ## end sync
- ##
- The purpose of the loop_cleanup_context call is to release any memory
- allocated for the loop context data. Here are some simple examples, based
- on the earlier example loop contexts.
- Linked list
- -----------
- /* nothing to do */
- Array
- -----
- /* nothing to do */
- File
- ----
- free(ref->loop_ctx);
- @end@
- ##
- @end@ // m2c_processing_type eq 'r
- ########################################################################
- @if $m2c_mark_boundary == 1@
- /** END code generated by $RCSfile: mfd-access-unsorted-external-defines.m2i,v $ $Revision: 1.12 $ */
- @end@