container.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:12k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. #include <net-snmp/net-snmp-config.h>
  2. #include <net-snmp/net-snmp-includes.h>
  3. #include <net-snmp/library/container.h>
  4. #include <net-snmp/library/container_binary_array.h>
  5. #include <net-snmp/library/container_list_ssll.h>
  6. #include <net-snmp/library/container_null.h>
  7. /*------------------------------------------------------------------
  8.  */
  9. static netsnmp_container *containers = NULL;
  10. typedef struct container_type_s {
  11.    const char                 *name;
  12.    netsnmp_factory            *factory;
  13. } container_type;
  14. netsnmp_factory *
  15. netsnmp_container_get_factory(const char *type);
  16. /*------------------------------------------------------------------
  17.  */
  18. static void 
  19. _factory_free(void *dat, void *context)
  20. {
  21.     container_type *data = (container_type *)dat;
  22.     if (data == NULL)
  23. return;
  24.     
  25.     if (data->name != NULL) {
  26.         DEBUGMSGTL(("container", "  _factory_free_list() called for %sn",
  27.                     data->name));
  28. free((void *)data->name); /* SNMP_FREE wasted on object about to be freed */
  29.     }
  30.     free(data); /* SNMP_FREE wasted on param */
  31. }
  32. /*------------------------------------------------------------------
  33.  */
  34. void
  35. netsnmp_container_init_list(void)
  36. {
  37.     if (NULL != containers)
  38.         return;
  39.     /*
  40.      * create a binary arry container to hold container
  41.      * factories
  42.      */
  43.     containers = netsnmp_container_get_binary_array();
  44.     containers->compare = netsnmp_compare_cstring;
  45.     /*
  46.      * register containers
  47.      */
  48.     netsnmp_container_binary_array_init();
  49.     netsnmp_container_ssll_init();
  50.     netsnmp_container_null_init();
  51.     /*
  52.      * default aliases for some containers
  53.      */
  54.     netsnmp_container_register("table_container",
  55.                                netsnmp_container_get_factory("binary_array"));
  56.     netsnmp_container_register("linked_list",
  57.                                netsnmp_container_get_factory("sorted_singly_linked_list"));
  58.     netsnmp_container_register("ssll_container",
  59.                                netsnmp_container_get_factory("sorted_singly_linked_list"));
  60. }
  61. void
  62. netsnmp_container_free_list(void)
  63. {
  64.     DEBUGMSGTL(("container", "netsnmp_container_free_list() calledn"));
  65.     if (containers == NULL)
  66. return;
  67.     /*
  68.      * free memory used by each factory entry
  69.      */
  70.     CONTAINER_FOR_EACH(containers, _factory_free, NULL);
  71.     /*
  72.      * free factory container
  73.      */
  74.     CONTAINER_FREE(containers);
  75.     containers = NULL;
  76. }
  77. int
  78. netsnmp_container_register(const char* name, netsnmp_factory *f)
  79. {
  80.     container_type *ct, tmp;
  81.     tmp.name = name;
  82.     ct = CONTAINER_FIND(containers, &tmp);
  83.     if (NULL!=ct) {
  84.         DEBUGMSGT(("container_registry",
  85.                    "replacing previous container factoryn"));
  86.         ct->factory = f;
  87.     }
  88.     else {
  89.         ct = SNMP_MALLOC_TYPEDEF(container_type);
  90.         if (NULL == ct)
  91.             return -1;
  92.         ct->name = strdup(name);
  93.         ct->factory = f;
  94.         CONTAINER_INSERT(containers, ct);
  95.     }
  96.     DEBUGMSGT(("container_registry", "registered container factory %s (%s)n",
  97.                ct->name, f->product));
  98.     return 0;
  99. }
  100. /*------------------------------------------------------------------
  101.  */
  102. netsnmp_factory *
  103. netsnmp_container_get_factory(const char *type)
  104. {
  105.     container_type ct, *found;
  106.     
  107.     ct.name = type;
  108.     found = CONTAINER_FIND(containers, &ct);
  109.     return found ? found->factory : NULL;
  110. }
  111. netsnmp_factory *
  112. netsnmp_container_find_factory(const char *type_list)
  113. {
  114.     netsnmp_factory   *f = NULL;
  115.     char              *list, *entry;
  116.     char              *st;
  117.     if (NULL==type_list)
  118.         return NULL;
  119.     list = strdup(type_list);
  120.     entry = strtok_r(list, ":", &st);
  121.     while(entry) {
  122.         f = netsnmp_container_get_factory(entry);
  123.         if (NULL != f)
  124.             break;
  125.         entry = strtok_r(NULL, ":", &st);
  126.     }
  127.     free(list);
  128.     return f;
  129. }
  130. /*------------------------------------------------------------------
  131.  */
  132. netsnmp_container *
  133. netsnmp_container_get(const char *type)
  134. {
  135.     netsnmp_factory *f = netsnmp_container_get_factory(type);
  136.     if (f)
  137.         return f->produce();
  138.     return NULL;
  139. }
  140. /*------------------------------------------------------------------
  141.  */
  142. netsnmp_container *
  143. netsnmp_container_find(const char *type)
  144. {
  145.     netsnmp_factory *f = netsnmp_container_find_factory(type);
  146.     netsnmp_container *c = f ? f->produce() : NULL;
  147.     /*
  148.      * provide default compare
  149.      */
  150.     if (c && (NULL == c->compare))
  151.         c->compare = netsnmp_compare_netsnmp_index;
  152.     return c;
  153. }
  154. /*------------------------------------------------------------------
  155.  */
  156. void
  157. netsnmp_container_add_index(netsnmp_container *primary,
  158.                             netsnmp_container *new_index)
  159. {
  160.     netsnmp_container *curr = primary;
  161.     if((NULL == new_index) || (NULL == primary)) {
  162.         snmp_log(LOG_ERR, "add index called with null pointern");
  163.         return;
  164.     }
  165.     while(curr->next)
  166.         curr = curr->next;
  167.     curr->next = new_index;
  168.     new_index->prev = curr;
  169. }
  170. #ifndef NETSNMP_USE_INLINE /* default is to inline */
  171. /*------------------------------------------------------------------
  172.  * These functions should EXACTLY match the inline version in
  173.  * container.h. If you chance one, change them both.
  174.  */
  175. int CONTAINER_INSERT(netsnmp_container *x, const void *k)
  176.     int rc2, rc = 0;
  177.     
  178.     /** start at first container */
  179.     while(x->prev)
  180.         x = x->prev;
  181.     while(x) {
  182.         rc2 = x->insert(x,k);
  183.         if (rc2) {
  184.             snmp_log(LOG_ERR,"error on subcontainer insert (%d)n", rc2);
  185.             rc = rc2;
  186.         }
  187.         x = x->next;
  188.     }
  189.     return rc;
  190. }
  191. /*------------------------------------------------------------------
  192.  * These functions should EXACTLY match the inline version in
  193.  * container.h. If you chance one, change them both.
  194.  */
  195. int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
  196. {
  197.     int rc2, rc = 0;
  198.     
  199.     /** start at last container */
  200.     while(x->next)
  201.         x = x->next;
  202.     while(x) {
  203.         rc2 = x->remove(x,k);
  204.         if (rc2) {
  205.             snmp_log(LOG_ERR,"error on subcontainer remove (%d)n", rc2);
  206.             rc = rc2;
  207.         }
  208.         x = x->prev;
  209.         
  210.     }
  211.     return rc;
  212. }
  213. /*------------------------------------------------------------------
  214.  * These functions should EXACTLY match the inline version in
  215.  * container.h. If you chance one, change them both.
  216.  */
  217. int CONTAINER_FREE(netsnmp_container *x)
  218. {
  219.     int  rc2, rc = 0;
  220.         
  221.     /** start at last container */
  222.     while(x->next)
  223.         x = x->next;
  224.     while(x) {
  225.         netsnmp_container *tmp;
  226.         tmp = x->prev;
  227.         if (NULL != x->container_name)
  228.             SNMP_FREE(x->container_name);
  229.         rc2 = x->cfree(x);
  230.         if (rc2) {
  231.             snmp_log(LOG_ERR,"error on subcontainer cfree (%d)n", rc2);
  232.             rc = rc2;
  233.         }
  234.         x = tmp;
  235.     }
  236.     return rc;
  237. }
  238. /*------------------------------------------------------------------
  239.  * These functions should EXACTLY match the function version in
  240.  * container.c. If you change one, change them both.
  241.  */
  242. /*
  243.  * clear all containers. When clearing the *first* container, and
  244.  * *only* the first container, call the function f for each item.
  245.  * After calling this function, all containers should be empty.
  246.  */
  247. void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
  248.                     void *c)
  249. {
  250.     /** start at last container */
  251.     while(x->next)
  252.         x = x->next;
  253.     while(x->prev) {
  254.         x->clear(x, NULL, c);
  255.         x = x->prev;
  256.     }
  257.     x->clear(x, f, c);
  258. }
  259. /*------------------------------------------------------------------
  260.  * These functions should EXACTLY match the function version in
  261.  * container.c. If you change one, change them both.
  262.  */
  263. /*
  264.  * Find a sub-container with the given name
  265.  */
  266. netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
  267.                                      const char* name)
  268. {
  269.     if ((NULL == x) || (NULL == name))
  270.         return NULL;
  271.     
  272.     /** start at first container */
  273.     while(x->prev)
  274.         x = x->prev;
  275.     while(x) {
  276.         if ((NULL != x->container_name) && (0 == strcmp(name,x->container_name)))
  277.             break;
  278.         x = x->next;
  279.     }
  280.     return x;
  281. }
  282. #endif
  283. /*------------------------------------------------------------------
  284.  */
  285. void
  286. netsnmp_init_container(netsnmp_container         *c,
  287.                        netsnmp_container_rc      *init,
  288.                        netsnmp_container_rc      *cfree,
  289.                        netsnmp_container_size    *size,
  290.                        netsnmp_container_compare *cmp,
  291.                        netsnmp_container_op      *ins,
  292.                        netsnmp_container_op      *rem,
  293.                        netsnmp_container_rtn     *fnd)
  294. {
  295.     if (c == NULL)
  296.         return;
  297.     c->init = init;
  298.     c->cfree = cfree;
  299.     c->get_size = size;
  300.     c->compare = cmp;
  301.     c->insert = ins;
  302.     c->remove = rem;
  303.     c->find = fnd;
  304. }
  305. /*------------------------------------------------------------------
  306.  *
  307.  * simple comparison routines
  308.  *
  309.  */
  310. int
  311. netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs)
  312. {
  313.     int rc;
  314.     netsnmp_assert((NULL != lhs) && (NULL != rhs));
  315.     DEBUGIF("compare:index") {
  316.         DEBUGMSGT(("compare:index", "compare "));
  317.         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
  318.                      ((const netsnmp_index *) lhs)->len));
  319.         DEBUGMSG(("compare:index", " to "));
  320.         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
  321.                      ((const netsnmp_index *) rhs)->len));
  322.         DEBUGMSG(("compare:index", "n"));
  323.     }
  324.     rc = snmp_oid_compare(((const netsnmp_index *) lhs)->oids,
  325.                           ((const netsnmp_index *) lhs)->len,
  326.                           ((const netsnmp_index *) rhs)->oids,
  327.                           ((const netsnmp_index *) rhs)->len);
  328.     DEBUGMSGT(("compare:index", "result was %dn", rc));
  329.     return rc;
  330. }
  331. int
  332. netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs)
  333. {
  334.     int rc;
  335.     netsnmp_assert((NULL != lhs) && (NULL != rhs));
  336.     DEBUGIF("compare:index") {
  337.         DEBUGMSGT(("compare:index", "compare "));
  338.         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) lhs)->oids,
  339.                      ((const netsnmp_index *) lhs)->len));
  340.         DEBUGMSG(("compare:index", " to "));
  341.         DEBUGMSGSUBOID(("compare:index", ((const netsnmp_index *) rhs)->oids,
  342.                      ((const netsnmp_index *) rhs)->len));
  343.         DEBUGMSG(("compare:index", "n"));
  344.     }
  345.     rc = snmp_oid_ncompare(((const netsnmp_index *) lhs)->oids,
  346.                            ((const netsnmp_index *) lhs)->len,
  347.                            ((const netsnmp_index *) rhs)->oids,
  348.                            ((const netsnmp_index *) rhs)->len,
  349.                            ((const netsnmp_index *) rhs)->len);
  350.     DEBUGMSGT(("compare:index", "result was %dn", rc));
  351.     return rc;
  352. }
  353. int
  354. netsnmp_compare_cstring(const void * lhs, const void * rhs)
  355. {
  356.     return strcmp(((const container_type*)lhs)->name,
  357.                   ((const container_type*)rhs)->name);
  358. }
  359. int
  360. netsnmp_ncompare_cstring(const void * lhs, const void * rhs)
  361. {
  362.     return strncmp(((const container_type*)lhs)->name,
  363.                    ((const container_type*)rhs)->name,
  364.                    strlen(((const container_type*)rhs)->name));
  365. }
  366. /*
  367.  * compare two memory buffers
  368.  *
  369.  * since snmp strings aren't NULL terminated, we can't use strcmp. So
  370.  * compare up to the length of the smaller, and then use length to
  371.  * break any ties.
  372.  */
  373. int
  374. netsnmp_compare_mem(const char * lhs, size_t lhs_len,
  375.                     const char * rhs, size_t rhs_len)
  376. {
  377.     int rc, min = SNMP_MIN(lhs_len, rhs_len);
  378.     rc = memcmp(lhs, rhs, min);
  379.     if((rc==0) && (lhs_len != rhs_len)) {
  380.         if(lhs_len < rhs_len)
  381.             rc = -1;
  382.         else
  383.             rc = 1;
  384.     }
  385.     return rc;
  386. }
  387. /*------------------------------------------------------------------
  388.  * netsnmp_container_simple_free
  389.  *
  390.  * useful function to pass to CONTAINER_FOR_EACH, when a simple
  391.  * free is needed for every item.
  392.  */
  393. void 
  394. netsnmp_container_simple_free(void *data, void *context)
  395. {
  396.     if (data == NULL)
  397. return;
  398.     
  399.     DEBUGMSGTL(("verbose:container",
  400.                 "netsnmp_container_simple_free) called for %p/%pn",
  401.                 data, context));
  402.     free((void*)data); /* SNMP_FREE wasted on param */
  403. }