Re: [tkined] [Q] About agent mode coding

Juergen Schoenwaelder (schoenw@ibr.cs.tu-bs.de)
Thu, 13 Nov 1997 17:42:23 +0100

Juergen Schoenwaelder <schoenw@ibr.cs.tu-bs.de> said:

Juergen> A simple work-around is to change the function
Juergen> CacheHit() in tnmSnmpAgent.c to always return
Juergen> NULL. (This actually disables the cache.) A more
Juergen> sophisticated fix would invalidate cache entries
Juergen> whenever the agent processes a set-request and
Juergen> automatically after some time (e.g. 5 seconds) has
Juergen> passed.

I played a little bit around and here is a patch which does the
following: All entries in the cache get a timestamp. This timestamp is
checked to determine whether the cache entry is recent. All cache
entries are invalidated whenever an agent receives a set-request by
setting the timestamps to 0. This should fix the problem you have
reported. Please test the attached patch and let me know if there are
any problems with it.
Juergen

*** tnmSnmpAgent.c.orig Tue Sep 9 20:29:16 1997
--- tnmSnmpAgent.c Thu Nov 13 17:34:32 1997
***************
*** 23,28 ****
--- 23,29 ----
SNMP_Session *session;
SNMP_PDU request;
SNMP_PDU response;
+ time_t timestamp;
} CacheElement;

#define CACHE_SIZE 64
***************
*** 199,205 ****
SNMP_Session *session;
SNMP_PDU *pdu;
{
! static last = 0;
last = (last + 1 ) % CACHE_SIZE;
Tcl_DStringFree(&cache[last].request.varbind);
Tcl_DStringFree(&cache[last].response.varbind);
--- 200,206 ----
SNMP_Session *session;
SNMP_PDU *pdu;
{
! static int last = 0;
last = (last + 1 ) % CACHE_SIZE;
Tcl_DStringFree(&cache[last].request.varbind);
Tcl_DStringFree(&cache[last].response.varbind);
***************
*** 211,216 ****
--- 212,218 ----
Tcl_DStringAppend(&cache[last].request.varbind,
Tcl_DStringValue(&pdu->varbind),
Tcl_DStringLength(&pdu->varbind));
+ cache[last].timestamp = time((time_t *) NULL);
return &(cache[last].response);
}

***************
*** 238,248 ****
SNMP_PDU *pdu;
{
int i;
for (i = 0; i < CACHE_SIZE; i++) {
! if (cache[i].response.request_id == pdu->request_id
! && cache[i].session == session
! && Tcl_DStringLength(&pdu->varbind)
! == Tcl_DStringLength(&cache[i].request.varbind)
&& strcmp(Tcl_DStringValue(&pdu->varbind),
Tcl_DStringValue(&cache[i].request.varbind)) == 0
) {
--- 240,257 ----
SNMP_PDU *pdu;
{
int i;
+ time_t now = time((time_t *) NULL);
+
for (i = 0; i < CACHE_SIZE; i++) {
! if (cache[i].response.request_id != pdu->request_id
! || cache[i].session != session) {
! continue;
! }
! if (!cache[i].timestamp || now - cache[i].timestamp > 5) {
! continue;
! }
! if (Tcl_DStringLength(&pdu->varbind)
! == Tcl_DStringLength(&cache[i].request.varbind)
&& strcmp(Tcl_DStringValue(&pdu->varbind),
Tcl_DStringValue(&cache[i].request.varbind)) == 0
) {
***************
*** 256,261 ****
--- 265,299 ----
/*
*----------------------------------------------------------------------
*
+ * CacheClear --
+ *
+ * This procedure clears the cache for a given session.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+ static void
+ CacheClear(session)
+ SNMP_Session *session;
+ {
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++) {
+ if (cache[i].session == session) {
+ cache[i].timestamp = 0;
+ }
+ }
+ }
+
+ /*
+ *----------------------------------------------------------------------
+ *
* TraceSysUpTime --
*
* This procedure is a trace callback which is called by the
***************
*** 371,377 ****
Tcl_Interp *interp;
SNMP_Session *session;
{
! static done = 0;
char tclvar[80], buffer[255], *value;
struct StatReg *p;

--- 409,415 ----
Tcl_Interp *interp;
SNMP_Session *session;
{
! static int done = 0;
char tclvar[80], buffer[255], *value;
struct StatReg *p;

***************
*** 964,974 ****
SNMP_PDU *reply;

switch (pdu->type) {
! case TNM_SNMP_GET: snmpStats.snmpInGetRequests++; break;
! case TNM_SNMP_GETNEXT: snmpStats.snmpInGetNexts++; break;
! case TNM_SNMP_GETBULK: break;
! case TNM_SNMP_SET: snmpStats.snmpInSetRequests++; break;
! case TNM_SNMP_INFORM: break;
}

reply = CacheHit(session, pdu);
--- 1002,1024 ----
SNMP_PDU *reply;

switch (pdu->type) {
! case TNM_SNMP_GET:
! snmpStats.snmpInGetRequests++;
! break;
! case TNM_SNMP_GETNEXT:
! snmpStats.snmpInGetNexts++;
! break;
! case TNM_SNMP_GETBULK:
! break;
! case TNM_SNMP_SET:
! snmpStats.snmpInSetRequests++;
! break;
! case TNM_SNMP_INFORM:
! break;
! }
!
! if (pdu->type == TNM_SNMP_SET) {
! CacheClear(session);
}

reply = CacheHit(session, pdu);

--
!! This message is brought to you via the `tkined & scotty' mailing list.
!! Please do not reply to this message to unsubscribe. To subscribe or
!! unsubscribe, send a mail message to <tkined-request@ibr.cs.tu-bs.de>.
!! See http://wwwsnmp.cs.utwente.nl/~schoenw/scotty/ for more information.