144d362409d5469aed47d19e7908d19bd194493aThomas Graf/* 244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/cache_mngt.c Cache Management 344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 444d362409d5469aed47d19e7908d19bd194493aThomas Graf * This library is free software; you can redistribute it and/or 544d362409d5469aed47d19e7908d19bd194493aThomas Graf * modify it under the terms of the GNU Lesser General Public 644d362409d5469aed47d19e7908d19bd194493aThomas Graf * License as published by the Free Software Foundation version 2.1 744d362409d5469aed47d19e7908d19bd194493aThomas Graf * of the License. 844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 98a3efffa5b3fde252675239914118664d36a2c24Thomas Graf * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1144d362409d5469aed47d19e7908d19bd194493aThomas Graf 1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 136782b6f709d03877a5661a4c8d8f8bd1b461f43fThomas Graf * @ingroup core 1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup cache_mngt Caching 1544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 1644d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 1744d362409d5469aed47d19e7908d19bd194493aThomas Graf 1844d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink-local.h> 1944d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h> 2044d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/cache.h> 2144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h> 2244d362409d5469aed47d19e7908d19bd194493aThomas Graf 2344d362409d5469aed47d19e7908d19bd194493aThomas Grafstatic struct nl_cache_ops *cache_ops; 2444d362409d5469aed47d19e7908d19bd194493aThomas Graf 2544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 26d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @name Cache Operations Sets 27d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @{ 28d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf */ 29d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf 30d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf/** 31d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * Lookup the set cache operations of a certain cache type 32d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @arg name name of the cache type 33d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * 34d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @return The cache operations or NULL if no operations 35d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * have been registered under the specified name. 36d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf */ 37d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Grafstruct nl_cache_ops *nl_cache_ops_lookup(const char *name) 38d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf{ 39d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf struct nl_cache_ops *ops; 40d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf 41d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf for (ops = cache_ops; ops; ops = ops->co_next) 42d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf if (!strcmp(ops->co_name, name)) 43d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf return ops; 44d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf 45d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf return NULL; 46d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf} 47d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf 48d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf/** 4944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Associate a message type to a set of cache operations 5044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg protocol netlink protocol 51d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @arg msgtype netlink message type 5244d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Associates the specified netlink message type with 5444d362409d5469aed47d19e7908d19bd194493aThomas Graf * a registered set of cache operations. 5544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 5644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return The cache operations or NULL if no association 5744d362409d5469aed47d19e7908d19bd194493aThomas Graf * could be made. 5844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 59d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Grafstruct nl_cache_ops *nl_cache_ops_associate(int protocol, int msgtype) 6044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 6144d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 6244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 6344d362409d5469aed47d19e7908d19bd194493aThomas Graf 64358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf for (ops = cache_ops; ops; ops = ops->co_next) { 65358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf if (ops->co_protocol != protocol) 66358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf continue; 67358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf 6844d362409d5469aed47d19e7908d19bd194493aThomas Graf for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 69358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf if (ops->co_msgtypes[i].mt_id == msgtype) 7044d362409d5469aed47d19e7908d19bd194493aThomas Graf return ops; 71358e44efa4b6791943acd26d4f9ad85771c6830cThomas Graf } 7244d362409d5469aed47d19e7908d19bd194493aThomas Graf 7344d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 7444d362409d5469aed47d19e7908d19bd194493aThomas Graf} 7544d362409d5469aed47d19e7908d19bd194493aThomas Graf 7644d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 77d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * Lookup message type cache association 78d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @arg ops cache operations 79d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @arg msgtype netlink message type 8044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 81d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * Searches for a matching message type association ing the specified 82d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * cache operations. 8344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 84d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf * @return A message type association or NULL. 8544d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 86d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Grafstruct nl_msgtype *nl_msgtype_lookup(struct nl_cache_ops *ops, int msgtype) 8744d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 8844d362409d5469aed47d19e7908d19bd194493aThomas Graf int i; 8944d362409d5469aed47d19e7908d19bd194493aThomas Graf 90d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++) 91d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf if (ops->co_msgtypes[i].mt_id == msgtype) 92d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf return &ops->co_msgtypes[i]; 9344d362409d5469aed47d19e7908d19bd194493aThomas Graf 9444d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 9544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 9644d362409d5469aed47d19e7908d19bd194493aThomas Graf 97d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Grafstatic struct nl_cache_ops *cache_ops_lookup_for_obj(struct nl_object_ops *obj_ops) 9844d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 9944d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 10044d362409d5469aed47d19e7908d19bd194493aThomas Graf 10144d362409d5469aed47d19e7908d19bd194493aThomas Graf for (ops = cache_ops; ops; ops = ops->co_next) 10244d362409d5469aed47d19e7908d19bd194493aThomas Graf if (ops->co_obj_ops == obj_ops) 10344d362409d5469aed47d19e7908d19bd194493aThomas Graf return ops; 10444d362409d5469aed47d19e7908d19bd194493aThomas Graf 10544d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 10644d362409d5469aed47d19e7908d19bd194493aThomas Graf 10744d362409d5469aed47d19e7908d19bd194493aThomas Graf} 10844d362409d5469aed47d19e7908d19bd194493aThomas Graf 10944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 11044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Call a function for each registered cache operation 11144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cb Callback function to be called 11244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg arg User specific argument. 11344d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 114d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Grafvoid nl_cache_ops_foreach(void (*cb)(struct nl_cache_ops *, void *), void *arg) 11544d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 11644d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 11744d362409d5469aed47d19e7908d19bd194493aThomas Graf 11844d362409d5469aed47d19e7908d19bd194493aThomas Graf for (ops = cache_ops; ops; ops = ops->co_next) 11944d362409d5469aed47d19e7908d19bd194493aThomas Graf cb(ops, arg); 12044d362409d5469aed47d19e7908d19bd194493aThomas Graf} 12144d362409d5469aed47d19e7908d19bd194493aThomas Graf 12244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 12344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Register a set of cache operations 12444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ops cache operations 12544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 12644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Called by users of caches to announce the avaibility of 12744d362409d5469aed47d19e7908d19bd194493aThomas Graf * a certain cache type. 12844d362409d5469aed47d19e7908d19bd194493aThomas Graf * 12944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code. 13044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 13144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cache_mngt_register(struct nl_cache_ops *ops) 13244d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 1338a3efffa5b3fde252675239914118664d36a2c24Thomas Graf if (!ops->co_name || !ops->co_obj_ops) 1348a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_INVAL; 13544d362409d5469aed47d19e7908d19bd194493aThomas Graf 13644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (nl_cache_ops_lookup(ops->co_name)) 1378a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_EXIST; 1388a3efffa5b3fde252675239914118664d36a2c24Thomas Graf 13944d362409d5469aed47d19e7908d19bd194493aThomas Graf ops->co_next = cache_ops; 14044d362409d5469aed47d19e7908d19bd194493aThomas Graf cache_ops = ops; 14144d362409d5469aed47d19e7908d19bd194493aThomas Graf 14244d362409d5469aed47d19e7908d19bd194493aThomas Graf NL_DBG(1, "Registered cache operations %s\n", ops->co_name); 14344d362409d5469aed47d19e7908d19bd194493aThomas Graf 14444d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 14544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 14644d362409d5469aed47d19e7908d19bd194493aThomas Graf 14744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 14844d362409d5469aed47d19e7908d19bd194493aThomas Graf * Unregister a set of cache operations 14944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg ops cache operations 15044d362409d5469aed47d19e7908d19bd194493aThomas Graf * 15144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Called by users of caches to announce a set of 15244d362409d5469aed47d19e7908d19bd194493aThomas Graf * cache operations is no longer available. The 15344d362409d5469aed47d19e7908d19bd194493aThomas Graf * specified cache operations must have been registered 15444d362409d5469aed47d19e7908d19bd194493aThomas Graf * previously using nl_cache_mngt_register() 15544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 15644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code 15744d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 15844d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_cache_mngt_unregister(struct nl_cache_ops *ops) 15944d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 16044d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *t, **tp; 16144d362409d5469aed47d19e7908d19bd194493aThomas Graf 16244d362409d5469aed47d19e7908d19bd194493aThomas Graf for (tp = &cache_ops; (t=*tp) != NULL; tp = &t->co_next) 16344d362409d5469aed47d19e7908d19bd194493aThomas Graf if (t == ops) 16444d362409d5469aed47d19e7908d19bd194493aThomas Graf break; 16544d362409d5469aed47d19e7908d19bd194493aThomas Graf 16644d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!t) 1678a3efffa5b3fde252675239914118664d36a2c24Thomas Graf return -NLE_NOCACHE; 16844d362409d5469aed47d19e7908d19bd194493aThomas Graf 16944d362409d5469aed47d19e7908d19bd194493aThomas Graf NL_DBG(1, "Unregistered cache operations %s\n", ops->co_name); 17044d362409d5469aed47d19e7908d19bd194493aThomas Graf 17144d362409d5469aed47d19e7908d19bd194493aThomas Graf *tp = t->co_next; 17244d362409d5469aed47d19e7908d19bd194493aThomas Graf return 0; 17344d362409d5469aed47d19e7908d19bd194493aThomas Graf} 17444d362409d5469aed47d19e7908d19bd194493aThomas Graf 17544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 17644d362409d5469aed47d19e7908d19bd194493aThomas Graf 17744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 17844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Global Cache Provisioning/Requiring 17944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{ 18044d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 18144d362409d5469aed47d19e7908d19bd194493aThomas Graf 18244d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 18344d362409d5469aed47d19e7908d19bd194493aThomas Graf * Provide a cache for global use 18444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache cache to provide 18544d362409d5469aed47d19e7908d19bd194493aThomas Graf * 18644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Offers the specified cache to be used by other modules. 18744d362409d5469aed47d19e7908d19bd194493aThomas Graf * Only one cache per type may be shared at a time, 18844d362409d5469aed47d19e7908d19bd194493aThomas Graf * a previsouly provided caches will be overwritten. 18944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 19044d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cache_mngt_provide(struct nl_cache *cache) 19144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 19244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 19344d362409d5469aed47d19e7908d19bd194493aThomas Graf 194d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 19544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!ops) 19644d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 19744d362409d5469aed47d19e7908d19bd194493aThomas Graf else 19844d362409d5469aed47d19e7908d19bd194493aThomas Graf ops->co_major_cache = cache; 19944d362409d5469aed47d19e7908d19bd194493aThomas Graf} 20044d362409d5469aed47d19e7908d19bd194493aThomas Graf 20144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 20244d362409d5469aed47d19e7908d19bd194493aThomas Graf * Unprovide a cache for global use 20344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg cache cache to unprovide 20444d362409d5469aed47d19e7908d19bd194493aThomas Graf * 20544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Cancels the offer to use a cache globally. The 20644d362409d5469aed47d19e7908d19bd194493aThomas Graf * cache will no longer be returned via lookups but 20744d362409d5469aed47d19e7908d19bd194493aThomas Graf * may still be in use. 20844d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 20944d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_cache_mngt_unprovide(struct nl_cache *cache) 21044d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 21144d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 21244d362409d5469aed47d19e7908d19bd194493aThomas Graf 213d36d396fd0ae94aa2269546a02b5973b4ec27775Thomas Graf ops = cache_ops_lookup_for_obj(cache->c_ops->co_obj_ops); 21444d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!ops) 21544d362409d5469aed47d19e7908d19bd194493aThomas Graf BUG(); 21644d362409d5469aed47d19e7908d19bd194493aThomas Graf else if (ops->co_major_cache == cache) 21744d362409d5469aed47d19e7908d19bd194493aThomas Graf ops->co_major_cache = NULL; 21844d362409d5469aed47d19e7908d19bd194493aThomas Graf} 21944d362409d5469aed47d19e7908d19bd194493aThomas Graf 22044d362409d5469aed47d19e7908d19bd194493aThomas Graf/** 22144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Demand the use of a global cache 22244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg name name of the required object type 22344d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22444d362409d5469aed47d19e7908d19bd194493aThomas Graf * Trys to find a cache of the specified type for global 22544d362409d5469aed47d19e7908d19bd194493aThomas Graf * use. 22644d362409d5469aed47d19e7908d19bd194493aThomas Graf * 22744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return A cache provided by another subsystem of the 22844d362409d5469aed47d19e7908d19bd194493aThomas Graf * specified type marked to be available. 22944d362409d5469aed47d19e7908d19bd194493aThomas Graf */ 23044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_cache *nl_cache_mngt_require(const char *name) 23144d362409d5469aed47d19e7908d19bd194493aThomas Graf{ 23244d362409d5469aed47d19e7908d19bd194493aThomas Graf struct nl_cache_ops *ops; 23344d362409d5469aed47d19e7908d19bd194493aThomas Graf 23444d362409d5469aed47d19e7908d19bd194493aThomas Graf ops = nl_cache_ops_lookup(name); 23544d362409d5469aed47d19e7908d19bd194493aThomas Graf if (!ops || !ops->co_major_cache) { 23644d362409d5469aed47d19e7908d19bd194493aThomas Graf fprintf(stderr, "Application BUG: Your application must " 23744d362409d5469aed47d19e7908d19bd194493aThomas Graf "call nl_cache_mngt_provide() and\nprovide a valid " 23844d362409d5469aed47d19e7908d19bd194493aThomas Graf "%s cache to be used for internal lookups.\nSee the " 23944d362409d5469aed47d19e7908d19bd194493aThomas Graf " API documentation for more details.\n", name); 24044d362409d5469aed47d19e7908d19bd194493aThomas Graf 24144d362409d5469aed47d19e7908d19bd194493aThomas Graf return NULL; 24244d362409d5469aed47d19e7908d19bd194493aThomas Graf } 24344d362409d5469aed47d19e7908d19bd194493aThomas Graf 24444d362409d5469aed47d19e7908d19bd194493aThomas Graf return ops->co_major_cache; 24544d362409d5469aed47d19e7908d19bd194493aThomas Graf} 24644d362409d5469aed47d19e7908d19bd194493aThomas Graf 24744d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 24844d362409d5469aed47d19e7908d19bd194493aThomas Graf 24944d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */ 250