Unexpected behaviour

Sverre Moe <[email protected]>
Newsgroups gmane.network.net-snmp.user
Message-ID <f736f9db-964c-4ac3-9a31-3e3598082651@zcs>
I have implemented a delegated response with a 2 seconds delay time. 

My handler function handle_snmp and callback function delayed_response gets called/executed several times for the same requests. Why is that? Is it a feature or a bug? If its a feature is it how it handles the delay by executing it multiple times within the delay time?

In order to avoid querying the device multiple times per request I have implemented a list of active requests. This list holds a pointer to a netsnmp_delegated_cache. When I have gotten the response/value from the device I then remove the request from the active request list. However when this value is retrieved handle_snmp and delayed_response are not yet finished and may be executed a few times more before it ends. Thus it may query the device again.

Can I terminate the delay earlier than the defined delay if I have gotten the value I need? 

int 
handle_snmp(netsnmp_mib_handler *handler, 
            netsnmp_handler_registration *reginfo, 
            netsnmp_agent_request_info *reqinfo, 
            netsnmp_request_info *requests) { 

  const oid* request_oid = (*reginfo).rootoid; 
  const size_t request_oid_length = (*reginfo).rootoid_len - 1; //removes the trailing .0 

  bool request_active = false; 
  list<netsnmp_delegated_cache*>::iterator request_iterator; 
  for (request_iterator = active_requests.begin(); 
         request_iterator != active_requests.end(); 
           request_iterator++) { 
    netsnmp_delegated_cache *delegated_cache = (*request_iterator); 
    netsnmp_handler_registration *delegated_reginfo = delegated_cache->reginfo; 
    const oid* oid_value = (*delegated_reginfo).rootoid; 
    const size_t oid_length = (*delegated_reginfo).rootoid_len - 1; //removes the trailing .0 
    if (netsnmp_oid_equals(oid_value, oid_length, request_oid, request_oid_length) == 0) { 
      request_active = true; 
      break; 
    } 
  } 

  netsnmp_delegated_cache *cache = 
         netsnmp_create_delegated_cache(handler, reginfo, reqinfo, requests, NULL); 

  map<oid_wrapper, scalar>::iterator scalar_iterator; 
  for (scalar_iterator = scalars.begin(); 
         scalar_iterator != scalars.end(); 
           scalar_iterator++) { 
    const oid_wrapper oid_wrapper = (*scalar_iterator).first; 
    const oid* oid_value = oid_wrapper.get_oid(); 
    const int oid_length = oid_wrapper.get_length(); 
    if (netsnmp_oid_equals(oid_value, oid_length, request_oid, request_oid_length) == 0) { 
      if (!request_active) { //request is active, no need to query middleware again. 
        active_requests.push_back(cache); 

        scalar _scalar = (*scalar_iterator).second; 
        const string scalar_path = _scalar.getPath(); 
        const string scalar_type = _scalar.getType(); 
        //My own call to retrieve value from device... 
      } 
      break; 
    } 
  } 

  /* 
   * mark this variable as something that can't be handled now. 
   * We'll answer it later. 
   */ 
  requests->delegated = 1; 

  snmp_alarm_register(delay_time, /* delay */ 
                     0, /* repeat */ 
                     delayed_response, /* the function to call */ 
                     (void *) cache); 

  return SNMP_ERR_NOERROR; 
} 

void 
delayed_response(unsigned int clientreg, void *clientarg) { 
  /* 
   * extract the cache from the passed argument 
   */ 
  netsnmp_delegated_cache *cache = (netsnmp_delegated_cache *) clientarg; 

  netsnmp_request_info *requests; 
  netsnmp_agent_request_info *reqinfo; 
  netsnmp_handler_registration *reginfo; 

  /* 
   * here we double check that the cache we created earlier is still 
   * valid. If not, the request timed out for some reason and we 
   * don't need to keep processing things. Should never happen, but 
   * this double checks. 
   */ 
  cache = netsnmp_handler_check_cache(cache); 

  if (!cache) { 
    snmp_log(LOG_ERR, "illegal call to return delayed response\n"); 
    return; 
  } 

  //re-establish the previous pointers we are used to having 
  reqinfo = cache->reqinfo; 
  reginfo = cache->reginfo; 
  requests = cache->requests; 
  const oid* request_oid = (*reginfo).rootoid; 
  const size_t request_oid_length = (*reginfo).rootoid_len; 

  void* datapointer; 
  char buffer[2048]; 
  int dataint; 
  int length = 0; 
  u_char type; 

  bool found = false; 
  map<oid_wrapper, status>::iterator status_iterator; 
  for (status_iterator = available_status.begin(); 
         status_iterator != available_status.end(); 
           status_iterator++) { 
    const oid_wrapper oid_wrapper = (*status_iterator).first; 
    const oid* oid_value = oid_wrapper.get_oid(); 
    const int oid_length = oid_wrapper.get_length(); 
    if (netsnmp_oid_equals(oid_value, oid_length, request_oid, request_oid_length) == 0) { 
      const status _status = (*status_iterator).second; 
      const string value = _status.getValue(); 
      found = true; 

      strcpy(buffer, value.c_str()); 
      datapointer = buffer; 
      length = strlen(buffer); 
      type = ASN_OCTET_STR; 

      //Value retrieved. We now remove it. 
      available_status.erase(status_iterator); 
      break; 
    } 
  } 

  /* 
   * mention that it's no longer delegated, 
   * and we've now answered the query. 
   */ 
  requests->delegated = 0; 

  if (found) { 
    list<netsnmp_delegated_cache*>::iterator request_iterator; 
    for (request_iterator = active_requests.begin(); 
           request_iterator != active_requests.end(); 
             request_iterator++) { 
      netsnmp_delegated_cache *delegated_cache = (*request_iterator); 
      netsnmp_handler_registration *delegated_reginfo = delegated_cache->reginfo; 
      const oid* oid_value = (*delegated_reginfo).rootoid; 
      const size_t oid_length = (*delegated_reginfo).rootoid_len; 
      if (netsnmp_oid_equals(oid_value, oid_length, request_oid, request_oid_length) == 0) { 
        active_requests.erase(request_iterator); 
        break; 
      } 
    } 

    snmp_set_var_typed_value(cache->requests->requestvb, 
                            type, 
                            datapointer, 
                            length); 
  } else { 
    netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR); 
  } 

  //free the information cache 
  netsnmp_free_delegated_cache(cache); 
} 

CONFIDENTIALITY
This e-mail and any attachment contain KONGSBERG information which may be 
proprietary, confidential or subject to export regulations, and is only meant 
for the intended recipient(s). Any disclosure, copying, distribution or use is 
prohibited, if not otherwise explicitly agreed with KONGSBERG. If received in 
error, please delete it immediately from your system and notify the sender 
properly.


------------------------------------------------------------------------------
LogMeIn Central: Instant, anywhere, Remote PC access and management.
Stay in control, update software, and manage PCs from one command center
Diagnose problems and improve visibility into emerging IT issues
Automate, monitor and manage. Do more in less time with Central
http://p.sf.net/sfu/logmein12331_d2d
_______________________________________________
Net-snmp-users mailing list
[email protected]
Please see the following page to unsubscribe or change other options:
https://lists.sourceforge.net/lists/listinfo/net-snmp-users
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.