libnl 1.1.4
object.c
1/*
2 * lib/object.c Generic Cacheable Object
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-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup cache
14 * @defgroup object Object
15 * @{
16 */
17
18#include <netlink-local.h>
19#include <netlink/netlink.h>
20#include <netlink/cache.h>
21#include <netlink/object.h>
22#include <netlink/utils.h>
23
24static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
25{
26 if (!obj->ce_ops)
27 BUG();
28
29 return obj->ce_ops;
30}
31
32/**
33 * @name Object Creation/Deletion
34 * @{
35 */
36
37/**
38 * Allocate a new object of kind specified by the operations handle
39 * @arg ops cache operations handle
40 * @return The new object or NULL
41 */
42struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
43{
44 struct nl_object *new;
45
46 if (ops->oo_size < sizeof(*new))
47 BUG();
48
49 new = calloc(1, ops->oo_size);
50 if (!new) {
51 nl_errno(ENOMEM);
52 return NULL;
53 }
54
55 new->ce_refcnt = 1;
56 nl_init_list_head(&new->ce_list);
57
58 new->ce_ops = ops;
59 if (ops->oo_constructor)
60 ops->oo_constructor(new);
61
62 NL_DBG(4, "Allocated new object %p\n", new);
63
64 return new;
65}
66
67/**
68 * Allocate a new object of kind specified by the name
69 * @arg kind name of object type
70 * @return The new object or nULL
71 */
72struct nl_object *nl_object_alloc_name(const char *kind)
73{
74 struct nl_cache_ops *ops;
75
76 ops = nl_cache_ops_lookup(kind);
77 if (!ops) {
78 nl_error(ENOENT, "Unable to lookup cache kind \"%s\"", kind);
79 return NULL;
80 }
81
82 return nl_object_alloc(ops->co_obj_ops);
83}
84
87 char data;
88};
89
90/**
91 * Allocate a new object and copy all data from an existing object
92 * @arg obj object to inherite data from
93 * @return The new object or NULL.
94 */
95struct nl_object *nl_object_clone(struct nl_object *obj)
96{
97 struct nl_object *new;
98 struct nl_object_ops *ops = obj_ops(obj);
99 int doff = offsetof(struct nl_derived_object, data);
100 int size;
101
102 new = nl_object_alloc(ops);
103 if (!new)
104 return NULL;
105
106 size = ops->oo_size - doff;
107 if (size < 0)
108 BUG();
109
110 new->ce_ops = obj->ce_ops;
111 new->ce_msgtype = obj->ce_msgtype;
112
113 if (size)
114 memcpy((void *)new + doff, (void *)obj + doff, size);
115
116 if (ops->oo_clone) {
117 if (ops->oo_clone(new, obj) < 0) {
118 nl_object_free(new);
119 return NULL;
120 }
121 } else if (size && ops->oo_free_data)
122 BUG();
123
124 return new;
125}
126
127/**
128 * Free a cacheable object
129 * @arg obj object to free
130 *
131 * @return 0 or a negative error code.
132 */
133void nl_object_free(struct nl_object *obj)
134{
135 struct nl_object_ops *ops;
136
137 if (!obj)
138 return;
139
140 ops = obj_ops(obj);
141
142 if (obj->ce_refcnt > 0)
143 NL_DBG(1, "Warning: Freeing object in use...\n");
144
145 if (obj->ce_cache)
146 nl_cache_remove(obj);
147
148 if (ops->oo_free_data)
149 ops->oo_free_data(obj);
150
151 free(obj);
152
153 NL_DBG(4, "Freed object %p\n", obj);
154}
155
156/** @} */
157
158/**
159 * @name Reference Management
160 * @{
161 */
162
163/**
164 * Acquire a reference on a object
165 * @arg obj object to acquire reference from
166 */
167void nl_object_get(struct nl_object *obj)
168{
169 obj->ce_refcnt++;
170 NL_DBG(4, "New reference to object %p, total %d\n",
171 obj, obj->ce_refcnt);
172}
173
174/**
175 * Release a reference from an object
176 * @arg obj object to release reference from
177 */
178void nl_object_put(struct nl_object *obj)
179{
180 if (!obj)
181 return;
182
183 obj->ce_refcnt--;
184 NL_DBG(4, "Returned object reference %p, %d remaining\n",
185 obj, obj->ce_refcnt);
186
187 if (obj->ce_refcnt < 0)
188 BUG();
189
190 if (obj->ce_refcnt <= 0)
191 nl_object_free(obj);
192}
193
194/**
195 * Check whether this object is used by multiple users
196 * @arg obj object to check
197 * @return true or false
198 */
199int nl_object_shared(struct nl_object *obj)
200{
201 return obj->ce_refcnt > 1;
202}
203
204/** @} */
205
206/**
207 * @name Marks
208 * @{
209 */
210
211/**
212 * Add mark to object
213 * @arg obj Object to mark
214 */
215void nl_object_mark(struct nl_object *obj)
216{
217 obj->ce_flags |= NL_OBJ_MARK;
218}
219
220/**
221 * Remove mark from object
222 * @arg obj Object to unmark
223 */
224void nl_object_unmark(struct nl_object *obj)
225{
226 obj->ce_flags &= ~NL_OBJ_MARK;
227}
228
229/**
230 * Return true if object is marked
231 * @arg obj Object to check
232 * @return true if object is marked, otherwise false
233 */
234int nl_object_is_marked(struct nl_object *obj)
235{
236 return (obj->ce_flags & NL_OBJ_MARK);
237}
238
239/** @} */
240
241/**
242 * @name Utillities
243 * @{
244 */
245
246/**
247 * Dump this object according to the specified parameters
248 * @arg obj object to dump
249 * @arg params dumping parameters
250 */
251void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
252{
253 dump_from_ops(obj, params);
254}
255
256/**
257 * Check if the identifiers of two objects are identical
258 * @arg a an object
259 * @arg b another object of same type
260 *
261 * @return true if both objects have equal identifiers, otherwise false.
262 */
263int nl_object_identical(struct nl_object *a, struct nl_object *b)
264{
265 struct nl_object_ops *ops = obj_ops(a);
266 int req_attrs;
267
268 /* Both objects must be of same type */
269 if (ops != obj_ops(b))
270 return 0;
271
272 req_attrs = ops->oo_id_attrs;
273
274 /* Both objects must provide all required attributes to uniquely
275 * identify an object */
276 if ((a->ce_mask & req_attrs) != req_attrs ||
277 (b->ce_mask & req_attrs) != req_attrs)
278 return 0;
279
280 /* Can't judge unless we can compare */
281 if (ops->oo_compare == NULL)
282 return 0;
283
284 return !(ops->oo_compare(a, b, req_attrs, 0));
285}
286
287/**
288 * Compute bitmask representing difference in attribute values
289 * @arg a an object
290 * @arg b another object of same type
291 *
292 * The bitmask returned is specific to an object type, each bit set represents
293 * an attribute which mismatches in either of the two objects. Unavailability
294 * of an attribute in one object and presence in the other is regarded a
295 * mismatch as well.
296 *
297 * @return Bitmask describing differences or 0 if they are completely identical.
298 */
299uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
300{
301 struct nl_object_ops *ops = obj_ops(a);
302
303 if (ops != obj_ops(b) || ops->oo_compare == NULL)
304 return UINT_MAX;
305
306 return ops->oo_compare(a, b, ~0, 0);
307}
308
309/**
310 * Match a filter against an object
311 * @arg obj object to check
312 * @arg filter object of same type acting as filter
313 *
314 * @return 1 if the object matches the filter or 0
315 * if no filter procedure is available or if the
316 * filter does not match.
317 */
318int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
319{
320 struct nl_object_ops *ops = obj_ops(obj);
321
322 if (ops != obj_ops(filter) || ops->oo_compare == NULL)
323 return 0;
324
325 return !(ops->oo_compare(obj, filter, filter->ce_mask,
326 LOOSE_FLAG_COMPARISON));
327}
328
329/**
330 * Convert bitmask of attributes to a character string
331 * @arg obj object of same type as attribute bitmask
332 * @arg attrs bitmask of attribute types
333 * @arg buf destination buffer
334 * @arg len length of destination buffer
335 *
336 * Converts the bitmask of attribute types into a list of attribute
337 * names separated by comas.
338 *
339 * @return destination buffer.
340 */
341char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
342 char *buf, size_t len)
343{
344 struct nl_object_ops *ops = obj_ops(obj);
345
346 if (ops->oo_attrs2str != NULL)
347 return ops->oo_attrs2str(attrs, buf, len);
348 else {
349 memset(buf, 0, len);
350 return buf;
351 }
352}
353
354/**
355 * Return list of attributes present in an object
356 * @arg obj an object
357 * @arg buf destination buffer
358 * @arg len length of destination buffer
359 *
360 * @return destination buffer.
361 */
362char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
363{
364 return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
365}
366
367/** @} */
368
369/**
370 * @name Attributes
371 * @{
372 */
373
374int nl_object_get_refcnt(struct nl_object *obj)
375{
376 return obj->ce_refcnt;
377}
378
379struct nl_cache *nl_object_get_cache(struct nl_object *obj)
380{
381 return obj->ce_cache;
382}
383
384/** @} */
385
386/** @} */
struct nl_cache_ops * nl_cache_ops_lookup(const char *name)
Lookup cache operations by name.
Definition: cache_mngt.c:68
void nl_cache_remove(struct nl_object *obj)
Removes an object from a cache.
Definition: cache.c:374
#define NLHDR_COMMON
Common Object Header.
Definition: object-api.h:188
uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
Compute bitmask representing difference in attribute values.
Definition: object.c:299
void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
Dump this object according to the specified parameters.
Definition: object.c:251
struct nl_object * nl_object_alloc_name(const char *kind)
Allocate a new object of kind specified by the name.
Definition: object.c:72
struct nl_object * nl_object_clone(struct nl_object *obj)
Allocate a new object and copy all data from an existing object.
Definition: object.c:95
char * nl_object_attrs2str(struct nl_object *obj, uint32_t attrs, char *buf, size_t len)
Convert bitmask of attributes to a character string.
Definition: object.c:341
int nl_object_shared(struct nl_object *obj)
Check whether this object is used by multiple users.
Definition: object.c:199
void nl_object_unmark(struct nl_object *obj)
Remove mark from object.
Definition: object.c:224
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:178
int nl_object_identical(struct nl_object *a, struct nl_object *b)
Check if the identifiers of two objects are identical.
Definition: object.c:263
char * nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
Return list of attributes present in an object.
Definition: object.c:362
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:167
void nl_object_free(struct nl_object *obj)
Free a cacheable object.
Definition: object.c:133
int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
Match a filter against an object.
Definition: object.c:318
int nl_object_is_marked(struct nl_object *obj)
Return true if object is marked.
Definition: object.c:234
void nl_object_mark(struct nl_object *obj)
Add mark to object.
Definition: object.c:215
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:42
Cache Operations.
Definition: cache-api.h:164
Dumping parameters.
Definition: types.h:37
Object Operations.
Definition: object-api.h:255
size_t oo_size
Size of object including its header.
Definition: object-api.h:264
void(* oo_constructor)(struct nl_object *)
Constructor function.
Definition: object-api.h:275
int(* oo_clone)(struct nl_object *, struct nl_object *)
Cloning function.
Definition: object-api.h:296
void(* oo_free_data)(struct nl_object *)
Destructor function.
Definition: object-api.h:284
int(* oo_compare)(struct nl_object *, struct nl_object *, uint32_t, int)
Comparison function.
Definition: object-api.h:321