F
/*
 * Note: this file originally auto-generated by mib2c using
 *        : mib2c.access_functions.conf,v 1.9 2004/10/14 12:57:33 dts12 Exp $
 */

#include <assert.h>

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "test_handlerTable.h"
#include "cfgmon.h"

//This is arbitrary, memory is malloc'd during the parse
#define TABLE_CAPACITY 1024

#define TEST_LENGTH1     5
#define TEST_LENGTH2 5
#define SNMP_DATE_TIME_LENGTH      11

static u_int modify_time    = 0;


/*************************************************************************
*
* DESCRIPTION:
*       This loads the container via a call to CFGMON on demand
*
* CATEGORY      NAME    IN/OUT  TYPE                Description
* --------      ----    ------  ----                -----------
* PARAM         cache   IN      netsnmp_cache *     contains details about cache params, not cahce data
*                                                   all cache data is file local
* PARAM         vmagic  IN      void *              user pointer for general use
*
* RETURN                OUT     int                 snmp error code,
*                                                   SNMP_ERR_NOERROR(0) is success
*
* NOTES:
*       This is called by the SNMP library to load up the table into cache memory (local)
*       This is timed by the library and will be reloaded after TABLE_TIMEOUT (.h file)
*       seconds if needed
*
*       This is always called before any get/set routine
*
*************************************************************************/
int test_handlerTable_load(netsnmp_cache * cache, void *vmagic)
{
    t_SYS_ERR_ENUM err;

    err = CFGMON_cache_load(CFGMON_FILE_TYPE_FOO1);

    if (err == SUCCESS)
        err = CFGMON_cache_load(CFGMON_FILE_TYPE_FOO2);

    if (err != SUCCESS)
        return SNMP_ERR_RESOURCEUNAVAILABLE;

    return SNMP_ERR_NOERROR;
}

/*************************************************************************
*
* DESCRIPTION:
*       This frees the container memory using CFGMON - actually does nothing
*
* CATEGORY      NAME    IN/OUT  TYPE                Description
* --------      ----    ------  ----                -----------
* PARAM         cache   IN      netsnmp_cache *     contains details about cache params, not cahce data
*                                                   all cache data is file local
* PARAM         vmagic  IN      void *              user pointer for general use
*
* RETURN        None
*
* NOTES:
*
*************************************************************************/
void test_handlerTable_free(netsnmp_cache * cache, void *vmagic)
{
}


/*************************************************************************
* DESCRIPTION:
*       This returns the first row in the table.
*
* CATEGORY      NAME    IN/OUT          TYPE                        Description
* --------      ----    ------          ----                        -----------
* PARAM         my_loop_context IN/OUT  void **                     Info about where in the iteration we are, index here
* PARAM         my_data_context IN      void **                     pointer to the row requested, or NULL if none
* PARAM         put_index_data  OUT     netsnmp_variable_list *     snmp index for the row selected
* PARAM         mydata          IN/OUT  netsnmp_iterator_info *     set to something you may need later
*
* RETURN                        OUT     netsnmp_variable_list *     snmp index for the row selected
*
* NOTES:
*   first and next are very close so we call next with NULLs in the
*   control variables
*
*   Set the my_loop_context variable to the first data point structure
*   of your choice (from which you can find the next one).  This could
*   be anything from the first node in a linked list, to an integer
*   pointer containing the beginning of an array variable.
*
*   Set the my_data_context variable to something to be returned to
*   you later that will provide you with the data to return in a given
*   row.  This could be the same pointer as what my_loop_context is
*   set to, or something different.
*
*   The put_index_data variable contains a list of snmp variable
*   bindings, one for each index in your table.  Set the values of
*   each appropriately according to the data matching the first row
*   and return the put_index_data variable at the end of the function.
*
*************************************************************************/
netsnmp_variable_list *test_handlerTable_get_first_data_point(void **my_loop_context,
                                                              void **my_data_context,
                                                              netsnmp_variable_list *put_index_data, 
															  netsnmp_iterator_info * mydata)
{
    *my_loop_context = NULL;
    *my_data_context = NULL;

    return test_handlerTable_get_next_data_point(my_loop_context, my_data_context, put_index_data, mydata);
}

/*************************************************************************
* DESCRIPTION:
*       This returns the next row in the table.
*
* CATEGORY      NAME    IN/OUT          TYPE                        Description
* --------      ----    ------          ----                        -----------
* PARAM         my_loop_context IN/OUT  void **                     Info about where in the iteration we are, index here
* PARAM         my_data_context IN      void **                     pointer to the row requested, or NULL if none
* PARAM         put_index_data  OUT     netsnmp_variable_list *     snmp index for the row selected
* PARAM         mydata          IN/OUT  netsnmp_iterator_info *     set to something you may need later
*
* RETURN                        OUT     netsnmp_variable_list *     snmp index for the row selected
*
* NOTES:
*   functionally the same as X_get_first_data_point, but
*   my_loop_context has already been set to a previous value and should
*   be updated to the next row.
*
*************************************************************************/
netsnmp_variable_list *test_handlerTable_get_next_data_point(void **my_loop_context,
                                                              void **my_data_context,
                                                              netsnmp_variable_list *put_index_data,
                                                              netsnmp_iterator_info * mydata)
{
    netsnmp_variable_list *vptr;
    t_CFGMON_TEST_STRUCT *curr;

    char encodedstr[18]; //no NULL termination

    if (*my_data_context == NULL)
        curr = (t_CFGMON_TEST_STRUCT *)CFGMON_get_list_head(CFGMON_FILE_TYPE_FOO2);  //the first row

    else
    {
        curr = (t_CFGMON_TEST_STRUCT *)(*my_data_context);     //the next
        curr = curr->next;
    }

    *my_data_context = (void *)curr;

    //are there any more rows?
    if (curr == NULL)
        return NULL;

    vptr = put_index_data;



	//This works great



    //we need to not encode the length of this octet string - it is fixed at 18 bytes
    CFGMON_encode_string_value(curr->string_value, encoded_string);
    snmp_set_var_value(vptr, (u_char *)encoded_str, 18);

    vptr = vptr->next_variable;
    //we need to not encode the length of this octet string - it is fixed at 5 bytes
    snmp_set_var_value(vptr, (u_char *)curr->array2, TEST_LENGTH1);

    vptr = vptr->next_variable;
    snmp_set_var_value(vptr, (u_char *)&curr->int_value, sizeof(UINT32));

    return put_index_data;
}

/*************************************************************************
* DESCRIPTION:
*       This create a holding place for new data before it gets committed to the table
*
* CATEGORY      NAME        IN/OUT  TYPE                        Description
* --------      ----        ------  ----                        -----------
* PARAM         index_data  IN      netsnmp_variable_list *     snmp index of new row
* PARAM         column      IN      int                         column that triggered row creation
*
* RETURN                        OUT     void *                  pointer to new data context just created
*
* NOTES:
*
*  Should never be called - we can not add new rows, only zeroize an existing one
*
**************************************************************************/
void *test_handlerTable_create_data_context(netsnmp_variable_list * index_data, int column)
{
    snmp_log(LOG_ERR, "%s: operation not supported\n", __func__);
    return NULL;
}

/*************************************************************************
* DESCRIPTION:
*       This writes the row changes into the table and then to persistent memory (File)
*
* CATEGORY      NAME        IN/OUT  TYPE            Description
* --------      ----        ------  ----            -----------
* PARAM         my_data_context IN      void **     snmp index of new row (cast to t_CFGMON_RULE_INFO *)
* PARAM         new_or_del      IN      int         operation defined
*                                                    1 = new row
*                                                    0 = modified existing row
*                                                   -1 = deleted row
*
* RETURN                        OUT     int         snmp error code - Library probably won't tolerate ERRORs
*
* NOTES:
*
* If the implemented set_* functions don't operate directly on the
   real-live data (which is actually recommended), then this function
   can be used to take a given my_data_context pointer and "commit" it
   to whereever the modified data needs to be put back to.  For
   example, if this was a routing table you could publish the modified
   routes back into the kernel at this point.

   new_or_del will be set to 1 if new, or -1 if it should be deleted
   or 0 if it is just a modification of an existing row.

   If you free the data yourself, make sure to *my_data_context = NULL
**************************************************************************/
int test_handlerTable_commit_row(void **my_data_context, int new_or_del)
{
    t_SYS_ERR_ENUM     err       = SUCCESS;
    t_CFGMON_DATA_CONTAINER *container;

    container = CFGMON_get_container_reference(CFGMON_FILE_TYPE_FOO2);

    switch (new_or_del)
    {
        case 1:     //NEW row, add this new row to the container, then write
            snmp_log(LOG_DEBUG, "test_handlerTable_commit_row(): Can not add NEW row\n");
            return SNMP_ERR_COMMITFAILED;

        case 0:   
            break;

        case -1:    //DESTROY row, The row was marked inactive
            snmp_log(LOG_DEBUG, "test_handlerTable_commit_row(): can not DESTROY a row\n");
            return SNMP_ERR_COMMITFAILED;

        default:
            SYS_ASSERT(new_or_del >= -1 && new_or_del <= 1);
            break;
    }

    //nothing else we can do here if there is any failure
    //memory owned by the container now or was handled - snmp should not see this address anymore
    *my_data_context = NULL;

    if (err != SUCCESS)
        return SNMP_ERR_RESOURCEUNAVAILABLE;        //not much we can do except report it

    modify_time = (u_int)netsnmp_get_agent_uptime();

    //this will cause a write from the outgoing snmp_agent.c handler
    CFGMON_set_container_dirty(container);

    return SNMP_ERR_NOERROR;
}







/*************************************************************************
* DESCRIPTION:
*       This following routines GET the values requested from the row in the
*       table passed in data_context
*
* CATEGORY      NAME            IN/OUT  TYPE        Description
* --------      ----            ------  ----        -----------
* PARAM         data_context    IN      u_int *     row to extract the column from
* PARAM         ret_len         OUT     size_t *    return data size
*
* Return                        OUT     long        The column requested
*
* NOTES: Less optimized coding here to prevent compiler warnings
*
*   Any get_ routines MUST return data that will not be freed (ie,
*   use static variables or persistent data).  It will be copied, if
*   needed, immediately after the get_routine has been called.
*
*   Any SET routines must copy the incoming data and can not take
*   ownership of the memory passed in by the val pointer.
*
*************************************************************************/

char *get_TEST_str1(void *data_context, size_t * ret_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;
    static char encoded_str[CFGMON_MAX_PACKED_SHORT_TITLE_LENGTH];

    CFGMON_encode_string_value(info->string_value, encoded_str);

    *ret_len = 18;

    return encoded_str;
}

char *get_TEST_Edition(void *data_context, size_t * ret_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;
    static char arr[5];

    memcpy(arr, info->arr, 5);


    *ret_len = 5;

    return arr;
}

u_long *get_TEST_int_value(void *data_context, size_t * ret_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;
    static u_long ret_val;

    ret_val  = (u_long)(info->int_value);
    *ret_len = sizeof(u_long);

    return &ret_val;;
}


long *get_TEST_UsageType(void *data_context, size_t * ret_len)
{
    static long ret_val;
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;

    ret_val = info->usage;

    *ret_len = sizeof(ret_val);

    return &ret_val;
}


//can only allow unassigned->new value, see checkfns.c
int set_TEST_UsageType(void *data_context, long *val, size_t val_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;

    info->usage = *val;

    return SNMP_ERR_NOERROR;
}

char *get_TEST_Date(void *data_context, size_t * ret_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;
    static char buffer[SNMP_DATE_TIME_LENGTH];

    short year = htons((short)info->year);

    memset(buffer, 0, SNMP_DATE_TIME_LENGTH);
    memcpy(&buffer[0], &year, sizeof(short));
    memcpy(&buffer[2], &info->month, 1);
    memcpy(&buffer[3], &info->day,   1);

    *ret_len = SNMP_DATE_TIME_LENGTH;

    return buffer;

}

long *get_TEST_foo(void *data_context, size_t * ret_len)
{
    t_CFGMON_TEST_STRUCT *info = (t_CFGMON_TEST_STRUCT *)data_context;
    static long ret_val;

    ret_val = (long)info->foo;
    *ret_len = sizeof(long);

    return &ret_val;
}

