libnl  3.2.7
cache_mngt.c
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@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  */
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  */
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 struct nl_cache *__nl_cache_mngt_require(const char *name)
221 {
222  struct nl_cache_ops *ops;
223 
224  ops = nl_cache_ops_lookup(name);
225  if (ops)
226  return ops->co_major_cache;
227 
228  return NULL;
229 }
230 
231 /**
232  * Demand the use of a global cache
233  * @arg name name of the required object type
234  *
235  * Trys to find a cache of the specified type for global
236  * use.
237  *
238  * @return A cache provided by another subsystem of the
239  * specified type marked to be available.
240  */
241 struct nl_cache *nl_cache_mngt_require(const char *name)
242 {
243  struct nl_cache *cache;
244 
245  if (!(cache = __nl_cache_mngt_require(name)))
246  fprintf(stderr, "Application BUG: Your application must "
247  "call nl_cache_mngt_provide() and\nprovide a valid "
248  "%s cache to be used for internal lookups.\nSee the "
249  " API documentation for more details.\n", name);
250 
251  return cache;
252 }
253 
254 /** @} */
255 
256 /** @} */