/*
 * 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();
}

extern oid      hrSWRunTable_oid[];
extern size_t   hrSWRunTable_oid_len;

/** 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;
    netsnmp_table_registration_info *table_info;

    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);
}

/** 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;
}
