cache_mngt.c revision d36d396fd0ae94aa2269546a02b5973b4ec27775
1/* 2 * lib/cache_mngt.c Cache Management 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @defgroup cache_mngt Caching 14 * @{ 15 */ 16 17#include <netlink-local.h> 18#include <netlink/netlink.h> 19#include <netlink/cache.h> 20#include <netlink/utils.h> 21 22static struct nl_cache_ops *cache_ops; 23 24/** 25 * @name Cache Operations Sets 26 * @{ 27 */ 28 29/** 30 * Lookup the set cache operations of a certain cache type 31 * @arg name name of the cache type 32 * 33 * @return The cache operations or NULL if no operations 34 * have been registered under the specified name. 35 */ 36struct nl_cache_ops *nl_cache_ops_lookup(const char *name) 37{ 38 struct nl_cache_ops *ops; 39 40 for (ops = cache_ops; ops; ops = ops->co_next) 41 if (!strcmp(ops->co_name, name)) 42 return ops; 43 44 return NULL; 45} 46 47/** 48 * Associate a message type to a set of cache operations 49 * @arg protocol netlink protocol 50 * @arg msgtype netlink message type 51 * 52 * Associates the specified netlink message type with 53 * a registered set of cache operations. 54 * 55 * @return The cache operations or NULL if no association 56 * could be made. 57 */ 58struct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) 59{ 60 int i; 61 struct nl_cache_ops *ops; 62 63 for (ops = cache_ops; ops; ops = ops->co_next) 64 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 65 if (ops->co_msgtypes[i].mt_id == msgtype && 66 ops->co_protocol == protocol) 67 return ops; 68 69 return NULL; 70} 71 72/** 73 * Lookup message type cache association 74 * @arg ops cache operations 75 * @arg msgtype netlink message type 76 * 77 * Searches for a matching message type association ing the specified 78 * cache operations. 79 * 80 * @return A message type association or NULL. 81 */ 82struct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) 83{ 84 int i; 85 86 for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 87 if (ops->co_msgtypes[i].mt_id == msgtype) 88 return &ops->co_msgtypes[i]; 89 90 return NULL; 91} 92 93static struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops) 94{ 95 struct nl_cache_ops *ops; 96 97 for (ops = cache_ops; ops; ops = ops->co_next) 98 if (ops->co_obj_ops == obj_ops) 99 return ops; 100 101 return NULL; 102 103} 104 105/** 106 * Call a function for each registered cache operation 107 * @arg cb Callback function to be called 108 * @arg arg User specific argument. 109 */ 110void nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) 111{ 112 struct nl_cache_ops *ops; 113 114 for (ops = cache_ops; ops; ops = ops->co_next) 115 cb(ops, arg); 116} 117 118/** 119 * Register a set of cache operations 120 * @arg ops cache operations 121 * 122 * Called by users of caches to announce the avaibility of 123 * a certain cache type. 124 * 125 * @return 0 on success or a negative error code. 126 */ 127int nl_cache_mngt_register(struct nl_cache_ops *ops) 128{ 129 if (!ops->co_name) 130 return nl_error(EINVAL, "No cache name specified"); 131 132 if (!ops->co_obj_ops) 133 return nl_error(EINVAL, "No obj cache ops specified"); 134 135 if (nl_cache_ops_lookup(ops->co_name)) 136 return nl_error(EEXIST, "Cache operations already exist"); 137 138 ops->co_next = cache_ops; 139 cache_ops = ops; 140 141 NL_DBG(1, "Registered cache operations %s\n", ops->co_name); 142 143 return 0; 144} 145 146/** 147 * Unregister a set of cache operations 148 * @arg ops cache operations 149 * 150 * Called by users of caches to announce a set of 151 * cache operations is no longer available. The 152 * specified cache operations must have been registered 153 * previously using nl_cache_mngt_register() 154 * 155 * @return 0 on success or a negative error code 156 */ 157int nl_cache_mngt_unregister(struct nl_cache_ops *ops) 158{ 159 struct nl_cache_ops *t, **tp; 160 161 for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) 162 if (t == ops) 163 break; 164 165 if (!t) 166 return nl_error(ENOENT, "No such cache operations"); 167 168 NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); 169 170 *tp = t->co_next; 171 return 0; 172} 173 174/** @} */ 175 176/** 177 * @name Global Cache Provisioning/Requiring 178 * @{ 179 */ 180 181/** 182 * Provide a cache for global use 183 * @arg cache cache to provide 184 * 185 * Offers the specified cache to be used by other modules. 186 * Only one cache per type may be shared at a time, 187 * a previsouly provided caches will be overwritten. 188 */ 189void nl_cache_mngt_provide(struct nl_cache *cache) 190{ 191 struct nl_cache_ops *ops; 192 193 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 194 if (!ops) 195 BUG(); 196 else 197 ops->co_major_cache = cache; 198} 199 200/** 201 * Unprovide a cache for global use 202 * @arg cache cache to unprovide 203 * 204 * Cancels the offer to use a cache globally. The 205 * cache will no longer be returned via lookups but 206 * may still be in use. 207 */ 208void nl_cache_mngt_unprovide(struct nl_cache *cache) 209{ 210 struct nl_cache_ops *ops; 211 212 ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 213 if (!ops) 214 BUG(); 215 else if (ops->co_major_cache == cache) 216 ops->co_major_cache = NULL; 217} 218 219/** 220 * Demand the use of a global cache 221 * @arg name name of the required object type 222 * 223 * Trys to find a cache of the specified type for global 224 * use. 225 * 226 * @return A cache provided by another subsystem of the 227 * specified type marked to be available. 228 */ 229struct nl_cache *nl_cache_mngt_require(const char *name) 230{ 231 struct nl_cache_ops *ops; 232 233 ops = nl_cache_ops_lookup(name); 234 if (!ops || !ops->co_major_cache) { 235 fprintf(stderr, "Application BUG: Your application must " 236 "call nl_cache_mngt_provide() and\nprovide a valid " 237 "%s cache to be used for internal lookups.\nSee the " 238 " API documentation for more details.\n", name); 239 240 return NULL; 241 } 242 243 return ops->co_major_cache; 244} 245 246/** @} */ 247 248/** @} */ 249