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