~ubuntu-branches/ubuntu/trusty/libnl3/trusty

« back to all changes in this revision

Viewing changes to lib/object.c

  • Committer: Bazaar Package Importer
  • Author(s): Heiko Stuebner
  • Date: 2011-05-21 19:25:13 UTC
  • Revision ID: james.westby@ubuntu.com-20110521192513-1ieyu9w9kym4bt16
Tags: upstream-3.0
ImportĀ upstreamĀ versionĀ 3.0

Show diffs side-by-side

added added

removed removed

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