00001 #ifndef NETSNMP_CONTAINER_H 00002 #define NETSNMP_CONTAINER_H 00003 00004 /* 00005 * $Id: container_8h-source.html 14005 2005-12-30 19:14:23Z alex_b $ 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 returning an int for an operation on a container 00035 */ 00036 typedef int (netsnmp_container_option)(struct netsnmp_container_s *, 00037 int set, u_int flags); 00038 00039 /* 00040 * function returning an int for an operation on a container 00041 */ 00042 typedef int (netsnmp_container_rc)(struct netsnmp_container_s *); 00043 00044 /* 00045 * function returning an iterator for a container 00046 */ 00047 typedef struct netsnmp_iterator_s * (netsnmp_container_it) 00048 (struct netsnmp_container_s *); 00049 00050 /* 00051 * function returning a size_t for an operation on a container 00052 */ 00053 typedef size_t (netsnmp_container_size)(struct netsnmp_container_s *); 00054 00055 /* 00056 * function returning an int for an operation on an object and 00057 * a container 00058 */ 00059 typedef int (netsnmp_container_op)(struct netsnmp_container_s *, 00060 const void *data); 00061 00062 /* 00063 * function returning an oject for an operation on an object and a 00064 * container 00065 */ 00066 typedef void * (netsnmp_container_rtn)(struct netsnmp_container_s *, 00067 const void *data); 00068 00069 /* 00070 * function with no return which acts on an object 00071 */ 00072 typedef void (netsnmp_container_obj_func)(void *data, void *context); 00073 00074 /* 00075 * function with no return which calls a function on an object 00076 */ 00077 typedef void (netsnmp_container_func)(struct netsnmp_container_s *, 00078 netsnmp_container_obj_func *, 00079 void *context); 00080 00081 /* 00082 * function returning an array of objects for an operation on an 00083 * ojbect and a container 00084 */ 00085 typedef netsnmp_void_array * (netsnmp_container_set) 00086 (struct netsnmp_container_s *, void *data); 00087 00088 /* 00089 * function returning an int for a comparison between two objects 00090 */ 00091 typedef int (netsnmp_container_compare)(const void *lhs, 00092 const void *rhs); 00093 00094 /************************************************************************* 00095 * 00096 * Basic container 00097 * 00098 *************************************************************************/ 00099 typedef struct netsnmp_container_s { 00100 00101 /* 00102 * pointer for container implementation 00103 */ 00104 void * container_data; 00105 00106 /* 00107 * returns the number of items in a container 00108 */ 00109 netsnmp_container_size *get_size; 00110 00111 /* 00112 * initialize a container 00113 */ 00114 netsnmp_container_rc *init; 00115 00116 /* 00117 * release memory used by a container. 00118 * 00119 * Note: if your data structures contained allocated 00120 * memory, you are responsible for releasing that 00121 * memory before calling this function! 00122 */ 00123 netsnmp_container_rc *cfree; 00124 00125 /* 00126 * add an entry to the container 00127 */ 00128 netsnmp_container_op *insert; 00129 00130 /* 00131 * remove an entry from the container 00132 */ 00133 netsnmp_container_op *remove; 00134 00135 /* 00136 * release memory for an entry from the container 00137 */ 00138 netsnmp_container_op *release; 00139 00140 /* 00141 * Note: do not change the key! If you need to 00142 * change a key, remove the entry, change the key, 00143 * and the re-add the entry. 00144 */ 00145 00146 /* 00147 * find the entry in the container with the same key 00148 * 00149 */ 00150 netsnmp_container_rtn *find; 00151 00152 /* 00153 * find the entry in the container with the next highest key 00154 * 00155 * If the key is NULL, return the first item in the container. 00156 */ 00157 netsnmp_container_rtn *find_next; 00158 00159 /* 00160 * find all entries in the container which match the partial key 00161 * returns allocated memory (netsnmp_void_array). User is responsible 00162 * for releasing this memory (free(array->array), free(array)). 00163 * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers 00164 * stored in the container. 00165 */ 00166 netsnmp_container_set *get_subset; 00167 00168 /* 00169 * function to return an iterator for the container 00170 */ 00171 netsnmp_container_it *get_iterator; 00172 00173 /* 00174 * function to call another function for each object in the container 00175 */ 00176 netsnmp_container_func *for_each; 00177 00178 /* 00179 * specialized version of for_each used to optimize cleanup. 00180 * clear the container, optionally calling a function for each item. 00181 */ 00182 netsnmp_container_func *clear; 00183 00184 /* 00185 * OPTIONAL function to filter inserts to the container 00186 * (intended for a secondary container, which only wants 00187 * a sub-set of the objects in the primary/parent container) 00188 * Returns: 00189 * 1 : filter matched (don't insert) 00190 * 0 : no match (insert) 00191 */ 00192 netsnmp_container_op *insert_filter; 00193 00194 /* 00195 * function to compare two object stored in the container. 00196 * 00197 * Returns: 00198 * 00199 * -1 LHS < RHS 00200 * 0 LHS = RHS 00201 * 1 LHS > RHS 00202 */ 00203 netsnmp_container_compare *compare; 00204 00205 /* 00206 * same as compare, but RHS will be a partial key 00207 */ 00208 netsnmp_container_compare *ncompare; 00209 00210 /* 00211 * function to set container options 00212 */ 00213 netsnmp_container_option *options; 00214 00215 /* 00216 * unique name for finding a particular container in a list 00217 */ 00218 char *container_name; 00219 00220 /* 00221 * sort count, for iterators to track (insert/delete 00222 * bumps coutner, invalidates iterator 00223 */ 00224 u_long sync; 00225 00226 /* 00227 * containers can contain other containers (additional indexes) 00228 */ 00229 struct netsnmp_container_s *next, *prev; 00230 00231 } netsnmp_container; 00232 00233 /* 00234 * initialize/free a container of container factories. used by 00235 * netsnmp_container_find* functions. 00236 */ 00237 void netsnmp_container_init_list(void); 00238 void netsnmp_container_free_list(void); 00239 00240 /* 00241 * register a new container factory 00242 */ 00243 int netsnmp_container_register_with_compare(const char* name, 00244 netsnmp_factory *f, 00245 netsnmp_container_compare *c); 00246 int netsnmp_container_register(const char* name, netsnmp_factory *f); 00247 00248 /* 00249 * search for and create a container from a list of types or a 00250 * specific type. 00251 */ 00252 netsnmp_container * netsnmp_container_find(const char *type_list); 00253 netsnmp_container * netsnmp_container_get(const char *type); 00254 00255 /* 00256 * utility routines 00257 */ 00258 void netsnmp_container_add_index(netsnmp_container *primary, 00259 netsnmp_container *new_index); 00260 00261 00262 netsnmp_factory *netsnmp_container_get_factory(const char *type); 00263 00264 /* 00265 * common comparison routines 00266 */ 00268 int netsnmp_compare_netsnmp_index(const void *lhs, const void *rhs); 00269 int netsnmp_ncompare_netsnmp_index(const void *lhs, const void *rhs); 00270 00272 int netsnmp_compare_cstring(const void * lhs, const void * rhs); 00273 int netsnmp_ncompare_cstring(const void * lhs, const void * rhs); 00274 00276 int netsnmp_compare_mem(const char * lhs, size_t lhs_len, 00277 const char * rhs, size_t rhs_len); 00278 00280 void netsnmp_container_simple_free(void *data, void *context); 00281 00282 /* 00283 * container optionflags 00284 */ 00285 #define CONTAINER_KEY_ALLOW_DUPLICATES 0x00000001 00286 #define CONTAINER_KEY_UNSORTED 0x00000002 00287 00288 #define CONTAINER_SET_OPTIONS(x,o,rc) do { \ 00289 if (NULL==(x)->options) \ 00290 rc = -1; \ 00291 else \ 00292 rc = (x)->options(x, 1, o); \ 00293 } while(0) 00294 00295 #define CONTAINER_CHECK_OPTION(x,o,rc) do { \ 00296 if (NULL==(x)->options) \ 00297 rc = -1; \ 00298 else \ 00299 rc = (x)->options(x,0, o); \ 00300 } while(0) 00301 00302 00303 /* 00304 * useful macros (x = container; k = key; c = user context) 00305 */ 00306 #define CONTAINER_FIRST(x) (x)->find_next(x,NULL) 00307 #define CONTAINER_FIND(x,k) (x)->find(x,k) 00308 #define CONTAINER_NEXT(x,k) (x)->find_next(x,k) 00309 /* 00310 * GET_SUBSET returns allocated memory (netsnmp_void_array). User is responsible 00311 * for releasing this memory (free(array->array), free(array)). 00312 * DO NOT FREE ELEMENTS OF THE ARRAY, because they are the same pointers 00313 * stored in the container. 00314 */ 00315 #define CONTAINER_GET_SUBSET(x,k) (x)->get_subset(x,k) 00316 #define CONTAINER_SIZE(x) (x)->get_size(x) 00317 #define CONTAINER_ITERATOR(x) (x)->get_iterator(x) 00318 #define CONTAINER_COMPARE(x,l,r) (x)->compare(l,r) 00319 #define CONTAINER_FOR_EACH(x,f,c) (x)->for_each(x,f,c) 00320 00321 /* 00322 * if you are getting multiple definitions of these three 00323 * inline functions, you most likely have optimizations turned off. 00324 * Either turn them back on, or define NETSNMP_NO_INLINE 00325 */ 00326 #ifndef NETSNMP_USE_INLINE /* default is to inline */ 00327 /* 00328 * insert k into all containers 00329 */ 00330 int CONTAINER_INSERT(netsnmp_container *x, const void *k); 00331 00332 /* 00333 * remove k from all containers 00334 */ 00335 int CONTAINER_REMOVE(netsnmp_container *x, const void *k); 00336 00337 /* 00338 * clear all containers. When clearing the *first* container, and 00339 * *only* the first container, call the function f for each item. 00340 * After calling this function, all containers should be empty. 00341 */ 00342 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f, 00343 void *c); 00344 /* 00345 * free all containers 00346 */ 00347 int CONTAINER_FREE(netsnmp_container *x); 00348 #else 00349 /*------------------------------------------------------------------ 00350 * These functions should EXACTLY match the function version in 00351 * container.c. If you change one, change them both. 00352 */ 00353 NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 00354 int CONTAINER_INSERT(netsnmp_container *x, const void *k) 00355 { 00356 int rc2, rc = 0; 00357 00359 while(x->prev) 00360 x = x->prev; 00361 for(; x; x = x->next) { 00362 if ((NULL != x->insert_filter) && 00363 (x->insert_filter(x,k) == 1)) 00364 continue; 00365 rc2 = x->insert(x,k); 00366 if (rc2) { 00367 snmp_log(LOG_ERR,"error on subcontainer '%s' insert (%d)\n", 00368 x->container_name ? x->container_name : "", rc2); 00369 rc = rc2; 00370 } 00371 } 00372 return rc; 00373 } 00374 00375 /*------------------------------------------------------------------ 00376 * These functions should EXACTLY match the function version in 00377 * container.c. If you change one, change them both. 00378 */ 00379 NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 00380 int CONTAINER_REMOVE(netsnmp_container *x, const void *k) 00381 { 00382 int rc2, rc = 0; 00383 00385 while(x->next) 00386 x = x->next; 00387 while(x) { 00388 rc2 = x->remove(x,k); 00390 if ((rc2) && (NULL == x->insert_filter)) { 00391 snmp_log(LOG_ERR,"error on subcontainer remove (%d)\n", rc2); 00392 rc = rc2; 00393 } 00394 x = x->prev; 00395 00396 } 00397 return rc; 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_FREE(netsnmp_container *x) 00406 { 00407 int rc2, rc = 0; 00408 00410 while(x->next) 00411 x = x->next; 00412 while(x) { 00413 netsnmp_container *tmp; 00414 tmp = x->prev; 00415 if (NULL != x->container_name) 00416 SNMP_FREE(x->container_name); 00417 rc2 = x->cfree(x); 00418 if (rc2) { 00419 snmp_log(LOG_ERR,"error on subcontainer cfree (%d)\n", rc2); 00420 rc = rc2; 00421 } 00422 x = tmp; 00423 } 00424 return rc; 00425 } 00426 00427 /*------------------------------------------------------------------ 00428 * These functions should EXACTLY match the function version in 00429 * container.c. If you change one, change them both. 00430 */ 00431 /* 00432 * clear all containers. When clearing the *first* container, and 00433 * *only* the first container, call the function f for each item. 00434 * After calling this function, all containers should be empty. 00435 */ 00436 NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 00437 void CONTAINER_CLEAR(netsnmp_container *x, netsnmp_container_obj_func *f, 00438 void *c) 00439 { 00441 while(x->next) 00442 x = x->next; 00443 while(x->prev) { 00444 x->clear(x, NULL, c); 00445 x = x->prev; 00446 } 00447 x->clear(x, f, c); 00448 } 00449 00450 /*------------------------------------------------------------------ 00451 * These functions should EXACTLY match the function version in 00452 * container.c. If you change one, change them both. 00453 */ 00454 /* 00455 * Find a sub-container with the given name 00456 */ 00457 NETSNMP_STATIC_INLINE /* gcc docs recommend static w/inline */ 00458 netsnmp_container *SUBCONTAINER_FIND(netsnmp_container *x, 00459 const char* name) 00460 { 00461 if ((NULL == x) || (NULL == name)) 00462 return NULL; 00463 00465 while(x->prev) 00466 x = x->prev; 00467 while(x) { 00468 if ((NULL != x->container_name) && 00469 (0 == strcmp(name,x->container_name))) 00470 break; 00471 x = x->next; 00472 } 00473 return x; 00474 } 00475 00476 #endif 00477 00478 /************************************************************************* 00479 * 00480 * container iterator 00481 * 00482 *************************************************************************/ 00483 /* 00484 * function returning an int for an operation on an iterator 00485 */ 00486 typedef int (netsnmp_iterator_rc)(struct netsnmp_iterator_s *); 00487 00488 /* 00489 * function returning an oject for an operation on an iterator 00490 */ 00491 typedef void * (netsnmp_iterator_rtn)(struct netsnmp_iterator_s *); 00492 00493 00494 /* 00495 * iterator structure 00496 */ 00497 typedef struct netsnmp_iterator_s { 00498 00499 netsnmp_container *container; 00500 00501 /* 00502 * sync from container when iterator created. used to invalidate 00503 * the iterator when the container changes. 00504 */ 00505 u_long sync; 00506 00507 /* 00508 * reset iterator position to beginning of container. 00509 */ 00510 netsnmp_iterator_rc *reset; 00511 00512 /* 00513 * release iterator and memory it uses 00514 */ 00515 netsnmp_iterator_rc *release; 00516 00517 /* 00518 * first, last and current DO NOT advance the iterator 00519 */ 00520 netsnmp_iterator_rtn *first; 00521 netsnmp_iterator_rtn *curr; 00522 netsnmp_iterator_rtn *last; 00523 00524 netsnmp_iterator_rtn *next; 00525 00526 } netsnmp_iterator; 00527 00528 00529 #define ITERATOR_FIRST(x) x->first(x) 00530 #define ITERATOR_NEXT(x) x->next(x) 00531 #define ITERATOR_LAST(x) x->last(x) 00532 #define ITERATOR_RELEASE(x) do { x->release(x); x = NULL; } while(0) 00533 00534 #ifdef __cplusplus 00535 } 00536 #endif 00537 00538 #endif
1.3.9.1
Last modified: Thursday, 01-Mar-2007 16:20:05 PST
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.