libnl
3.2.3
|
00001 /* 00002 * lib/cache_mngt.c Cache Management 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup core 00014 * @defgroup cache_mngt Caching 00015 * @{ 00016 */ 00017 00018 #include <netlink-local.h> 00019 #include <netlink/netlink.h> 00020 #include <netlink/cache.h> 00021 #include <netlink/utils.h> 00022 00023 static struct nl_cache_ops *cache_ops; 00024 00025 /** 00026 * @name Cache Operations Sets 00027 * @{ 00028 */ 00029 00030 /** 00031 * Lookup the set cache operations of a certain cache type 00032 * @arg name name of the cache type 00033 * 00034 * @return The cache operations or NULL if no operations 00035 * have been registered under the specified name. 00036 */ 00037 struct nl_cache_ops *nl_cache_ops_lookup(const char *name) 00038 { 00039 struct nl_cache_ops *ops; 00040 00041 for (ops = cache_ops; ops; ops = ops->co_next) 00042 if (!strcmp(ops->co_name, name)) 00043 return ops; 00044 00045 return NULL; 00046 } 00047 00048 /** 00049 * Associate a message type to a set of cache operations 00050 * @arg protocol netlink protocol 00051 * @arg msgtype netlink message type 00052 * 00053 * Associates the specified netlink message type with 00054 * a registered set of cache operations. 00055 * 00056 * @return The cache operations or NULL if no association 00057 * could be made. 00058 */ 00059 struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) 00060 { 00061 int i; 00062 struct nl_cache_ops *ops; 00063 00064 for (ops = cache_ops; ops; ops = ops->co_next) { 00065 if (ops->co_protocol != protocol) 00066 continue; 00067 00068 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 00069 if (ops->co_msgtypes[i].mt_id == msgtype) 00070 return ops; 00071 } 00072 00073 return NULL; 00074 } 00075 00076 /** 00077 * Lookup message type cache association 00078 * @arg ops cache operations 00079 * @arg msgtype netlink message type 00080 * 00081 * Searches for a matching message type association ing the specified 00082 * cache operations. 00083 * 00084 * @return A message type association or NULL. 00085 */ 00086 struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) 00087 { 00088 int i; 00089 00090 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 00091 if (ops->co_msgtypes[i].mt_id == msgtype) 00092 return &ops->co_msgtypes[i]; 00093 00094 return NULL; 00095 } 00096 00097 static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops) 00098 { 00099 struct nl_cache_ops *ops; 00100 00101 for (ops = cache_ops; ops; ops = ops->co_next) 00102 if (ops->co_obj_ops == obj_ops) 00103 return ops; 00104 00105 return NULL; 00106 00107 } 00108 00109 /** 00110 * Call a function for each registered cache operation 00111 * @arg cb Callback function to be called 00112 * @arg arg User specific argument. 00113 */ 00114 void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) 00115 { 00116 struct nl_cache_ops *ops; 00117 00118 for (ops = cache_ops; ops; ops = ops->co_next) 00119 cb(ops, arg); 00120 } 00121 00122 /** 00123 * Register a set of cache operations 00124 * @arg ops cache operations 00125 * 00126 * Called by users of caches to announce the avaibility of 00127 * a certain cache type. 00128 * 00129 * @return 0 on success or a negative error code. 00130 */ 00131 int nl_cache_mngt_register(struct nl_cache_ops *ops) 00132 { 00133 if (!ops->co_name || !ops->co_obj_ops) 00134 return -NLE_INVAL; 00135 00136 if (nl_cache_ops_lookup(ops->co_name)) 00137 return -NLE_EXIST; 00138 00139 ops->co_next = cache_ops; 00140 cache_ops = ops; 00141 00142 NL_DBG(1, "Registered cache operations %s\n", ops->co_name); 00143 00144 return 0; 00145 } 00146 00147 /** 00148 * Unregister a set of cache operations 00149 * @arg ops cache operations 00150 * 00151 * Called by users of caches to announce a set of 00152 * cache operations is no longer available. The 00153 * specified cache operations must have been registered 00154 * previously using nl_cache_mngt_register() 00155 * 00156 * @return 0 on success or a negative error code 00157 */ 00158 int nl_cache_mngt_unregister(struct nl_cache_ops *ops) 00159 { 00160 struct nl_cache_ops *t, **tp; 00161 00162 for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) 00163 if (t == ops) 00164 break; 00165 00166 if (!t) 00167 return -NLE_NOCACHE; 00168 00169 NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); 00170 00171 *tp = t->co_next; 00172 return 0; 00173 } 00174 00175 /** @} */ 00176 00177 /** 00178 * @name Global Cache Provisioning/Requiring 00179 * @{ 00180 */ 00181 00182 /** 00183 * Provide a cache for global use 00184 * @arg cache cache to provide 00185 * 00186 * Offers the specified cache to be used by other modules. 00187 * Only one cache per type may be shared at a time, 00188 * a previsouly provided caches will be overwritten. 00189 */ 00190 void nl_cache_mngt_provide(struct nl_cache *cache) 00191 { 00192 struct nl_cache_ops *ops; 00193 00194 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 00195 if (!ops) 00196 BUG(); 00197 else 00198 ops->co_major_cache = cache; 00199 } 00200 00201 /** 00202 * Unprovide a cache for global use 00203 * @arg cache cache to unprovide 00204 * 00205 * Cancels the offer to use a cache globally. The 00206 * cache will no longer be returned via lookups but 00207 * may still be in use. 00208 */ 00209 void nl_cache_mngt_unprovide(struct nl_cache *cache) 00210 { 00211 struct nl_cache_ops *ops; 00212 00213 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 00214 if (!ops) 00215 BUG(); 00216 else if (ops->co_major_cache == cache) 00217 ops->co_major_cache = NULL; 00218 } 00219 00220 struct nl_cache *__nl_cache_mngt_require(const char *name) 00221 { 00222 struct nl_cache_ops *ops; 00223 00224 ops = nl_cache_ops_lookup(name); 00225 if (ops) 00226 return ops->co_major_cache; 00227 00228 return NULL; 00229 } 00230 00231 /** 00232 * Demand the use of a global cache 00233 * @arg name name of the required object type 00234 * 00235 * Trys to find a cache of the specified type for global 00236 * use. 00237 * 00238 * @return A cache provided by another subsystem of the 00239 * specified type marked to be available. 00240 */ 00241 struct nl_cache *nl_cache_mngt_require(const char *name) 00242 { 00243 struct nl_cache *cache; 00244 00245 if (!(cache = __nl_cache_mngt_require(name))) 00246 fprintf(stderr, "Application BUG: Your application must " 00247 "call nl_cache_mngt_provide() and\nprovide a valid " 00248 "%s cache to be used for internal lookups.\nSee the " 00249 " API documentation for more details.\n", name); 00250 00251 return cache; 00252 } 00253 00254 /** @} */ 00255 00256 /** @} */