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