/*--------------------------------------------------------------------------+
| Edition History:                                                          |
| #   Date     Comments                                                 By  |
| --- -------- -------------------------------------------------------- --- |
|   1 07/05/18 Created.                                                 emi |
+--------------------------------------------------------------------------*/
/*
 * Note: this file originally auto-generated by mib2c using
 *  : mib2c.table_data.conf,v 1.11.2.1 2006/01/11 15:17:47 dts12 Exp $
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-features.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "utilities/iquery.h"
#include "alarmTable.h"

netsnmp_feature_require(iquery)
netsnmp_feature_require(query_set_default_session)
netsnmp_feature_require(table_tdata)
netsnmp_feature_require(check_vb_type_and_max_size)
netsnmp_feature_require(table_tdata_extract_table)
#ifndef NETSNMP_NO_WRITE_SUPPORT
netsnmp_feature_require(table_tdata_insert_row)
netsnmp_feature_require(iquery_pdu_session)
#endif /* NETSNMP_NO_WRITE_SUPPORT */

/** Initializes the alarmTable module */
void
init_alarmTable(void)
{
    /*
     * here we initialize all the tables we're planning on supporting 
     */
    initialize_table_alarmTable();
}

/** Initialize the alarmTable table by defining its contents and how it's structured */
void
initialize_table_alarmTable(void)
{
    static oid      alarmTable_oid[] = { 1, 3, 6, 1, 2, 1, 16, 3, 1 };
    size_t          alarmTable_oid_len = OID_LENGTH(alarmTable_oid);
    netsnmp_handler_registration *reg;
    netsnmp_tdata  *table_data;
    netsnmp_table_registration_info *table_info;

    DEBUGMSGTL(( "rmon:alarmTable", "initialize_table_alarmTable called.\n"));
    reg =
        netsnmp_create_handler_registration("alarmTable",
                                            alarmTable_handler,
                                            alarmTable_oid,
                                            alarmTable_oid_len,
                                            HANDLER_CAN_RWRITE);

    table_data = netsnmp_tdata_create_table("alarmTable", 0);
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
    netsnmp_table_helper_add_indexes(table_info, ASN_INTEGER,   /* index: alarmIndex */
                                     0);

    table_info->min_column = COLUMN_ALARMINDEX;
    table_info->max_column = COLUMN_ALARMSTATUS;

    netsnmp_tdata_register(reg, table_data, table_info);

    /*
     * Initialise the contents of the table here 
     */
}

extern int
event_api_send_alarm(u_char is_rising,
                     u_long alarm_index,
                     u_long event_index,
                     oid * alarmed_var,
                     size_t alarmed_var_length,
                     u_long sample_type,
                     u_long value,
                     u_long the_threshold, const char *alarm_descr);

#define ALARM_STR1_LEN	32
typedef enum {
    RMON1_ENTRY_VALID = 1,
    RMON1_ENTRY_CREATE_REQUEST,
    RMON1_ENTRY_UNDER_CREATION,
    RMON1_ENTRY_INVALID
} RMON1_ENTRY_STATUS_T;

typedef enum {
    SAMPLE_TYPE_ABSOLUTE =
    1,
    SAMPLE_TYPE_DELTE
} SAMPLE_TYPE_T;

typedef enum {
    ALARM_NOTHING =
    0,
    ALARM_RISING,
    ALARM_FALLING,
    ALARM_BOTH
} ALARM_TYPE_T;
    /*
     * Typical data structure for a row entry 
     */
struct alarmTable_entry {
    /*
     * Index values 
     */
    long            alarmIndex;

    /*
     * Column values 
     */
    long            alarmInterval;
    long            old_alarmInterval;
    oid             alarmVariable[ALARM_STR1_LEN];
    size_t          alarmVariable_len;
    oid             old_alarmVariable[ALARM_STR1_LEN];
    size_t          old_alarmVariable_len;
    long            alarmSampleType;
    long            old_alarmSampleType;
    long            alarmValue;
    long            alarmStartupAlarm;
    long            old_alarmStartupAlarm;
    long            alarmRisingThreshold;
    long            old_alarmRisingThreshold;
    long            alarmFallingThreshold;
    long            old_alarmFallingThreshold;
    long            alarmRisingEventIndex;
    long            old_alarmRisingEventIndex;
    long            alarmFallingEventIndex;
    long            old_alarmFallingEventIndex;
    char            alarmOwner[ALARM_STR1_LEN];
    size_t          alarmOwner_len;
    char            old_alarmOwner[ALARM_STR1_LEN];
    size_t          old_alarmOwner_len;
    long            alarmStatus;
    long            old_alarmStatus;

    int             valid;
    unsigned int    alarm_reg;
    netsnmp_session *session;
    u_long          last_abs_value;
    ALARM_TYPE_T    prev_alarm;        /* NOTHING | RISING | FALLING */
};


void
alarmTable_run( unsigned int reg, void *clientarg)
{
    struct alarmTable_entry *entry = (struct alarmTable_entry *)clientarg;
    netsnmp_variable_list *var;
    u_long new_value;
    int rc;

    if (!entry) {
        snmp_alarm_unregister( reg );
        return;
    }
    /*
     * Retrieve the requested MIB value(s)...
     */
    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_run called\n"));
    var = (netsnmp_variable_list *)SNMP_MALLOC_TYPEDEF( netsnmp_variable_list );
    if (!var) {
        snmp_log(LOG_ERR,"failed to create alarmTable query varbind");
        return;
    }
    snmp_set_var_objid( var, entry->alarmVariable,
                             entry->alarmVariable_len );
    
    rc = netsnmp_query_get(  var, entry->session );
    if ( rc != SNMP_ERR_NOERROR ) {
        DEBUGMSGTL(( "rmon:alarmTable", "alarmVariable query failed (%d)\n", rc));
        snmp_free_varbind(var);
        return;
    }

	switch (var->type) {
    case ASN_INTEGER:
    case ASN_COUNTER:
    case ASN_TIMETICKS:
    case ASN_GAUGE:
    case ASN_COUNTER64:
        new_value = *var->val.integer;
        break;
    default:
        DEBUGMSGTL(("rmon:alarmTable", "invalid type (%d)\n", var->type));
        snmp_free_varbind(var);
        return ;
    }

    DEBUGMSGTL(("rmon:alarmTable", "alarmIndex.%ld last value (%ld)\n", entry->alarmIndex, entry->last_abs_value));
    DEBUGMSGTL(("rmon:alarmTable", "alarmIndex.%ld new_value (%ld)\n", entry->alarmIndex, new_value));

    entry->alarmValue = (SAMPLE_TYPE_ABSOLUTE == entry->alarmSampleType) ?
        new_value : new_value - entry->last_abs_value;
    entry->last_abs_value = new_value;

    if (ALARM_RISING != entry->prev_alarm &&
        entry->alarmValue >= entry->alarmRisingThreshold) {
        if (SNMP_ERR_NOERROR == event_api_send_alarm(1, entry->alarmIndex,
                                                 entry->alarmRisingEventIndex,
                                                 entry->alarmVariable,
                                                 entry->alarmVariable_len,
                                                 entry->alarmSampleType, 
                                                 entry->alarmValue,
                                                 entry->alarmRisingThreshold,
                                                 "Rising"))
            entry->prev_alarm = ALARM_RISING;
        else 
            snmp_log(LOG_ERR,"failed to send rising alarm\n");
    }
    else if (ALARM_FALLING != entry->prev_alarm &&
             entry->alarmValue <= entry->alarmFallingThreshold) {
        if (SNMP_ERR_NOERROR == event_api_send_alarm(0, entry->alarmIndex,
                                                      entry->alarmFallingEventIndex,
                                                      entry->alarmVariable,
                                                      entry->alarmVariable_len, 
                                                      entry->alarmSampleType,
                                                      entry->alarmValue,
                                                      entry->alarmFallingThreshold,
                                                      "Falling"))
            entry->prev_alarm = ALARM_FALLING;
        else 
            snmp_log(LOG_ERR,"failed to send falling alarm\n");
    }
    else
        DEBUGMSGTL(("rmon:alarmTable", "no alarm sent\n"));

    snmp_free_varbind(var);
}

void
alarmTable_enable( struct alarmTable_entry *entry )
{
    if (!entry)
        return;

    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_enable called.\n"));
    if (entry->alarm_reg) {
        snmp_alarm_unregister( entry->alarm_reg );
        entry->alarm_reg = 0;
    }

    if (entry->alarmInterval) {
        /*
         * register once to run ASAP, and another to run
         * at the trigger frequency
         */
        snmp_alarm_register(0, 0, alarmTable_run, entry );
        entry->alarm_reg = snmp_alarm_register(
                           entry->alarmInterval, SA_REPEAT,
                           alarmTable_run, entry );
    }
}

void
alarmTable_disable( struct alarmTable_entry *entry )
{
    if (!entry)
        return;

    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_disable called.\n"));
    if (entry->alarm_reg) {
        snmp_alarm_unregister( entry->alarm_reg );
        entry->alarm_reg = 0;
        /* XXX - perhaps release any previous results */
    }
}

/*
 * create a new row in the table 
 */
netsnmp_tdata_row *
alarmTable_createEntry(netsnmp_tdata * table_data, long alarmIndex)
{
    struct alarmTable_entry *entry;
    netsnmp_tdata_row *row;

    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_createEntry called.\n"));
    entry = SNMP_MALLOC_TYPEDEF(struct alarmTable_entry);
    if (!entry)
        return NULL;

    row = netsnmp_tdata_create_row();
    if (!row) {
        SNMP_FREE(entry);
        return NULL;
    }
    row->data = entry;
    entry->alarmIndex = alarmIndex;
    entry->alarmInterval = 1;
    entry->alarmSampleType = SAMPLE_TYPE_ABSOLUTE;
    entry->alarmStartupAlarm = ALARM_BOTH;
    entry->alarmRisingThreshold = 10;
    entry->alarmFallingThreshold = 5;
    entry->alarmRisingEventIndex = alarmIndex;
    entry->alarmFallingEventIndex = alarmIndex;
    entry->prev_alarm = ALARM_NOTHING;
    netsnmp_tdata_row_add_index(row, ASN_INTEGER,
                                &(entry->alarmIndex),
                                sizeof(entry->alarmIndex));
    netsnmp_tdata_add_row(table_data, row);
    return row;
}

/*
 * remove a row from the table 
 */
void
alarmTable_removeEntry(netsnmp_tdata * table_data, netsnmp_tdata_row * row)
{
    struct alarmTable_entry *entry;

    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_removeEntry called.\n"));
    if (!row)
        return;                 /* Nothing to remove */
    entry = (struct alarmTable_entry *)
        netsnmp_tdata_remove_and_delete_row(table_data, row);
    if (entry) {
        alarmTable_disable(entry);
        SNMP_FREE(entry);       /* XXX - release any other internal resources */
    }
}


/** handles requests for the alarmTable table */
int
alarmTable_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_tdata  *table_data;
    netsnmp_tdata_row *table_row;
    struct alarmTable_entry *table_entry;
    int             ret;
    netsnmp_session *sess = NULL;
    char           *secName;

    DEBUGMSGTL(( "rmon:alarmTable", "alarmTable_handler called.\n"));
    switch (reqinfo->mode) {
        /*
         * Read-support (also covers GetNext requests)
         */
    case MODE_GET:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINDEX:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmIndex);
                break;
            case COLUMN_ALARMINTERVAL:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmInterval);
                break;
            case COLUMN_ALARMVARIABLE:
                snmp_set_var_typed_value(request->requestvb, ASN_OBJECT_ID,
                                         (u_char *) table_entry->
                                         alarmVariable,
                                         table_entry->alarmVariable_len *
                                         sizeof(oid));
                break;
            case COLUMN_ALARMSAMPLETYPE:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmSampleType);
                break;
            case COLUMN_ALARMVALUE:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmValue);
                break;
            case COLUMN_ALARMSTARTUPALARM:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmStartupAlarm);
                break;
            case COLUMN_ALARMRISINGTHRESHOLD:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->
                                           alarmRisingThreshold);
                break;
            case COLUMN_ALARMFALLINGTHRESHOLD:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->
                                           alarmFallingThreshold);
                break;
            case COLUMN_ALARMRISINGEVENTINDEX:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->
                                           alarmRisingEventIndex);
                break;
            case COLUMN_ALARMFALLINGEVENTINDEX:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->
                                           alarmFallingEventIndex);
                break;
            case COLUMN_ALARMOWNER:
                snmp_set_var_typed_value(request->requestvb, ASN_OCTET_STR,
                                         (u_char *) table_entry->
                                         alarmOwner,
                                         table_entry->alarmOwner_len);
                break;
            case COLUMN_ALARMSTATUS:
                snmp_set_var_typed_integer(request->requestvb, ASN_INTEGER,
                                           table_entry->alarmStatus);
                break;
            }
        }
        break;

        /*
         * Write-support
         */
    case MODE_SET_RESERVE1:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMVARIABLE:
                /*
                 * or possibly 'netsnmp_check_vb_type_and_max_size' 
                 */
                break;
            case COLUMN_ALARMSAMPLETYPE:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMSTARTUPALARM:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMRISINGTHRESHOLD:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMFALLINGTHRESHOLD:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMRISINGEVENTINDEX:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMFALLINGEVENTINDEX:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            case COLUMN_ALARMOWNER:
                /*
                 * or possibly 'netsnmp_check_vb_type_and_max_size' 
                 */
                break;
            case COLUMN_ALARMSTATUS:
                /*
                 * or possibly 'netsnmp_check_vb_int_range' 
                 */
                ret = netsnmp_check_vb_int(request->requestvb);
                if (ret != SNMP_ERR_NOERROR) {
                    netsnmp_set_request_error(reqinfo, request, ret);
                    return SNMP_ERR_NOERROR;
                }
                break;
            default:
                netsnmp_set_request_error(reqinfo, request,
                                          SNMP_ERR_NOTWRITABLE);
                return SNMP_ERR_NOERROR;
            }
        }
        break;

    case MODE_SET_RESERVE2:
        for (request = requests; request; request = request->next) {
            table_row = netsnmp_tdata_extract_row(request);
            table_data = netsnmp_tdata_extract_table(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
            case COLUMN_ALARMVARIABLE:
            case COLUMN_ALARMSAMPLETYPE:
            case COLUMN_ALARMSTARTUPALARM:
            case COLUMN_ALARMRISINGTHRESHOLD:
            case COLUMN_ALARMFALLINGTHRESHOLD:
            case COLUMN_ALARMRISINGEVENTINDEX:
            case COLUMN_ALARMFALLINGEVENTINDEX:
            case COLUMN_ALARMOWNER:
            case COLUMN_ALARMSTATUS:
                if (!table_row) {
                    table_row =
                        alarmTable_createEntry(table_data,
                                               *table_info->indexes->val.
                                               integer);
                    if (table_row) {
                        netsnmp_insert_tdata_row(request, table_row);
                    } else {
                        netsnmp_set_request_error(reqinfo, request,
                                                  SNMP_ERR_RESOURCEUNAVAILABLE);
                        return SNMP_ERR_NOERROR;
                    }
                }
                break;
            }
        }
        break;

    case MODE_SET_FREE:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_row = netsnmp_tdata_extract_row(request);
            table_data = netsnmp_tdata_extract_table(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
            case COLUMN_ALARMVARIABLE:
            case COLUMN_ALARMSAMPLETYPE:
            case COLUMN_ALARMSTARTUPALARM:
            case COLUMN_ALARMRISINGTHRESHOLD:
            case COLUMN_ALARMFALLINGTHRESHOLD:
            case COLUMN_ALARMRISINGEVENTINDEX:
            case COLUMN_ALARMFALLINGEVENTINDEX:
            case COLUMN_ALARMOWNER:
            case COLUMN_ALARMSTATUS:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                }
                break;
            }
        }
        break;

    case MODE_SET_ACTION:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
                table_entry->old_alarmInterval =
                    table_entry->alarmInterval;
                table_entry->alarmInterval =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMVARIABLE:
                table_entry->alarmVariable_len =
                    request->requestvb->val_len / sizeof(oid);
                memset(table_entry->alarmVariable, 0,
                       sizeof(table_entry->alarmVariable));
                memcpy(table_entry->alarmVariable,
                       request->requestvb->val.objid,
                       request->requestvb->val_len);
                break;
            case COLUMN_ALARMSAMPLETYPE:
                table_entry->old_alarmSampleType =
                    table_entry->alarmSampleType;
                table_entry->alarmSampleType =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMSTARTUPALARM:
                table_entry->old_alarmStartupAlarm =
                    table_entry->alarmStartupAlarm;
                table_entry->alarmStartupAlarm =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMRISINGTHRESHOLD:
                table_entry->old_alarmRisingThreshold =
                    table_entry->alarmRisingThreshold;
                table_entry->alarmRisingThreshold =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMFALLINGTHRESHOLD:
                table_entry->old_alarmFallingThreshold =
                    table_entry->alarmFallingThreshold;
                table_entry->alarmFallingThreshold =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMRISINGEVENTINDEX:
                table_entry->old_alarmRisingEventIndex =
                    table_entry->alarmRisingEventIndex;
                table_entry->alarmRisingEventIndex =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMFALLINGEVENTINDEX:
                table_entry->old_alarmFallingEventIndex =
                    table_entry->alarmFallingEventIndex;
                table_entry->alarmFallingEventIndex =
                    *request->requestvb->val.integer;
                break;
            case COLUMN_ALARMOWNER:
                memcpy(table_entry->old_alarmOwner,
                       table_entry->alarmOwner,
                       sizeof(table_entry->alarmOwner));
                table_entry->old_alarmOwner_len =
                    table_entry->alarmOwner_len;
                memset(table_entry->alarmOwner, 0,
                       sizeof(table_entry->alarmOwner));
                memcpy(table_entry->alarmOwner,
                       request->requestvb->val.string,
                       request->requestvb->val_len);
                table_entry->alarmOwner_len = request->requestvb->val_len;
                break;
            case COLUMN_ALARMSTATUS:
                table_entry->old_alarmStatus = table_entry->alarmStatus;
                table_entry->alarmStatus =
                    *request->requestvb->val.integer;
                break;
            }
        }
        break;

    case MODE_SET_UNDO:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_row = netsnmp_tdata_extract_row(request);
            table_data = netsnmp_tdata_extract_table(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmInterval =
                        table_entry->old_alarmInterval;
                    table_entry->old_alarmInterval = 0;
                }
                break;
            case COLUMN_ALARMVARIABLE:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    memcpy(table_entry->alarmVariable,
                           table_entry->old_alarmVariable,
                           sizeof(table_entry->alarmVariable));
                    memset(table_entry->old_alarmVariable, 0,
                           sizeof(table_entry->alarmVariable));
                    table_entry->alarmVariable_len =
                        table_entry->old_alarmVariable_len;
                }
                break;
            case COLUMN_ALARMSAMPLETYPE:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmSampleType =
                        table_entry->old_alarmSampleType;
                    table_entry->old_alarmSampleType = 0;
                }
                break;
            case COLUMN_ALARMSTARTUPALARM:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmStartupAlarm =
                        table_entry->old_alarmStartupAlarm;
                    table_entry->old_alarmStartupAlarm = 0;
                }
                break;
            case COLUMN_ALARMRISINGTHRESHOLD:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmRisingThreshold =
                        table_entry->old_alarmRisingThreshold;
                    table_entry->old_alarmRisingThreshold = 0;
                }
                break;
            case COLUMN_ALARMFALLINGTHRESHOLD:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmFallingThreshold =
                        table_entry->old_alarmFallingThreshold;
                    table_entry->old_alarmFallingThreshold = 0;
                }
                break;
            case COLUMN_ALARMRISINGEVENTINDEX:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmRisingEventIndex =
                        table_entry->old_alarmRisingEventIndex;
                    table_entry->old_alarmRisingEventIndex = 0;
                }
                break;
            case COLUMN_ALARMFALLINGEVENTINDEX:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmFallingEventIndex =
                        table_entry->old_alarmFallingEventIndex;
                    table_entry->old_alarmFallingEventIndex = 0;
                }
                break;
            case COLUMN_ALARMOWNER:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    memcpy(table_entry->alarmOwner,
                           table_entry->old_alarmOwner,
                           sizeof(table_entry->alarmOwner));
                    memset(table_entry->old_alarmOwner, 0,
                           sizeof(table_entry->alarmOwner));
                    table_entry->alarmOwner_len =
                        table_entry->old_alarmOwner_len;
                }
                break;
            case COLUMN_ALARMSTATUS:
                if (table_entry && !table_entry->valid) {
                    alarmTable_removeEntry(table_data, table_row);
                } else {
                    table_entry->alarmStatus =
                        table_entry->old_alarmStatus;
                    table_entry->old_alarmStatus = 0;
                }
                break;
            }
        }
        break;

    case MODE_SET_COMMIT:
        for (request = requests; request; request = request->next) {
            table_entry = (struct alarmTable_entry *)
                netsnmp_tdata_extract_entry(request);
            table_info = netsnmp_extract_table_info(request);

            switch (table_info->colnum) {
            case COLUMN_ALARMINTERVAL:
            case COLUMN_ALARMVARIABLE:
            case COLUMN_ALARMSAMPLETYPE:
            case COLUMN_ALARMSTARTUPALARM:
            case COLUMN_ALARMRISINGTHRESHOLD:
            case COLUMN_ALARMFALLINGTHRESHOLD:
            case COLUMN_ALARMRISINGEVENTINDEX:
            case COLUMN_ALARMFALLINGEVENTINDEX:
            case COLUMN_ALARMOWNER:
                if (table_entry && !table_entry->valid) {
                    table_entry->valid = 1;
                }
                break;
            case COLUMN_ALARMSTATUS:
                switch (*request->requestvb->val.integer) {
                case RMON1_ENTRY_VALID:
                    alarmTable_enable( table_entry );
                    break;
                case RMON1_ENTRY_UNDER_CREATION:
                    alarmTable_disable( table_entry );
#if 0
                    table_entry->session = (netsnmp_session *)
                        netsnmp_iquery_pdu_session(reqinfo->asp->pdu);
#else
                    secName = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                                    NETSNMP_DS_AGENT_INTERNAL_SECNAME);
                    if (secName) {
                        sess   = netsnmp_iquery_user_session(secName);
                        netsnmp_query_set_default_session(sess);
                        DEBUGMSGTL(("rmon:alarmTable", "user name %s\n", secName));
                    } else { 
                        snmp_log(LOG_ERR, "user name %s not found\n", secName);
                        config_perror("Unknown user name\n");
                    }

                    if (NULL == sess) {
                        sess = netsnmp_query_get_default_session();
                        if (NULL == sess) {
                            config_perror
                                ("You must specify a default user name using the agentSecName token\n");
                            return SNMP_ERR_NOERROR;
                        }
                    }
#endif
                    break;
                case RMON1_ENTRY_INVALID:
                    table_row = netsnmp_tdata_extract_row(request);
                    table_data = netsnmp_tdata_extract_table(request);
                    alarmTable_removeEntry(table_data, table_row);
                }
                break;
            }
        }
        break;
    }
    return SNMP_ERR_NOERROR;
}
