net-snmp  5.4.1
container.h
00001 #ifndef NETSNMP_CONTAINER_H
00002 #define NETSNMP_CONTAINER_H
00003 
00004 /*
00005  * $Id: container.h 13803 2005-12-04 18:43:04Z rstory $
00006  *
00007  * WARNING: This is a recently created file, and all of it's contents are
00008  *          subject to change at any time.
00009  *
00010  * A basic container template. A generic way for code to store and
00011  * retrieve data. Allows for interchangable storage algorithms.
00012  */
00013 #ifndef NET_SNMP_CONFIG_H
00014 #error "Please include <net-snmp/net-snmp-config.h> before this file"
00015 #endif
00016 
00017 #include <net-snmp/types.h>
00018 #include <net-snmp/library/factory.h>
00019 #include <net-snmp/library/snmp_logging.h>
00020 
00021 #ifdef  __cplusplus
00022 extern "C" {
00023 #endif
00024 
00025     /*************************************************************************
00026      *
00027      * function pointer definitions
00028      *
00029      *************************************************************************/
00030     struct netsnmp_iterator_s; 
00031     struct netsnmp_container_s; 
00033     /*
00034      * function for performing an operation on a container which
00035      * returns (maybe the same) container.
00036      */
00037 
00038     typedef struct netsnmp_container_s* (netsnmp_container_mod_op)
00039       (struct netsnmp_container_s *, void *context, u_int flags);
00040 
00041     /*
00042      * function for setting an option on a container
00043      */
00044     typedef int (netsnmp_container_option)(struct netsnmp_container_s *,
00045                                            int set, u_int flags);
00046 
00047     /*
00048      * function returning an int for an operation on a container
00049      */
00050     typedef int (netsnmp_container_rc)(struct netsnmp_container_s *);
00051 
00052     /*
00053      * function returning an iterator for a container
00054      */
00055     typedef struct netsnmp_iterator_s * (netsnmp_container_it)
00056         (struct netsnmp_container_s *);
00057 
00058     /*
00059      * function returning a size_t for an operation on a container
00060      */
00061     typedef size_t (netsnmp_container_size)(struct netsnmp_container_s *);
00062 
00063     /*
00064      * function returning an int for an operation on an object and
00065      * a container
00066      */
00067     typedef int (netsnmp_container_op)(struct netsnmp_container_s *,
00068                                        const void *data);
00069 
00070     /*
00071      * function returning an oject for an operation on an object and a
00072      * container
00073      */
00074     typedef void * (netsnmp_container_rtn)(struct netsnmp_container_s *,
00075                                            const void *data);
00076 
00077     /*
00078      * function with no return which acts on an object
00079      */
00080     typedef void (netsnmp_container_obj_func)(void *data, void *context);
00081 
00082     /*
00083      * function with no return which calls a function on an object
00084      */
00085     typedef void (netsnmp_container_func)(struct netsnmp_container_s *,
00086                                           netsnmp_container_obj_func *,
00087                                           void *context);
00088 
00089     /*
00090      * function returning an array of objects for an operation on an
00091      * ojbect and a container
00092      */
00093     typedef netsnmp_void_array * (netsnmp_container_set)
00094         (struct netsnmp_container_s *, void *data);
00095 
00096     /*
00097      * function returning an int for a comparison between two objects
00098      */
00099     typedef int (netsnmp_container_compare)(const void *lhs,
00100                                             const void *rhs);
00101 
00102     /*************************************************************************
00103      *
00104      * Basic container
00105      *
00106      *************************************************************************/
00107     typedef struct netsnmp_container_s {
00108        
00109        /*
00110         * pointer for container implementation
00111         */
00112        void *         container_data;
00113 
00114        /*
00115         * returns the number of items in a container
00116         */
00117        netsnmp_container_size  *get_size;
00118        
00119        /*
00120         * initialize a container
00121         */
00122        netsnmp_container_rc    *init;
00123 
00124        /*
00125         * release memory used by a container.
00126         *
00127         * Note: if your data structures contained allocated
00128         * memory, you are responsible for releasing that
00129         * memory before calling this function!
00130         */
00131        netsnmp_container_rc    *cfree;
00132 
00133        /*
00134         * add an entry to the container
00135         */
00136        netsnmp_container_op    *insert;
00137 
00138        /*
00139         * remove an entry from the container
00140         */
00141        netsnmp_container_op    *remove;
00142 
00143        /*
00144         * release memory for an entry from the container
00145         */
00146        netsnmp_container_op    *release;
00147 
00148        /*
00149         * Note: do not change the key!  If you need to
00150         * change a key, remove the entry, change the key,
00151         * and the re-add the entry.
00152         */
00153 
00154        /*
00155         * find the entry in the container with the same key
00156         *
00157         */
00158        netsnmp_container_rtn   *find;
00159 
00160        /*
00161         * find the entry in the container with the next highest key
00162         *
00163         * If the key is NULL, return the first item in the container.
00164         */
00165        netsnmp_container_rtn   *find_next;
00166 
00167        /*
00168         * find all entries in the container which match the partial key
00169         * returns allocated memory (netsnmp_void_array). User is responsible
00170         * for releasing this memory (free(array->array), free(array)).
00171         * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers
00172         * stored in the container.
00173         */
00174        netsnmp_container_set            *get_subset;
00175 
00176        /*
00177         * function to return an iterator for the container
00178         */
00179        netsnmp_container_it           *get_iterator;
00180 
00181        /*
00182         * function to call another function for each object in the container
00183         */
00184        netsnmp_container_func         *for_each;
00185 
00186        /*
00187         * specialized version of for_each used to optimize cleanup.
00188         * clear the container, optionally calling a function for each item.
00189         */
00190        netsnmp_container_func         *clear;
00191 
00192        /*
00193         * OPTIONAL function to filter inserts to the container
00194         *  (intended for a secondary container, which only wants
00195         *   a sub-set of the objects in the primary/parent container)
00196         * Returns:
00197         *   1 : filter matched (don't insert)
00198         *   0 : no match (insert)
00199         */
00200        netsnmp_container_op    *insert_filter;
00201 
00202        /*
00203         * OPTIONAL function to duplicate a container. Defaults to a shallow
00204         * copy. Only the specified container is copied (i.e. sub-containers
00205         * not included).
00206         */
00207 
00208        netsnmp_container_mod_op *duplicate;
00209 
00210        /*
00211         * function to compare two object stored in the container.
00212         *
00213         * Returns:
00214         *
00215         *   -1  LHS < RHS
00216         *    0  LHS = RHS
00217         *    1  LHS > RHS
00218         */
00219        netsnmp_container_compare        *compare;
00220 
00221        /*
00222         * same as compare, but RHS will be a partial key
00223         */
00224        netsnmp_container_compare        *ncompare;
00225 
00226        /*
00227         * function to set container options
00228         */
00229        netsnmp_container_option         *options;
00230 
00231        /*
00232         * unique name for finding a particular container in a list
00233         */
00234        char *container_name;
00235 
00236        /*
00237         * sort count, for iterators to track (insert/delete
00238         * bumps counter, invalidates iterator)
00239         */
00240        u_long                          sync;
00241 
00242        /*
00243         * flags
00244         */
00245        u_int                           flags;
00246 
00247        /*
00248         * containers can contain other containers (additional indexes)
00249         */
00250        struct netsnmp_container_s *next, *prev;
00251 
00252     } netsnmp_container;
00253 
00254     /*
00255      * initialize/free a container of container factories. used by
00256      * netsnmp_container_find* functions.
00257      */
00258     void netsnmp_container_init_list(void);
00259     void netsnmp_container_free_list(void);
00260 
00261     /*
00262      * register a new container factory
00263      */
00264     int netsnmp_container_register_with_compare(const char* name,
00265                                                 netsnmp_factory *f,
00266                                                 netsnmp_container_compare *c);
00267     int netsnmp_container_register(const char* name, netsnmp_factory *f);
00268 
00269     /*
00270      * search for and create a container from a list of types or a
00271      * specific type.
00272      */
00273     netsnmp_container * netsnmp_container_find(const char *type_list);
00274     netsnmp_container * netsnmp_container_get(const char *type);
00275 
00276     /*
00277      * utility routines
00278      */
00279     void netsnmp_container_add_index(netsnmp_container *primary,
00280                                      netsnmp_container *new_index);
00281 
00282 
00283     netsnmp_factory *netsnmp_container_get_factory(const char *type);
00284 
00285     /*
00286      * common comparison routines
00287      */
00289     int netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs);
00290     int netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs);
00291 
00293     int netsnmp_compare_cstring(const void * lhs, const void * rhs);
00294     int netsnmp_ncompare_cstring(const void * lhs, const void * rhs);
00295 
00297     int netsnmp_compare_mem(const char * lhs, size_t lhs_len,
00298                             const char * rhs, size_t rhs_len);
00299 
00301     void  netsnmp_container_simple_free(void *data, void *context);
00302 
00303 /*
00304  * container optionflags
00305  */
00306 #define CONTAINER_KEY_ALLOW_DUPLICATES             0x00000001
00307 #define CONTAINER_KEY_UNSORTED                     0x00000002
00308 
00309 #define CONTAINER_SET_OPTIONS(x,o,rc)  do {                             \
00310         if (NULL==(x)->options)                                         \
00311             rc = -1;                                                    \
00312         else {                                                          \
00313             rc = (x)->options(x, 1, o);                                 \
00314              if (rc != -1 )                                             \
00315                 (x)->flags |= o;                                        \
00316         }                                                               \
00317     } while(0)
00318 
00319 #define CONTAINER_CHECK_OPTION(x,o,rc)    do {                          \
00320         rc = x->flags & 0;                                              \
00321     } while(0)
00322 
00323 
00324     /*
00325      * useful macros (x = container; k = key; c = user context)
00326      */
00327 #define CONTAINER_FIRST(x)          (x)->find_next(x,NULL)
00328 #define CONTAINER_FIND(x,k)         (x)->find(x,k)
00329 #define CONTAINER_NEXT(x,k)         (x)->find_next(x,k)
00330 /*
00331  * GET_SUBSET returns allocated memory (netsnmp_void_array). User is responsible
00332  * for releasing this memory (free(array->array), free(array)).
00333  * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers
00334  * stored in the container.
00335  */
00336 #define CONTAINER_GET_SUBSET(x,k)   (x)->get_subset(x,k)
00337 #define CONTAINER_SIZE(x)           (x)->get_size(x)
00338 #define CONTAINER_ITERATOR(x)       (x)->get_iterator(x)
00339 #define CONTAINER_COMPARE(x,l,r)    (x)->compare(l,r)
00340 #define CONTAINER_FOR_EACH(x,f,c)   (x)->for_each(x,f,c)
00341 
00342     /*
00343      * if you are getting multiple definitions of these three
00344      * inline functions, you most likely have optimizations turned off.
00345      * Either turn them back on, or define NETSNMP_NO_INLINE
00346      */
00347 #ifndef NETSNMP_USE_INLINE /* default is to inline */
00348     /*
00349      * insert k into all containers
00350      */
00351     int CONTAINER_INSERT(netsnmp_container *x, const void *k);
00352 
00353     /*
00354      * remove k from all containers
00355      */
00356     int CONTAINER_REMOVE(netsnmp_container *x, const void *k);
00357 
00358     /*
00359      * duplicate container
00360      */
00361     netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx,
00362                 u_int flags); 
00363 
00364     /*
00365      * clear all containers. When clearing the *first* container, and
00366      * *only* the first container, call the function f for each item.
00367      * After calling this function, all containers should be empty.
00368      */
00369     void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00370                         void *c);
00371     /*
00372      * free all containers
00373      */
00374     int CONTAINER_FREE(netsnmp_container *x);
00375 #else
00376      /*------------------------------------------------------------------
00377       * These functions should EXACTLY match the function version in
00378       * container.c. If you change one, change them both.
00379       */
00380      NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00381      int CONTAINER_INSERT_HELPER(netsnmp_container* x, const void* k)
00382      {
00383          while(x && x->insert_filter && x->insert_filter(x,k) == 1)
00384              x = x->next;
00385          if(x) {
00386              int rc = x->insert(x,k);
00387              if(rc)
00388                  snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n",
00389                           x->container_name ? x->container_name : "", rc);
00390              else {
00391                  rc = CONTAINER_INSERT_HELPER(x->next, k);
00392                  if(rc)
00393                      x->remove(x,k);
00394              }
00395              return rc;
00396          }
00397          return 0;
00398      }
00399  
00400      /*------------------------------------------------------------------
00401       * These functions should EXACTLY match the function version in
00402       * container.c. If you change one, change them both.
00403       */
00404      NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00405      int CONTAINER_INSERT(netsnmp_container* x, const void* k)
00406      {
00408          while(x->prev)
00409              x = x->prev;
00410          return CONTAINER_INSERT_HELPER(x, k);
00411      }
00412     
00413     /*------------------------------------------------------------------
00414      * These functions should EXACTLY match the function version in
00415      * container.c. If you change one, change them both.
00416      */
00417     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00418     int CONTAINER_REMOVE(netsnmp_container *x, const void *k)
00419     {
00420         int rc2, rc = 0;
00421         
00423         while(x->next)
00424             x = x->next;
00425         while(x) {
00426             rc2 = x->remove(x,k);
00428             if ((rc2) && (NULL == x->insert_filter)) {
00429                 snmp_log(LOG_ERR,"error on subcontainer remove (%d)\n", rc2);
00430                 rc = rc2;
00431             }
00432             x = x->prev;
00433             
00434         }
00435         return rc;
00436     }
00437     
00438     /*------------------------------------------------------------------
00439      * These functions should EXACTLY match the function version in
00440      * container.c. If you change one, change them both.
00441      */
00442     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00443     netsnmp_container *CONTAINER_DUP(netsnmp_container *x, void *ctx,
00444                 u_int flags)
00445     {
00446       if (NULL == x->duplicate) {
00447         snmp_log(LOG_ERR, "container '%s' does not support duplicate\n",
00448                 x->container_name ? x->container_name : "");
00449         return NULL;
00450       }
00451       return x->duplicate(x, ctx, flags);
00452     }
00453 
00454     /*------------------------------------------------------------------
00455      * These functions should EXACTLY match the function version in
00456      * container.c. If you change one, change them both.
00457      */
00458     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 
00459     int CONTAINER_FREE(netsnmp_container *x)
00460     {
00461         int  rc2, rc = 0;
00462         
00464         while(x->next)
00465             x = x->next;
00466         while(x) {
00467             netsnmp_container *tmp;
00468             tmp = x->prev;
00469             if (NULL != x->container_name)
00470                 SNMP_FREE(x->container_name);
00471             rc2 = x->cfree(x);
00472             if (rc2) {
00473                 snmp_log(LOG_ERR,"error on subcontainer cfree (%d)\n", rc2);
00474                 rc = rc2;
00475             }
00476             x = tmp;
00477         }
00478         return rc;
00479     }
00480 
00481     /*------------------------------------------------------------------
00482      * These functions should EXACTLY match the function version in
00483      * container.c. If you change one, change them both.
00484      */
00485     /*
00486      * clear all containers. When clearing the *first* container, and
00487      * *only* the first container, call the function f for each item.
00488      * After calling this function, all containers should be empty.
00489      */
00490     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00491     void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f,
00492                         void *c)
00493     {
00495         while(x->next)
00496             x = x->next;
00497         while(x->prev) {
00498             x->clear(x, NULL, c);
00499             x = x->prev;
00500         }
00501         x->clear(x, f, c);
00502     }
00503 
00504     /*------------------------------------------------------------------
00505      * These functions should EXACTLY match the function version in
00506      * container.c. If you change one, change them both.
00507      */
00508     /*
00509      * Find a sub-container with the given name
00510      */
00511     NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */
00512     netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x,
00513                                          const char* name)
00514     {
00515         if ((NULL == x) || (NULL == name))
00516             return NULL;
00517 
00519         while(x->prev)
00520             x = x->prev;
00521         while(x) {
00522             if ((NULL != x->container_name) &&
00523                 (0 == strcmp(name,x->container_name)))
00524                 break;
00525             x = x->next;
00526         }
00527         return x;
00528     }
00529 
00530 #endif
00531 
00533     int netsnmp_container_data_dup(netsnmp_container *dup,
00534         netsnmp_container *c); 
00535     
00536     /*************************************************************************
00537      *
00538      * container iterator
00539      *
00540      *************************************************************************/
00541     /*
00542      * function returning an int for an operation on an iterator
00543      */
00544     typedef int (netsnmp_iterator_rc)(struct netsnmp_iterator_s *);
00545 
00546     /*
00547      * function returning an oject for an operation on an iterator
00548      */
00549     typedef void * (netsnmp_iterator_rtn)(struct netsnmp_iterator_s *);
00550 
00551 
00552     /*
00553      * iterator structure
00554      */
00555     typedef struct netsnmp_iterator_s {
00556 
00557        netsnmp_container              *container;
00558 
00559         /*
00560          * sync from container when iterator created. used to invalidate
00561          * the iterator when the container changes.
00562          */
00563        u_long                          sync;
00564 
00565         /*
00566          * reset iterator position to beginning of container.
00567          */
00568        netsnmp_iterator_rc           *reset;
00569 
00570         /*
00571          * release iterator and memory it uses
00572          */
00573        netsnmp_iterator_rc           *release;
00574 
00575         /*
00576          * first, last and current DO NOT advance the iterator
00577          */
00578        netsnmp_iterator_rtn          *first;
00579        netsnmp_iterator_rtn          *curr;
00580        netsnmp_iterator_rtn          *last;
00581 
00582        netsnmp_iterator_rtn          *next;
00583 
00584     } netsnmp_iterator;
00585 
00586 
00587 #define ITERATOR_FIRST(x)  x->first(x)
00588 #define ITERATOR_NEXT(x)   x->next(x)
00589 #define ITERATOR_LAST(x)   x->last(x)
00590 #define ITERATOR_RELEASE(x) do { x->release(x); x = NULL; } while(0)
00591     
00592 #ifdef  __cplusplus
00593 }
00594 #endif
00595 
00596 #endif