oops
[libnl.git] / lib / 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 Cacheable 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_cache_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 cacheable object
39  * @arg size            size of object
40  * @return The new object or NULL.
41  */
42 struct nl_object *nl_object_alloc(size_t size)
43 {
44         struct nl_object *new;
45
46         if (size < sizeof(*new))
47                 BUG();
48
49         new = calloc(1, 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         return new;
59 }
60
61 /**
62  * Allocate a new object of kind specified by the operations handle
63  * @arg ops             cache operations handle
64  * @return The new object or NULL
65  */
66 struct nl_object *nl_object_alloc_from_ops(struct nl_cache_ops *ops)
67 {
68         struct nl_object *new;
69
70         new = nl_object_alloc(ops->co_size);
71         if (new) {
72                 new->ce_ops = ops;
73                 if (ops->co_constructor)
74                         ops->co_constructor(new);
75         }
76
77         return new;
78 }
79
80 /**
81  * Allocate a new object of kind specified by the name
82  * @arg kind            name of object type
83  * @return The new object or nULL
84  */
85 struct nl_object *nl_object_alloc_name(const char *kind)
86 {
87         struct nl_cache_ops *ops;
88
89         ops = nl_cache_mngt_lookup(kind);
90         if (!ops) {
91                 nl_error(ENOENT, "Unable to lookup cache kind \"%s\"", kind);
92                 return NULL;
93         }
94
95         return nl_object_alloc_from_ops(ops);
96 }
97
98 struct nl_derived_object {
99         NLHDR_COMMON
100         char data;
101 };
102
103 /**
104  * Allocate a new object and copy all data from an existing object
105  * @arg obj             object to inherite data from
106  * @return The new object or NULL.
107  */
108 struct nl_object *nl_object_clone(struct nl_object *obj)
109 {
110         struct nl_object *new;
111         struct nl_cache_ops *ops = obj_ops(obj);
112         int doff = offsetof(struct nl_derived_object, data);
113         int size;
114
115         new = nl_object_alloc(ops->co_size);
116         if (!new)
117                 return NULL;
118
119         size = ops->co_size - doff;
120         if (size < 0)
121                 BUG();
122
123         new->ce_cache = obj->ce_cache;
124         new->ce_ops = obj->ce_ops;
125         new->ce_msgtype = obj->ce_msgtype;
126         if (ops->co_free_data) {
127                 new->ce_dataref = obj;
128                 nl_object_get(obj);
129         }
130
131         if (size)
132                 memcpy((void *)new + doff, (void *)obj + doff, size);
133
134         return new;
135 }
136
137 /**
138  * Free a cacheable object
139  * @arg obj             object to free
140  *
141  * @return 0 or a negative error code.
142  */
143 void nl_object_free(struct nl_object *obj)
144 {
145         struct nl_cache_ops *ops = obj_ops(obj);
146
147         if (obj->ce_refcnt > 0)
148                 NL_DBG(1, "Warning: Freeing object in used...\n");
149
150         if (obj->ce_dataref)
151                 nl_object_put(obj->ce_dataref);
152         else if (ops->co_free_data)
153                 ops->co_free_data(obj);
154
155         free(obj);
156 }
157
158 /** @} */
159
160 /**
161  * @name Reference Management
162  * @{
163  */
164
165 /**
166  * Acquire a reference on a object
167  * @arg obj             object to acquire reference from
168  */
169 void nl_object_get(struct nl_object *obj)
170 {
171         obj->ce_refcnt++;
172 }
173
174 /**
175  * Release a reference from an object
176  * @arg obj             object to release reference from
177  */
178 void nl_object_put(struct nl_object *obj)
179 {
180         if (!obj)
181                 return;
182
183         obj->ce_refcnt--;
184
185         if (obj->ce_refcnt < 0)
186                 BUG();
187
188         if (obj->ce_refcnt <= 0)
189                 nl_object_free(obj);
190 }
191
192 /**
193  * Check whether this object is used by multiple users
194  * @arg obj             object to check
195  * @return true or false
196  */
197 int nl_object_shared(struct nl_object *obj)
198 {
199         return obj->ce_refcnt > 1;
200 }
201
202 /** @} */
203
204 /**
205  * @name Utillities
206  * @{
207  */
208
209 /**
210  * Dump this object according to the specified parameters
211  * @arg obj             object to dump
212  * @arg params          dumping parameters
213  */
214 void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
215 {
216         dump_from_ops(obj, params);
217 }
218
219 /**
220  * Match a filter against an object
221  * @arg obj             object to check
222  * @arg filter          filter object
223  *
224  * @return 0 if the object matches the filter or non-zero
225  *           if no filter procedure is available or if the
226  *           filter does not match.
227  */
228 int nl_object_match(struct nl_object *obj, struct nl_object *filter)
229 {
230         struct nl_cache_ops *ops = obj->ce_ops;
231
232         if (ops == filter->ce_ops &&
233             ops->co_filter && !ops->co_filter(obj, filter))
234                 return 1;
235         else
236                 return 0;
237 }
238
239 /** @} */
240
241 /**
242  * @name Access Functions
243  * @{
244  */
245
246 /**
247  * Get reference count of object
248  * @arg obj             object handle
249  */
250 int nl_object_get_refcnt(struct nl_object *obj)
251 {
252         return obj->ce_refcnt;
253 }
254
255 /**
256  * Get cache operations of object
257  * @arg obj             object handle
258  */
259 struct nl_cache_ops *nl_object_get_ops(struct nl_object *obj)
260 {
261         return obj->ce_ops;
262 }
263
264 /**
265  * Get cache this object is in
266  * @arg obj             object handle
267  * @return cache handle or NULL if object is not associated to a cache
268  */
269 struct nl_cache *nl_object_get_cache(struct nl_object *obj)
270 {
271         return obj->ce_cache;
272 }
273
274 /**
275  * Get the private data of object
276  * @arg obj             object handle
277  */
278 inline void *nl_object_priv(struct nl_object *obj)
279 {
280         return obj;
281 }
282
283 /** @} */
284
285 /** @} */