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