📄 snmp_alarm.c
字号:
/* * snmp_alarm.c: generic library based alarm timers for various parts * of an application */#include <net-snmp/net-snmp-config.h>#if HAVE_UNISTD_H#include <unistd.h>#endif#include <signal.h>#if HAVE_STDLIB_H#include <stdlib.h>#endif#include <sys/types.h>#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if TIME_WITH_SYS_TIME# ifdef WIN32# include <sys/timeb.h># else# include <sys/time.h># endif# include <time.h>#else# if HAVE_SYS_TIME_H# include <sys/time.h># else# include <time.h># endif#endif#if HAVE_WINSOCK_H#include <winsock.h>#endif#if HAVE_DMALLOC_H#include <dmalloc.h>#endif#include <net-snmp/types.h>#include <net-snmp/output_api.h>#include <net-snmp/config_api.h>#include <net-snmp/utilities.h>#include <net-snmp/library/snmp_api.h>#include <net-snmp/library/callback.h>#include <net-snmp/library/snmp_alarm.h>static struct snmp_alarm *thealarms = NULL;static int start_alarms = 0;static unsigned int regnum = 1;intinit_alarm_post_config(int majorid, int minorid, void *serverarg, void *clientarg){ start_alarms = 1; set_an_alarm(); return SNMPERR_SUCCESS;}voidinit_snmp_alarm(void){ start_alarms = 0; snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG, init_alarm_post_config, NULL);}voidsa_update_entry(struct snmp_alarm *a){ if (a->t.tv_sec == 0 && a->t.tv_usec == 0) { DEBUGMSGTL(("snmp_alarm", "update_entry: illegal interval specified\n")); return; } if (a->t_last.tv_sec == 0 && a->t_last.tv_usec == 0) { struct timeval t_now; /* * Never been called yet, call time `t' from now. */ gettimeofday(&t_now, NULL); a->t_last.tv_sec = t_now.tv_sec; a->t_last.tv_usec = t_now.tv_usec; a->t_next.tv_sec = t_now.tv_sec + a->t.tv_sec; a->t_next.tv_usec = t_now.tv_usec + a->t.tv_usec; while (a->t_next.tv_usec >= 1000000) { a->t_next.tv_usec -= 1000000; a->t_next.tv_sec += 1; } } else if (a->t_next.tv_sec == 0 && a->t_next.tv_usec == 0) { /* * We've been called but not reset for the next call. */ if (a->flags & SA_REPEAT) { a->t_next.tv_sec = a->t_last.tv_sec + a->t.tv_sec; a->t_next.tv_usec = a->t_last.tv_usec + a->t.tv_usec; while (a->t_next.tv_usec >= 1000000) { a->t_next.tv_usec -= 1000000; a->t_next.tv_sec += 1; } } else { /* * Single time call, remove it. */ snmp_alarm_unregister(a->clientreg); } }}voidsnmp_alarm_unregister(unsigned int clientreg){ struct snmp_alarm *sa_ptr, **prevNext = &thealarms; for (sa_ptr = thealarms; sa_ptr != NULL && sa_ptr->clientreg != clientreg; sa_ptr = sa_ptr->next) { prevNext = &(sa_ptr->next); } if (sa_ptr != NULL) { *prevNext = sa_ptr->next; DEBUGMSGTL(("snmp_alarm", "unregistered alarm %d\n", sa_ptr->clientreg)); /* * Note: do not free the clientarg, its the clients responsibility */ free(sa_ptr); } else { DEBUGMSGTL(("snmp_alarm", "no alarm %d to unregister\n", clientreg)); }}voidsnmp_alarm_unregister_all(void){ struct snmp_alarm *sa_ptr, *sa_tmp; for (sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_tmp) { sa_tmp = sa_ptr->next; free(sa_ptr); } DEBUGMSGTL(("snmp_alarm", "ALL alarms unregistered\n")); thealarms = NULL;} struct snmp_alarm *sa_find_next(void){ struct snmp_alarm *a, *lowest = NULL; for (a = thealarms; a != NULL; a = a->next) { if (lowest == NULL) { lowest = a; } else if (a->t_next.tv_sec == lowest->t_next.tv_sec) { if (a->t_next.tv_usec < lowest->t_next.tv_usec) { lowest = a; } } else if (a->t_next.tv_sec < lowest->t_next.tv_sec) { lowest = a; } } return lowest;}struct snmp_alarm *sa_find_specific(unsigned int clientreg){ struct snmp_alarm *sa_ptr; for (sa_ptr = thealarms; sa_ptr != NULL; sa_ptr = sa_ptr->next) { if (sa_ptr->clientreg == clientreg) { return sa_ptr; } } return NULL;}voidrun_alarms(void){ int done = 0; struct snmp_alarm *a = NULL; unsigned int clientreg; struct timeval t_now; /* * Loop through everything we have repeatedly looking for the next thing to * call until all events are finally in the future again. */ while (!done) { if ((a = sa_find_next()) == NULL) { return; } gettimeofday(&t_now, NULL); if ((a->t_next.tv_sec < t_now.tv_sec) || ((a->t_next.tv_sec == t_now.tv_sec) && (a->t_next.tv_usec < t_now.tv_usec))) { clientreg = a->clientreg; DEBUGMSGTL(("snmp_alarm", "run alarm %d\n", clientreg)); (*(a->thecallback)) (clientreg, a->clientarg); DEBUGMSGTL(("snmp_alarm", "alarm %d completed\n", clientreg)); if ((a = sa_find_specific(clientreg)) != NULL) { a->t_last.tv_sec = t_now.tv_sec; a->t_last.tv_usec = t_now.tv_usec; a->t_next.tv_sec = 0; a->t_next.tv_usec = 0; sa_update_entry(a); } else { DEBUGMSGTL(("snmp_alarm", "alarm %d deleted itself\n", clientreg)); } } else { done = 1; } }}RETSIGTYPEalarm_handler(int a){ run_alarms(); set_an_alarm();}intget_next_alarm_delay_time(struct timeval *delta){ struct snmp_alarm *sa_ptr; struct timeval t_diff, t_now; sa_ptr = sa_find_next(); if (sa_ptr) { gettimeofday(&t_now, 0); if ((t_now.tv_sec > sa_ptr->t_next.tv_sec) || ((t_now.tv_sec == sa_ptr->t_next.tv_sec) && (t_now.tv_usec > sa_ptr->t_next.tv_usec))) { /* * Time has already passed. Return the smallest possible amount of * time. */ delta->tv_sec = 0; delta->tv_usec = 1; return sa_ptr->clientreg; } else { /* * Time is still in the future. */ t_diff.tv_sec = sa_ptr->t_next.tv_sec - t_now.tv_sec; t_diff.tv_usec = sa_ptr->t_next.tv_usec - t_now.tv_usec; while (t_diff.tv_usec < 0) { t_diff.tv_sec -= 1; t_diff.tv_usec += 1000000; } delta->tv_sec = t_diff.tv_sec; delta->tv_usec = t_diff.tv_usec; return sa_ptr->clientreg; } } /* * Nothing Left. */ return 0;}voidset_an_alarm(void){ struct timeval delta; int nextalarm = get_next_alarm_delay_time(&delta); /* * We don't use signals if they asked us nicely not to. It's expected * they'll check the next alarm time and do their own calling of * run_alarms(). */ if (nextalarm && !netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_ALARM_DONT_USE_SIG)) {#ifndef WIN32# ifdef HAVE_SETITIMER struct itimerval it; it.it_value.tv_sec = delta.tv_sec; it.it_value.tv_usec = delta.tv_usec; it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 0; signal(SIGALRM, alarm_handler); setitimer(ITIMER_REAL, &it, NULL); DEBUGMSGTL(("snmp_alarm", "schedule alarm %d in %d.%03d seconds\n", nextalarm, delta.tv_sec, (delta.tv_usec / 1000)));# else /* HAVE_SETITIMER */# ifdef SIGALRM signal(SIGALRM, alarm_handler); alarm(delta.tv_sec); DEBUGMSGTL(("snmp_alarm", "schedule alarm %d in roughly %d seconds\n", nextalarm, delta.tv_sec));# endif /* SIGALRM */# endif /* HAVE_SETITIMER */#endif /* WIN32 */ } else { DEBUGMSGTL(("snmp_alarm", "no alarms found to schedule\n")); }}unsigned intsnmp_alarm_register(unsigned int when, unsigned int flags, SNMPAlarmCallback * thecallback, void *clientarg){ struct snmp_alarm **sa_pptr; if (thealarms != NULL) { for (sa_pptr = &thealarms; (*sa_pptr) != NULL; sa_pptr = &((*sa_pptr)->next)); } else { sa_pptr = &thealarms; } *sa_pptr = SNMP_MALLOC_STRUCT(snmp_alarm); if (*sa_pptr == NULL) return 0; (*sa_pptr)->t.tv_sec = when; (*sa_pptr)->t.tv_usec = 0; (*sa_pptr)->flags = flags; (*sa_pptr)->clientarg = clientarg; (*sa_pptr)->thecallback = thecallback; (*sa_pptr)->clientreg = regnum++; (*sa_pptr)->next = NULL; sa_update_entry(*sa_pptr); DEBUGMSGTL(("snmp_alarm", "registered alarm %d, t = %d.%03d, flags=0x%02x\n", (*sa_pptr)->clientreg, (*sa_pptr)->t.tv_sec, ((*sa_pptr)->t.tv_usec / 1000), (*sa_pptr)->flags)); if (start_alarms) set_an_alarm(); return (*sa_pptr)->clientreg;}unsigned intsnmp_alarm_register_hr(struct timeval t, unsigned int flags, SNMPAlarmCallback * cb, void *cd){ struct snmp_alarm **s = NULL; for (s = &(thealarms); *s != NULL; s = &((*s)->next)); *s = SNMP_MALLOC_STRUCT(snmp_alarm); if (*s == NULL) { return 0; } (*s)->t.tv_sec = t.tv_sec; (*s)->t.tv_usec = t.tv_usec; (*s)->flags = flags; (*s)->clientarg = cd; (*s)->thecallback = cb; (*s)->clientreg = regnum++; (*s)->next = NULL; sa_update_entry(*s); DEBUGMSGTL(("snmp_alarm", "registered alarm %d, t = %d.%03d, flags=0x%02x\n", (*s)->clientreg, (*s)->t.tv_sec, ((*s)->t.tv_usec / 1000), (*s)->flags)); if (start_alarms) { set_an_alarm(); } return (*s)->clientreg;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -