implementing a large table over a database

Martin Janzen janzen____pixelmetrix.com
Fri Nov 1 09:52:36 CET 2002


[Not sure this was sent earlier; sorry if you see it twice...]

Our resident external-tables expert, Alex Finogenov, wrote:

 > [...]
 > 2. I implemented GetBulk in terms of GetNext. You will have to override
 > MibTable::find_succ(), which is called by during the processing of either
 > method, if I remember correctly.

I've also found that this works pretty well.  It's a lot easier than
trying to make the update() method anticipate the exact set of rows
that will be needed by a complex GETBULK request.

However, I notice that if I override find_succ(), my update() method
still has to check for the case in which a GETNEXT/GETBULK from a
previous table has run over into the current table.  If this happens,
it must load the first row of the table, so that Agent++ knows there's
something there.

(The first row is sufficient: Once it knows that it must descend into
the current table, Agent++ will continue to call find_succ() as needed.)


In other words, here's a pseudocode version of what I'm doing now:

void
MyTable::update(Agentpp::Request* pReq)
{
     // Don't do more work than necessary.  (Note that it's good practice
     // to check both the request address and the transaction ID, since
     // the request address is at the whim of the implementations of
     // Agent++ and of your new/delete operators.)
     if ((pReq == mCurrentRequest) &&
         (pReq->get_transaction_id() == mLastTransactionID)
         return;

     mCurrentRequest = pReq;
     mLastTransactionID = (pReq == 0) ? 0 : pReq->get_transaction_id();

     // Since this is a new request, throw away all rows generated in
     // response to the previous request.  (I agree with Alex: stateless
     // agents are the way to go!)
     clear();

     for (int sub = 0; sub < pReq->subrequests(); sub++)
     {
         Agentpp::Oidx subrequestOID = pReq->get_oid(sub);

         switch (pReq->get_type())
         {
         case sNMP_PDU_GET:
             // If the requested OID is in this table, create a row for
             // the requested index value.
             if (base(subrequestOID) == *key())
                 loadRow(index(subrequestOID));
             break;

         case sNMP_PDU_GETNEXT:
         case sNMP_PDU_GETBULK:
             // If this table's update() method was called in response to
             // a GETNEXT request on the last object in a previous table,
             // load the first row of this table, so that Agent++ knows
             // it needs to descend into this subtree.
             if (base(subrequestOID) != *key())
                 loadNextRow(Oidx());
             break;

         [...]

         }
     }
}

Agentpp::Oidx
MyTable::find_succ(const Agentpp::Oidx& oid, Agentpp::Request* pReq)
{
     // Load the row which follows the requested index value, then let
     // the Agent++ tree traversal code find it as usual.
     loadNextRow(index(oid));
     return MibTable::find_succ(oid, pReq);
}

Comments/suggestions welcome, of course.



 > 3. Get methods are peanuts comparing to the Set, especially in when
 > implementing tables with AUGMENT clause, etc.

Oh, good.  I can hardly wait...


-- 
Martin Janzen
janzen at pixelmetrix.com


-- 
Martin Janzen
janzen at pixelmetrix.com




More information about the AGENTPP mailing list