net-snmp
5.4.1
|
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