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