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