container.c

00001 #include <net-snmp/net-snmp-config.h>
00002 #include <net-snmp/net-snmp-includes.h>
00003 #include <net-snmp/library/container.h>
00004 #include <net-snmp/library/container_binary_array.h>
00005 #include <net-snmp/library/container_list_ssll.h>
00006 #include <net-snmp/library/container_null.h>
00007 
00008 /*------------------------------------------------------------------
00009  */
00010 static netsnmp_container *containers = NULL;
00011 
00012 typedef struct container_type_s {
00013    const char                 *name;
00014    netsnmp_factory            *factory;
00015    netsnmp_container_compare  *compare;
00016 } container_type;
00017 
00018 netsnmp_factory *
00019 netsnmp_container_get_factory(const char *type);
00020 
00021 /*------------------------------------------------------------------
00022  */
00023 static void 
00024 _factory_free(void *dat, void *context)
00025 {
00026     container_type *data = (container_type *)dat;
00027     if (data == NULL)
00028         return;
00029     
00030     if (data->name != NULL) {
00031         DEBUGMSGTL(("container", "  _factory_free_list() called for %s\n",
00032                     data->name));
00033         free((void *)data->name); /* SNMP_FREE wasted on object about to be freed */
00034     }
00035     free(data); /* SNMP_FREE wasted on param */
00036 }
00037 
00038 /*------------------------------------------------------------------
00039  */
00040 void
00041 netsnmp_container_init_list(void)
00042 {
00043     if (NULL != containers)
00044         return;
00045 
00046     /*
00047      * create a binary arry container to hold container
00048      * factories
00049      */
00050     containers = netsnmp_container_get_binary_array();
00051     containers->compare = netsnmp_compare_cstring;
00052 
00053     /*
00054      * register containers
00055      */
00056     netsnmp_container_binary_array_init();
00057     netsnmp_container_ssll_init();
00058     netsnmp_container_null_init();
00059 
00060     /*
00061      * default aliases for some containers
00062      */
00063     netsnmp_container_register("table_container",
00064                                netsnmp_container_get_factory("binary_array"));
00065     netsnmp_container_register("linked_list",
00066                                netsnmp_container_get_factory("sorted_singly_linked_list"));
00067     netsnmp_container_register("ssll_container",
00068                                netsnmp_container_get_factory("sorted_singly_linked_list"));
00069 
00070     netsnmp_container_register_with_compare
00071         ("string", netsnmp_container_get_factory("binary_array"),
00072          netsnmp_compare_cstring);
00073     netsnmp_container_register_with_compare
00074         ("string:binary_array", netsnmp_container_get_factory("binary_array"),
00075          netsnmp_compare_cstring);
00076 
00077 }
00078 
00079 void
00080 netsnmp_container_free_list(void)
00081 {
00082     DEBUGMSGTL(("container", "netsnmp_container_free_list() called\n"));
00083     if (containers == NULL)
00084         return;
00085 
00086     /*
00087      * free memory used by each factory entry
00088      */
00089     CONTAINER_FOR_EACH(containers, ((netsnmp_container_obj_func *)_factory_free), NULL);
00090 
00091     /*
00092      * free factory container
00093      */
00094     CONTAINER_FREE(containers);
00095     containers = NULL;
00096 }
00097 
00098 int
00099 netsnmp_container_register_with_compare(const char* name, netsnmp_factory *f,
00100                                         netsnmp_container_compare  *c)
00101 {
00102     container_type *ct, tmp;
00103 
00104     tmp.name = (char *)name;
00105     ct = CONTAINER_FIND(containers, &tmp);
00106     if (NULL!=ct) {
00107         DEBUGMSGT(("container_registry",
00108                    "replacing previous container factory\n"));
00109         ct->factory = f;
00110     }
00111     else {
00112         ct = SNMP_MALLOC_TYPEDEF(container_type);
00113         if (NULL == ct)
00114             return -1;
00115         ct->name = strdup(name);
00116         ct->factory = f;
00117         ct->compare = c;
00118         CONTAINER_INSERT(containers, ct);
00119     }
00120     DEBUGMSGT(("container_registry", "registered container factory %s (%s)\n",
00121                ct->name, f->product));
00122 
00123     return 0;
00124 }
00125 
00126 int
00127 netsnmp_container_register(const char* name, netsnmp_factory *f)
00128 {
00129     return netsnmp_container_register_with_compare(name, f, NULL);
00130 }
00131 
00132 /*------------------------------------------------------------------
00133  */
00134 netsnmp_factory *
00135 netsnmp_container_get_factory(const char *type)
00136 {
00137     container_type ct, *found;
00138     
00139     ct.name = type;
00140     found = CONTAINER_FIND(containers, &ct);
00141 
00142     return found ? found->factory : NULL;
00143 }
00144 
00145 netsnmp_factory *
00146 netsnmp_container_find_factory(const char *type_list)
00147 {
00148     netsnmp_factory   *f = NULL;
00149     char              *list, *entry;
00150     char              *st;
00151 
00152     if (NULL==type_list)
00153         return NULL;
00154 
00155     list = strdup(type_list);
00156     entry = strtok_r(list, ":", &st);
00157     while(entry) {
00158         f = netsnmp_container_get_factory(entry);
00159         if (NULL != f)
00160             break;
00161         entry = strtok_r(NULL, ":", &st);
00162     }
00163 
00164     free(list);
00165     return f;
00166 }
00167 
00168 /*------------------------------------------------------------------
00169  */
00170 static container_type *
00171 netsnmp_container_get_ct(const char *type)
00172 {
00173     container_type ct;
00174     
00175     ct.name = type;
00176     return CONTAINER_FIND(containers, &ct);
00177 }
00178 
00179 static container_type *
00180 netsnmp_container_find_ct(const char *type_list)
00181 {
00182     container_type    *ct = NULL;
00183     char              *list, *entry;
00184     char              *st;
00185 
00186     if (NULL==type_list)
00187         return NULL;
00188 
00189     list = strdup(type_list);
00190     entry = strtok_r(list, ":", &st);
00191     while(entry) {
00192         ct = netsnmp_container_get_ct(entry);
00193         if (NULL != ct)
00194             break;
00195         entry = strtok_r(NULL, ":", &st);
00196     }
00197 
00198     free(list);
00199     return ct;
00200 }
00201 
00202 
00203 
00204 /*------------------------------------------------------------------
00205  */
00206 netsnmp_container *
00207 netsnmp_container_get(const char *type)
00208 {
00209     netsnmp_container *c;
00210     container_type *ct = netsnmp_container_get_ct(type);
00211     if (ct) {
00212         c = ct->factory->produce();
00213         if (c && ct->compare)
00214             c->compare = ct->compare;
00215         return c;
00216     }
00217 
00218     return NULL;
00219 }
00220 
00221 /*------------------------------------------------------------------
00222  */
00223 netsnmp_container *
00224 netsnmp_container_find(const char *type)
00225 {
00226     container_type *ct = netsnmp_container_find_ct(type);
00227     netsnmp_container *c = ct ? ct->factory->produce() : NULL;
00228 
00229     /*
00230      * provide default compare
00231      */
00232     if (c) {
00233         if (ct->compare)
00234             c->compare = ct->compare;
00235         else if (NULL == c->compare)
00236             c->compare = netsnmp_compare_netsnmp_index;
00237     }
00238 
00239     return c;
00240 }
00241 
00242 /*------------------------------------------------------------------
00243  */
00244 void
00245 netsnmp_container_add_index(netsnmp_container *primary,
00246                             netsnmp_container *new_index)
00247 {
00248     netsnmp_container *curr = primary;
00249 
00250     if((NULL == new_index) || (NULL == primary)) {
00251         snmp_log(LOG_ERR, "add index called with null pointer\n");
00252         return;
00253     }
00254 
00255     while(curr->next)
00256         curr = curr->next;
00257 
00258     curr->next = new_index;
00259     new_index->prev = curr;
00260 }
00261 
00262 #ifndef NETSNMP_USE_INLINE /* default is to inline */
00263 
00264 /*------------------------------------------------------------------
00265  * These functions should EXACTLY match the inline version in
00266  * container.h. If you change one, change them both.
00267  */
00268 int CONTAINER_INSERT(netsnmp_container *x, const void *k)
00269 { 
00270     int rc2, rc = 0;
00271     
00273     while(x->prev)
00274         x = x->prev;
00275     for(; x; x = x->next) {
00276         if ((NULL != x->insert_filter) &&
00277             (x->insert_filter(x,k) == 1))
00278             continue;
00279         rc2 = x->insert(x,k);
00280         if (rc2) {
00281             snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
00282                      x->container_name ? x->container_name : "", rc2);
00283             rc = rc2;
00284         }
00285     }
00286     return rc;
00287 }
00288 
00289 int CONTAINER_TRY_INSERT(netsnmp_container *x, const void *k)
00290 {
00291     const void *res = NULL;
00292 
00293     netsnmp_container *start;
00295     while(x->prev)
00296         x = x->prev;
00297 
00298     start = x;
00299 
00300     for(; x; x = x->next) {
00301         if ((NULL != x->insert_filter) &&
00302             (x->insert_filter(x,k) == 1))
00303             continue;
00304         res = x->find(x,k);
00305         if (res) {
00306             return -1;
00307         }
00308     }
00309     return CONTAINER_INSERT(start, k);
00310 }
00311 
00312 /*------------------------------------------------------------------
00313  * These functions should EXACTLY match the inline version in
00314  * container.h. If you change one, change them both.
00315  */
00316 int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
00317 {
00318     int rc2, rc = 0;
00319     
00321     while(x->next)
00322         x = x->next;
00323     while(x) {
00324         rc2 = x->remove(x,k);
00326         if ((rc2) && (NULL == x->insert_filter)) {
00327             snmp_log(LOG_ERR,"error on subcontainer remove (%d)\n", rc2);
00328             rc = rc2;
00329         }
00330         x = x->prev;
00331         
00332     }
00333     return rc;
00334 }
00335 
00336 /*------------------------------------------------------------------
00337  * These functions should EXACTLY match the inline version in
00338  * container.h. If you change one, change them both.
00339  */
00340 int CONTAINER_FREE(netsnmp_container *x)
00341 {
00342     int  rc2, rc = 0;
00343         
00345     while(x->next)
00346         x = x->next;
00347     while(x) {
00348         netsnmp_container *tmp;
00349         tmp = x->prev;
00350         if (NULL != x->container_name)
00351             SNMP_FREE(x->container_name);
00352         rc2 = x->cfree(x);
00353         if (rc2) {
00354             snmp_log(LOG_ERR,"error on subcontainer cfree (%d)\n", rc2);
00355             rc = rc2;
00356         }
00357         x = tmp;
00358     }
00359     return rc;
00360 }
00361 
00362 /*------------------------------------------------------------------
00363  * These functions should EXACTLY match the function version in
00364  * container.c. If you change one, change them both.
00365  */
00366 /*
00367  * clear all containers. When clearing the *first* container, and
00368  * *only* the first container, call the function f for each item.
00369  * After calling this function, all containers should be empty.
00370  */
00371 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00372                     void *c)
00373 {
00375     while(x->next)
00376         x = x->next;
00377     while(x->prev) {
00378         x->clear(x, NULL, c);
00379         x = x->prev;
00380     }
00381     x->clear(x, f, c);
00382 }
00383 
00384 /*------------------------------------------------------------------
00385  * These functions should EXACTLY match the function version in
00386  * container.c. If you change one, change them both.
00387  */
00388 /*
00389  * Find a sub-container with the given name
00390  */
00391 netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
00392                                      const char* name)
00393 {
00394     if ((NULL == x) || (NULL == name))
00395         return NULL;
00396     
00398     while(x->prev)
00399         x = x->prev;
00400     while(x) {
00401         if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
00402             break;
00403         x = x->next;
00404     }
00405     return x;
00406 }
00407 #endif
00408 
00409 
00410 /*------------------------------------------------------------------
00411  */
00412 void
00413 netsnmp_init_container(netsnmp_container         *c,
00414                        netsnmp_container_rc      *init,
00415                        netsnmp_container_rc      *cfree,
00416                        netsnmp_container_size    *size,
00417                        netsnmp_container_compare *cmp,
00418                        netsnmp_container_op      *ins,
00419                        netsnmp_container_op      *rem,
00420                        netsnmp_container_rtn     *fnd)
00421 {
00422     if (c == NULL)
00423         return;
00424 
00425     c->init = init;
00426     c->cfree = cfree;
00427     c->get_size = size;
00428     c->compare = cmp;
00429     c->insert = ins;
00430     c->remove = rem;
00431     c->find = fnd;
00432 }
00433 
00434 /*------------------------------------------------------------------
00435  *
00436  * simple comparison routines
00437  *
00438  */
00439 int
00440 netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs)
00441 {
00442     int rc;
00443     netsnmp_assert((NULL != lhs) && (NULL != rhs));
00444     DEBUGIF("compare:index") {
00445         DEBUGMSGT(("compare:index", "compare "));
00446         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00447                      ((const netsnmp_index *) lhs)->len));
00448         DEBUGMSG(("compare:index", " to "));
00449         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00450                      ((const netsnmp_index *) rhs)->len));
00451         DEBUGMSG(("compare:index", "\n"));
00452     }
00453     rc = snmp_oid_compare(((const netsnmp_index *) lhs)->oids,
00454                           ((const netsnmp_index *) lhs)->len,
00455                           ((const netsnmp_index *) rhs)->oids,
00456                           ((const netsnmp_index *) rhs)->len);
00457     DEBUGMSGT(("compare:index", "result was %d\n", rc));
00458     return rc;
00459 }
00460 
00461 int
00462 netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs)
00463 {
00464     int rc;
00465     netsnmp_assert((NULL != lhs) && (NULL != rhs));
00466     DEBUGIF("compare:index") {
00467         DEBUGMSGT(("compare:index", "compare "));
00468         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
00469                      ((const netsnmp_index *) lhs)->len));
00470         DEBUGMSG(("compare:index", " to "));
00471         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
00472                      ((const netsnmp_index *) rhs)->len));
00473         DEBUGMSG(("compare:index", "\n"));
00474     }
00475     rc = snmp_oid_ncompare(((const netsnmp_index *) lhs)->oids,
00476                            ((const netsnmp_index *) lhs)->len,
00477                            ((const netsnmp_index *) rhs)->oids,
00478                            ((const netsnmp_index *) rhs)->len,
00479                            ((const netsnmp_index *) rhs)->len);
00480     DEBUGMSGT(("compare:index", "result was %d\n", rc));
00481     return rc;
00482 }
00483 
00484 int
00485 netsnmp_compare_cstring(const void * lhs, const void * rhs)
00486 {
00487     return strcmp(((const container_type*)lhs)->name,
00488                   ((const container_type*)rhs)->name);
00489 }
00490 
00491 int
00492 netsnmp_ncompare_cstring(const void * lhs, const void * rhs)
00493 {
00494     return strncmp(((const container_type*)lhs)->name,
00495                    ((const container_type*)rhs)->name,
00496                    strlen(((const container_type*)rhs)->name));
00497 }
00498 
00499 /*
00500  * compare two memory buffers
00501  *
00502  * since snmp strings aren't NULL terminated, we can't use strcmp. So
00503  * compare up to the length of the smaller, and then use length to
00504  * break any ties.
00505  */
00506 int
00507 netsnmp_compare_mem(const char * lhs, size_t lhs_len,
00508                     const char * rhs, size_t rhs_len)
00509 {
00510     int rc, min = SNMP_MIN(lhs_len, rhs_len);
00511 
00512     rc = memcmp(lhs, rhs, min);
00513     if((rc==0) && (lhs_len != rhs_len)) {
00514         if(lhs_len < rhs_len)
00515             rc = -1;
00516         else
00517             rc = 1;
00518     }
00519 
00520     return rc;
00521 }
00522 
00523 /*------------------------------------------------------------------
00524  * netsnmp_container_simple_free
00525  *
00526  * useful function to pass to CONTAINER_FOR_EACH, when a simple
00527  * free is needed for every item.
00528  */
00529 void 
00530 netsnmp_container_simple_free(void *data, void *context)
00531 {
00532     if (data == NULL)
00533         return;
00534     
00535     DEBUGMSGTL(("verbose:container",
00536                 "netsnmp_container_simple_free) called for %p/%p\n",
00537                 data, context));
00538     free((void*)data); /* SNMP_FREE wasted on param */
00539 }

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