/*
 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
 *
 * U.S. Government Rights - Commercial software. Government users are subject
 * to the Sun Microsystems, Inc. standard license agreement and applicable
 * provisions of the FAR and its supplements.
 *
 *
 * This distribution may include materials developed by third parties. Sun,
 * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
 * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
 *
 */
#pragma ident   "@(#)entLastChangeTime.c 1.1     03/02/24 SMI"

/*
 * Note: this file originally auto-generated by mib2c using
 *        : mib2c.scalar.conf,v 1.5 2002/07/18 14:18:52 dts12 Exp $
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "stdhdr.h"
#include "entLastChangeTime.h"

/* Fix for 4929068 */
static int creg;
/* End of Fix for 4929068 */

static void poll_entLastChangeTime();
static void send_entConfigChange_trap();

/* time between entConfigChange traps in 1/1000th of a second */
#define	TRAP_THROTTLE_PERIOD	5000
/* Fix for 4929068 */
#define	TRAP_THROTTLE_PERIOD_SECS TRAP_THROTTLE_PERIOD/1000
/* End of Fix for 4929068 */

/* Fix for 4928832 */
/* Static storage for markers */
static struct timeval entLastChangeTimeStorage;
static struct timeval trapLastIssuedStorage;

/* Pointers to storage for markers */
static marker_t entLastChangeTime;
static marker_t trapLastIssued;
/* End of Fix for 4928832 */

/* 4929068 - structures for debugging throttling period waits
static struct timeval alarmTimeStorage;
static marker_t alarmTime;
*/

static oid entityMIBTrapsOID[] = { entityMIBTraps };


/*
 * returns the value of sysUpTime in TimeTicks
 */
static unsigned long
entLastChangeTime_TimeTicks()
{
	return (unsigned long) netsnmp_marker_uptime(entLastChangeTime) &
	    0xFFFFFFFF;
}

/* Initializes the entLastChangeTime module */
void
init_entLastChangeTime(void)
{
	static oid entLastChangeTime_oid[] =
	    { 1, 3, 6, 1, 2, 1, 47, 1, 4, 1, 0 };

	DEBUGMSGTL(("entLastChangeTime", "Initializing\n"));

/* Fix for 4928832 */
	entLastChangeTime = (marker_t)&entLastChangeTimeStorage;
	trapLastIssued = (marker_t)&trapLastIssuedStorage;
/* End of Fix for 4928832 */
/* Fix for 4928828 */
	entLastChangeTimeStorage.tv_sec = 0;
	entLastChangeTimeStorage.tv_usec = 0;
	atime_setMarker(entLastChangeTime);
/* End of Fix for 4928828 */

/* 4929068 - debug code
	alarmTime = (marker_t)&alarmTimeStorage;
*/

	if (!entLastChangeTime || !trapLastIssued)
	    return;

	netsnmp_register_read_only_instance(netsnmp_create_handler_registration
	    ("entLastChangeTime", get_entLastChangeTime, entLastChangeTime_oid,
		OID_LENGTH(entLastChangeTime_oid), HANDLER_CAN_RONLY));
}

/* Fix for 4929068 */
/*
 * alarm_entLastChangeTime - called after throttle period over,
 * poll to see if anything was suppressed.
 */
static void alarm_entLastChangeTime(unsigned int regnum, void *data) {
/* 4929068 - debug code
	atime_setMarker(alarmTime);
	printf("alarm_entLastChangeTime, marker time = %d\n",
	(netsnmp_marker_uptime(alarmTime) & 0xFFFFFFFF));
*/

    poll_entLastChangeTime();
}
/* End of Fix for 4929068 */

int
get_entLastChangeTime(netsnmp_mib_handler * handler,
    netsnmp_handler_registration * reginfo,
    netsnmp_agent_request_info * reqinfo, netsnmp_request_info * requests)
{
	unsigned long t;

	/*
	 * We are never called for a GETNEXT if it's registered as a
	 * "instance", as it's "magically" handled for us.
	 */

	/*
	 * a instance handler also only hands us one request at a time, so
	 * we don't need to loop over a list of requests; we'll only get one.
	 */

	switch (reqinfo->mode) {

	case MODE_GET:

		t = entLastChangeTime_TimeTicks();
		snmp_set_var_typed_value(requests->requestvb, ASN_TIMETICKS,
		    (u_char *) & t, sizeof (t));
		break;

	default:
		/*
		 * we should never get here, so this is a really bad error
		 */
		return (SNMP_ERR_GENERR);
	}

	return (SNMP_ERR_NOERROR);
}

void
configChanged()
{
	atime_setMarker(entLastChangeTime);
	poll_entLastChangeTime();
}

static void
poll_entLastChangeTime()
{
	long diff;

	/* don't issue trap if within throttle period */
	if (!atime_ready(trapLastIssued, TRAP_THROTTLE_PERIOD))
		return;

	diff = atime_diff(entLastChangeTime, trapLastIssued);
	if (diff <= 0 ) {
		/* there was a change since the last trap was issued */

		send_entConfigChange_trap();

		atime_setMarker(trapLastIssued);
		/* Fix for 4929068 */
		/*
		 * Set up alarm to wake up TRAP_THROTTLE_PERIOD_SECS seconds
		 * after the last trap was sent.  If anything was suppressed,
		 * a trap will be sent.
		 */
		creg = snmp_alarm_register(TRAP_THROTTLE_PERIOD_SECS, NULL,
					   alarm_entLastChangeTime, NULL);
		/* End of Fix for 4929068 */
	}
}

static void
send_entConfigChange_trap()
{
        send_enterprise_trap_vars(SNMP_TRAP_ENTERPRISESPECIFIC, 1,
            entityMIBTrapsOID, OID_LENGTH(entityMIBTrapsOID), NULL);
}


