oid_stash.c

00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #include <string.h>
00004 
00005 #include <stdlib.h>
00006 #include <sys/types.h>
00007 
00008 #include <net-snmp/net-snmp-includes.h>
00009 
00018 /*
00019  * xxx-rks: when you have some spare time:
00020  *
00021  * b) basically, everything currently creates one node per sub-oid,
00022  *    which is less than optimal. add code to create nodes with the
00023  *    longest possible OID per node, and split nodes when necessary
00024  *    during adds.
00025  *
00026  * c) If you are feeling really ambitious, also merge split nodes if
00027  *    possible on a delete.
00028  *
00029  * xxx-wes: uh, right, like I *ever* have that much time.
00030  *
00031  */
00032 
00033 /***************************************************************************
00034  *
00035  *
00036  ***************************************************************************/
00037 
00045 netsnmp_oid_stash_node *
00046 netsnmp_oid_stash_create_sized_node(size_t mysize)
00047 {
00048     netsnmp_oid_stash_node *ret;
00049     ret = SNMP_MALLOC_TYPEDEF(netsnmp_oid_stash_node);
00050     if (!ret)
00051         return NULL;
00052     ret->children = calloc(mysize, sizeof(netsnmp_oid_stash_node *));
00053     if (!ret->children) {
00054         free(ret);
00055         return NULL;
00056     }
00057     ret->children_size = mysize;
00058     return ret;
00059 }
00060 
00065 NETSNMP_INLINE netsnmp_oid_stash_node *
00066 netsnmp_oid_stash_create_node(void)
00067 {
00068     return netsnmp_oid_stash_create_sized_node(OID_STASH_CHILDREN_SIZE);
00069 }
00070 
00082 int
00083 netsnmp_oid_stash_add_data(netsnmp_oid_stash_node **root,
00084                            oid * lookup, size_t lookup_len, void *mydata)
00085 {
00086     netsnmp_oid_stash_node *curnode, *tmpp, *loopp;
00087     unsigned int    i;
00088 
00089     if (!root || !lookup || lookup_len == 0)
00090         return SNMPERR_GENERR;
00091 
00092     if (!*root) {
00093         *root = netsnmp_oid_stash_create_node();
00094         if (!*root)
00095             return SNMPERR_MALLOC;
00096     }
00097     DEBUGMSGTL(( "oid_stash", "stash_add_data "));
00098     DEBUGMSGOID(("oid_stash", lookup, lookup_len));
00099     DEBUGMSG((   "oid_stash", "\n"));
00100     tmpp = NULL;
00101     for (curnode = *root, i = 0; i < lookup_len; i++) {
00102         tmpp = curnode->children[lookup[i] % curnode->children_size];
00103         if (!tmpp) {
00104             /*
00105              * no child in array at all 
00106              */
00107             tmpp = curnode->children[lookup[i] % curnode->children_size] =
00108                 netsnmp_oid_stash_create_node();
00109             tmpp->value = lookup[i];
00110             tmpp->parent = curnode;
00111         } else {
00112             for (loopp = tmpp; loopp; loopp = loopp->next_sibling) {
00113                 if (loopp->value == lookup[i])
00114                     break;
00115             }
00116             if (loopp) {
00117                 tmpp = loopp;
00118             } else {
00119                 /*
00120                  * none exists.  Create it 
00121                  */
00122                 loopp = netsnmp_oid_stash_create_node();
00123                 loopp->value = lookup[i];
00124                 loopp->next_sibling = tmpp;
00125                 loopp->parent = curnode;
00126                 tmpp->prev_sibling = loopp;
00127                 curnode->children[lookup[i] % curnode->children_size] =
00128                     loopp;
00129                 tmpp = loopp;
00130             }
00131             /*
00132              * tmpp now points to the proper node 
00133              */
00134         }
00135         curnode = tmpp;
00136     }
00137     /*
00138      * tmpp now points to the exact match 
00139      */
00140     if (curnode->thedata)
00141         return SNMPERR_GENERR;
00142     if (NULL == tmpp)
00143         return SNMPERR_GENERR;
00144     tmpp->thedata = mydata;
00145     return SNMPERR_SUCCESS;
00146 }
00147 
00153 netsnmp_oid_stash_node *
00154 netsnmp_oid_stash_get_node(netsnmp_oid_stash_node *root,
00155                            oid * lookup, size_t lookup_len)
00156 {
00157     netsnmp_oid_stash_node *curnode, *tmpp, *loopp;
00158     unsigned int    i;
00159 
00160     if (!root)
00161         return NULL;
00162     tmpp = NULL;
00163     for (curnode = root, i = 0; i < lookup_len; i++) {
00164         tmpp = curnode->children[lookup[i] % curnode->children_size];
00165         if (!tmpp) {
00166             return NULL;
00167         } else {
00168             for (loopp = tmpp; loopp; loopp = loopp->next_sibling) {
00169                 if (loopp->value == lookup[i])
00170                     break;
00171             }
00172             if (loopp) {
00173                 tmpp = loopp;
00174             } else {
00175                 return NULL;
00176             }
00177         }
00178         curnode = tmpp;
00179     }
00180     return tmpp;
00181 }
00182 
00190 netsnmp_oid_stash_node *
00191 netsnmp_oid_stash_getnext_node(netsnmp_oid_stash_node *root,
00192                                oid * lookup, size_t lookup_len)
00193 {
00194     netsnmp_oid_stash_node *curnode, *tmpp, *loopp;
00195     unsigned int    i, j, bigger_than = 0, do_bigger = 0;
00196 
00197     if (!root)
00198         return NULL;
00199     tmpp = NULL;
00200 
00201     /* get closest matching node */
00202     for (curnode = root, i = 0; i < lookup_len; i++) {
00203         tmpp = curnode->children[lookup[i] % curnode->children_size];
00204         if (!tmpp) {
00205             break;
00206         } else {
00207             for (loopp = tmpp; loopp; loopp = loopp->next_sibling) {
00208                 if (loopp->value == lookup[i])
00209                     break;
00210             }
00211             if (loopp) {
00212                 tmpp = loopp;
00213             } else {
00214                 break;
00215             }
00216         }
00217         curnode = tmpp;
00218     }
00219 
00220     /* find the *next* node lexographically greater */
00221     if (!curnode)
00222         return NULL; /* ack! */
00223 
00224     if (i+1 < lookup_len) {
00225         bigger_than = lookup[i+1];
00226         do_bigger = 1;
00227     }
00228 
00229     do {
00230         /* check the children first */
00231         tmpp = NULL;
00232         /* next child must be (next) greater than our next search node */
00233         /* XXX: should start this loop at best_nums[i]%... and wrap */
00234         for(j = 0; j < curnode->children_size; j++) {
00235             for (loopp = curnode->children[j];
00236                  loopp; loopp = loopp->next_sibling) {
00237                 if ((!do_bigger || loopp->value > bigger_than) &&
00238                     (!tmpp || tmpp->value > loopp->value)) {
00239                     tmpp = loopp;
00240                     /* XXX: can do better and include min_nums[i] */
00241                     if (tmpp->value <= curnode->children_size-1) {
00242                         /* best we can do. */
00243                         goto done_this_loop;
00244                     }
00245                 }
00246             }
00247         }
00248 
00249       done_this_loop:
00250         if (tmpp && tmpp->thedata)
00251             /* found a node with data.  Go with it. */
00252             return tmpp;
00253 
00254         if (tmpp) {
00255             /* found a child node without data, maybe find a grandchild? */
00256             do_bigger = 0;
00257             curnode = tmpp;
00258         } else {
00259             /* no respectable children (the bums), we'll have to go up.
00260                But to do so, they must be better than our current best_num + 1.
00261             */
00262             do_bigger = 1;
00263             bigger_than = curnode->value;
00264             curnode = curnode->parent;
00265         }
00266     } while (curnode);
00267 
00268     /* fell off the top */
00269     return NULL;
00270 }
00271 
00281 void           *
00282 netsnmp_oid_stash_get_data(netsnmp_oid_stash_node *root,
00283                            oid * lookup, size_t lookup_len)
00284 {
00285     netsnmp_oid_stash_node *ret;
00286     ret = netsnmp_oid_stash_get_node(root, lookup, lookup_len);
00287     if (ret)
00288         return ret->thedata;
00289     return NULL;
00290 }
00291 
00303 int
00304 netsnmp_oid_stash_store_all(int majorID, int minorID,
00305                             void *serverarg, void *clientarg) {
00306     oid oidbase[MAX_OID_LEN];
00307     netsnmp_oid_stash_save_info *sinfo;
00308     
00309     if (!clientarg)
00310         return SNMP_ERR_NOERROR;
00311     
00312     sinfo = clientarg;
00313     netsnmp_oid_stash_store(*(sinfo->root), sinfo->token, sinfo->dumpfn,
00314                             oidbase,0);
00315     return SNMP_ERR_NOERROR;
00316 }
00317 
00333 void
00334 netsnmp_oid_stash_store(netsnmp_oid_stash_node *root,
00335                         const char *tokenname, NetSNMPStashDump *dumpfn,
00336                         oid *curoid, size_t curoid_len) {
00337 
00338     char buf[SNMP_MAXBUF];
00339     netsnmp_oid_stash_node *tmpp;
00340     char *cp;
00341     char *appname = netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, 
00342                                           NETSNMP_DS_LIB_APPTYPE);
00343     int i;
00344     
00345     if (!tokenname || !root || !curoid || !dumpfn)
00346         return;
00347 
00348     for (i = 0; i < (int)root->children_size; i++) {
00349         if (root->children[i]) {
00350             for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) {
00351                 curoid[curoid_len] = tmpp->value;
00352                 if (tmpp->thedata) {
00353                     snprintf(buf, sizeof(buf), "%s ", tokenname);
00354                     cp = read_config_save_objid(buf+strlen(buf), curoid,
00355                                                 curoid_len+1);
00356                     *cp++ = ' ';
00357                     *cp = '\0';
00358                     if ((*dumpfn)(cp, sizeof(buf) - strlen(buf),
00359                                   tmpp->thedata, tmpp))
00360                         read_config_store(appname, buf);
00361                 }
00362                 netsnmp_oid_stash_store(tmpp, tokenname, dumpfn,
00363                                         curoid, curoid_len+1);
00364             }
00365         }
00366     }
00367 }
00368 
00373 void 
00374 oid_stash_dump(netsnmp_oid_stash_node *root, char *prefix)
00375 {
00376     char            myprefix[MAX_OID_LEN * 4];
00377     netsnmp_oid_stash_node *tmpp;
00378     int             prefix_len = strlen(prefix) + 1;    /* actually it's +2 */
00379     unsigned int    i;
00380 
00381     memset(myprefix, ' ', MAX_OID_LEN * 4);
00382     myprefix[prefix_len] = '\0';
00383 
00384     for (i = 0; i < root->children_size; i++) {
00385         if (root->children[i]) {
00386             for (tmpp = root->children[i]; tmpp; tmpp = tmpp->next_sibling) {
00387                 printf("%s%ld@%d: %s\n", prefix, tmpp->value, i,
00388                        (tmpp->thedata) ? "DATA" : "");
00389                 oid_stash_dump(tmpp, myprefix);
00390             }
00391         }
00392     }
00393 }
00394 
00400 void
00401 netsnmp_oid_stash_free(netsnmp_oid_stash_node **root,
00402                        NetSNMPStashFreeNode *freefn) {
00403 
00404     netsnmp_oid_stash_node *curnode, *tmpp;
00405     unsigned int    i;
00406 
00407     if (!root || !*root)
00408         return;
00409 
00410     /* loop through all our children and free each node */
00411     for (i = 0; i < (*root)->children_size; i++) {
00412         if ((*root)->children[i]) {
00413             for(tmpp = (*root)->children[i]; tmpp; tmpp = curnode) {
00414                 if (tmpp->thedata) {
00415                     if (freefn)
00416                         (*freefn)(tmpp->thedata);
00417                     else
00418                         free(tmpp->thedata);
00419                 }
00420                 curnode = tmpp->next_sibling;
00421                 netsnmp_oid_stash_free(&tmpp, freefn);
00422             }
00423         }
00424     }
00425     free((*root)->children);
00426     free (*root);
00427     *root = NULL;
00428 }
00429 
00430 void
00431 netsnmp_oid_stash_no_free(void *bogus)
00432 {
00433     /* noop */
00434 }
00435 

net-snmpに対してSat Sep 5 13:14:22 2009に生成されました。  doxygen 1.4.7