...
The problem with the above approach is: It will not work with AGENT++ (at least not without additional coding)!
Solution
OK, so how can asynchronous or pseudo-synchronous processing a SNMP request be implemented with AGENT++?
The answer is, there are at least two approaches:
- Asynchronous (concurrent) processing of all sub-requests with reprocessing of the request when a sub-task associated with sub-request has completed.
- Pseudo-synchronous processing of each sub-request sequentially.
Asynchronous
The real asynchronous approach has been implemented by AgentX++ in order to be able to concurrently process sub-requests on several sub-agents (or a single multi-threaded sub-agent).
Pseudo-Synchronous
The pseudo-synchronous approach allows queued instrumentation while answering the SNMP request is done synchronously. That means, all sub-requests are processed in the order as they occur in the original SNMP request.
To implement this solution you need:
- An OidList<RequestID> to associate the processed Request...
- The Request pointer which extends Synchronized and can therefore by used to wait with timeout until another thread notifies it.
- A pointer to the RequestList to be able to lookup the pending Request to be notified when the instrumentation code finishes.
Code Block |
---|
int agentppTestRowCreation::commit_set_request(Request* req, int ind)
{
//--AgentGen BEGIN=agentppTestRowCreation::commit_set_request
unsigned long val;
Vbx vb(req->get_value(ind));
vb.get_value(val);
Oidx rowIndex;
rowIndex += val;
if (agentppTestSharedEntry::instance->
pending_row_ops.find(&rowIndex)) {
return SNMP_ERROR_COMITFAIL;
}
// double check for duplicate row (has already been checked in prepare
agentppTestSharedEntry::instance->start_synch();
if (agentppTestSharedEntry::instance->find_index(rowIndex)) {
agentppTestSharedEntry::instance->end_synch();
return SNMP_ERROR_COMITFAIL;
}
agentppTestSharedEntry::instance->end_synch();
// allocate index and then register and add the row in a background thread
if (!agentppTestSharedEntry::instance->allocate_index(rowIndex)) {
*((Gauge32*)value) = 0;
return SNMP_ERROR_COMITFAIL;
}
else {
agentppTestSharedEntry::instance->
pending_row_ops.add(new RequestID(req->get_request_id(), rowIndex));
// wait until row has been registered at master agent
if (req->wait(AGENTX_DEFAULT_TIMEOUT*1000)) {
agentppTestSharedEntry::instance->start_synch();
agentppTestSharedEntry::instance->remove_row(rowIndex);
agentppTestSharedEntry::instance->end_synch();
return SNMP_ERROR_COMITFAIL;
}
}
//--AgentGen END
return MibLeaf::commit_set_request(req, ind);
}
|