/*
 * Note: this file originally auto-generated by mib2c using
 *  : mib2c.container.conf,v 1.8 2006/07/26 15:58:26 dts12 Exp $
 */
/* Portions of this file are subject to the following copyright(s).  See
 * the Net-SNMP's COPYING file for more details and other copyrights
 * that may apply:
 */
/*
 * Portions of this file are copyrighted by:
 * Copyright (C) 2007 Apple, Inc. All rights reserved.
 * Use is subject to license terms specified in the COPYING file
 * distributed with the Net-SNMP package.
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/data_access/swrun.h>
#include "hrSWRunPerfTable.h"
#include "data_access/swrun.h"

#define MYTABLE "hrSWRunPerfTable"

/** Initializes the hrSWRunPerfTable module */
void
init_hrSWRunPerfTable(void)
{
    /*
     * here we initialize all the tables we're planning on supporting 
     */
    initialize_table_hrSWRunPerfTable();
}

void
shutdown_hrSWRunPerfTable(void)
{
    shutdown_table_hrSWRunPerfTable();
}

extern oid      hrSWRunTable_oid[];
extern size_t   hrSWRunTable_oid_len;
static netsnmp_table_registration_info *table_info;

/** Initialize the hrSWRunPerfTable table by defining its contents and how it's structured */
void
initialize_table_hrSWRunPerfTable(void)
{
    static oid      hrSWRunPerfTable_oid[] =
        { 1, 3, 6, 1, 2, 1, 25, 5, 1 };
    size_t          hrSWRunPerfTable_oid_len =
        OID_LENGTH(hrSWRunPerfTable_oid);
    netsnmp_handler_registration *reg;
    netsnmp_mib_handler *handler = NULL;

    reg =
        netsnmp_create_handler_registration("hrSWRunPerfTable",
                                            hrSWRunPerfTable_handler,
                                            hrSWRunPerfTable_oid,
                                            hrSWRunPerfTable_oid_len,
                                            HANDLER_CAN_RONLY);
    if (NULL == reg) {
        snmp_log(LOG_ERR,"error creating handler registration for "
                 MYTABLE "\n");
        goto bail;
    }

    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
    if (NULL == table_info) {
        snmp_log(LOG_ERR,"error allocating table registration for "
                 MYTABLE "\n");
        goto bail;
    }
    netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER,   /* index: hrSWRunIndex */
                                     0);
    table_info->min_column = COLUMN_HRSWRUNPERFCPU;
    table_info->max_column = COLUMN_HRSWRUNPERFMEM;

    /*************************************************
     *
     * inject container_table helper
     */
    handler = netsnmp_container_table_handler_get(table_info, netsnmp_swrun_container(),
                                                  TABLE_CONTAINER_KEY_NETSNMP_INDEX);
    if (NULL == handler) {
        snmp_log(LOG_ERR,"error allocating table registration for "
                 MYTABLE "\n");
        goto bail;
    }
    if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
        snmp_log(LOG_ERR,"error injecting container_table handler for "
                 MYTABLE "\n");
        goto bail;
    }
    handler = NULL; /* reg has it, will reuse below */

    /*************************************************
     *
     * inject cache helper
     */

    handler = netsnmp_cache_handler_get(netsnmp_swrun_cache());
    if (NULL == handler) {
        snmp_log(LOG_ERR, "error creating cache handler for " MYTABLE "\n");
        goto bail;
    }

    if (SNMPERR_SUCCESS != netsnmp_inject_handler(reg, handler)) {
        snmp_log(LOG_ERR,"error injecting cache handler for "
                 MYTABLE "\n");
        goto bail;
    }
    handler = NULL; /* reg has it*/

    if (SNMPERR_SUCCESS != netsnmp_register_table(reg, table_info)) {
        snmp_log(LOG_ERR,"error registering table handler for "
                 MYTABLE "\n");
        reg = NULL; /* it was freed inside netsnmp_register_table */
        goto bail;
    }

    return; /* ok */


  bail: /* not ok */
    
    if (handler)
        netsnmp_handler_free(handler);

    if (table_info)
        netsnmp_table_registration_info_free(table_info);

    if (reg) 
        netsnmp_handler_registration_free(reg);
}

void
shutdown_table_hrSWRunPerfTable(void)
{
    if (table_info) {
	netsnmp_table_registration_info_free(table_info);
	table_info = NULL;
    }
}

/** handles requests for the hrSWRunPerfTable table */
int
hrSWRunPerfTable_handler(netsnmp_mib_handler *handler,
                         netsnmp_handler_registration *reginfo,
                         netsnmp_agent_request_info *reqinfo,
                         netsnmp_request_info *requests)
{

    netsnmp_request_info *request;
    netsnmp_table_request_info *table_info;
    netsnmp_swrun_entry *table_entry;

    switch (reqinfo->mode) {
        /*
         * Read-support (also covers GetNext requests)
         */
    case MODE_GET:
        for (request = requests; request; request = request->next) {
            if (request->processed)
               continue;
            table_entry = (netsnmp_swrun_entry *)
                netsnmp_container_table_extract_context(request);
            table_info = netsnmp_extract_table_info(request);
            if ((NULL == table_entry) || (NULL == table_info)) {
                snmp_log(LOG_ERR, "could not extract table entry or info for "
                 MYTABLE "\n");
                snmp_set_var_typed_value(request->requestvb,
                                         SNMP_ERR_GENERR, NULL, 0);
                continue;
            }

            switch (table_info->colnum) {
            case COLUMN_HRSWRUNPERFCPU:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->hrSWRunPerfCPU);
                break;
            case COLUMN_HRSWRUNPERFMEM:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->hrSWRunPerfMem);
                break;
            default:
                /*
                 * An unsupported/unreadable column (if applicable) 
                 */
                snmp_set_var_typed_value(request->requestvb,
                                         SNMP_NOSUCHOBJECT, NULL, 0);
            }
        }
        break;

    }
    return SNMP_ERR_NOERROR;
}
