libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/object.c
00001 /*
00002  * lib/object.c         Generic Cacheable Object
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup cache
00014  * @defgroup object Object
00015  * @{
00016  */
00017 
00018 #include <netlink-local.h>
00019 #include <netlink/netlink.h>
00020 #include <netlink/cache.h>
00021 #include <netlink/object.h>
00022 #include <netlink/utils.h>
00023 
00024 static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
00025 {
00026         if (!obj->ce_ops)
00027                 BUG();
00028 
00029         return obj->ce_ops;
00030 }
00031 
00032 /**
00033  * @name Object Creation/Deletion
00034  * @{
00035  */
00036 
00037 /**
00038  * Allocate a new object of kind specified by the operations handle
00039  * @arg ops             cache operations handle
00040  * @return The new object or NULL
00041  */
00042 struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
00043 {
00044         struct nl_object *new;
00045 
00046         if (ops->oo_size < sizeof(*new))
00047                 BUG();
00048 
00049         new = calloc(1, ops->oo_size);
00050         if (!new)
00051                 return NULL;
00052 
00053         new->ce_refcnt = 1;
00054         nl_init_list_head(&new->ce_list);
00055 
00056         new->ce_ops = ops;
00057         if (ops->oo_constructor)
00058                 ops->oo_constructor(new);
00059 
00060         NL_DBG(4, "Allocated new object %p\n", new);
00061 
00062         return new;
00063 }
00064 
00065 /**
00066  * Allocate new object of kind specified by the name
00067  * @arg kind            name of object type
00068  * @arg result          Result pointer
00069  *
00070  * @return 0 on success or a negative error code.
00071  */
00072 int nl_object_alloc_name(const char *kind, struct nl_object **result)
00073 {
00074         struct nl_cache_ops *ops;
00075 
00076         ops = nl_cache_ops_lookup(kind);
00077         if (!ops)
00078                 return -NLE_OPNOTSUPP;
00079 
00080         if (!(*result = nl_object_alloc(ops->co_obj_ops)))
00081                 return -NLE_NOMEM;
00082 
00083         return 0;
00084 }
00085 
00086 struct nl_derived_object {
00087         NLHDR_COMMON
00088         char data;
00089 };
00090 
00091 /**
00092  * Allocate a new object and copy all data from an existing object
00093  * @arg obj             object to inherite data from
00094  * @return The new object or NULL.
00095  */
00096 struct nl_object *nl_object_clone(struct nl_object *obj)
00097 {
00098         struct nl_object *new;
00099         struct nl_object_ops *ops = obj_ops(obj);
00100         int doff = offsetof(struct nl_derived_object, data);
00101         int size;
00102 
00103         new = nl_object_alloc(ops);
00104         if (!new)
00105                 return NULL;
00106 
00107         size = ops->oo_size - doff;
00108         if (size < 0)
00109                 BUG();
00110 
00111         new->ce_ops = obj->ce_ops;
00112         new->ce_msgtype = obj->ce_msgtype;
00113         new->ce_mask = obj->ce_mask;
00114 
00115         if (size)
00116                 memcpy((void *)new + doff, (void *)obj + doff, size);
00117 
00118         if (ops->oo_clone) {
00119                 if (ops->oo_clone(new, obj) < 0) {
00120                         nl_object_free(new);
00121                         return NULL;
00122                 }
00123         } else if (size && ops->oo_free_data)
00124                 BUG();
00125 
00126         return new;
00127 }
00128 
00129 /**
00130  * Free a cacheable object
00131  * @arg obj             object to free
00132  *
00133  * @return 0 or a negative error code.
00134  */
00135 void nl_object_free(struct nl_object *obj)
00136 {
00137         struct nl_object_ops *ops = obj_ops(obj);
00138 
00139         if (obj->ce_refcnt > 0)
00140                 NL_DBG(1, "Warning: Freeing object in use...\n");
00141 
00142         if (obj->ce_cache)
00143                 nl_cache_remove(obj);
00144 
00145         if (ops->oo_free_data)
00146                 ops->oo_free_data(obj);
00147 
00148         free(obj);
00149 
00150         NL_DBG(4, "Freed object %p\n", obj);
00151 }
00152 
00153 /** @} */
00154 
00155 /**
00156  * @name Reference Management
00157  * @{
00158  */
00159 
00160 /**
00161  * Acquire a reference on a object
00162  * @arg obj             object to acquire reference from
00163  */
00164 void nl_object_get(struct nl_object *obj)
00165 {
00166         obj->ce_refcnt++;
00167         NL_DBG(4, "New reference to object %p, total %d\n",
00168                obj, obj->ce_refcnt);
00169 }
00170 
00171 /**
00172  * Release a reference from an object
00173  * @arg obj             object to release reference from
00174  */
00175 void nl_object_put(struct nl_object *obj)
00176 {
00177         if (!obj)
00178                 return;
00179 
00180         obj->ce_refcnt--;
00181         NL_DBG(4, "Returned object reference %p, %d remaining\n",
00182                obj, obj->ce_refcnt);
00183 
00184         if (obj->ce_refcnt < 0)
00185                 BUG();
00186 
00187         if (obj->ce_refcnt <= 0)
00188                 nl_object_free(obj);
00189 }
00190 
00191 /**
00192  * Check whether this object is used by multiple users
00193  * @arg obj             object to check
00194  * @return true or false
00195  */
00196 int nl_object_shared(struct nl_object *obj)
00197 {
00198         return obj->ce_refcnt > 1;
00199 }
00200 
00201 /** @} */
00202 
00203 /**
00204  * @name Marks
00205  * @{
00206  */
00207 
00208 /**
00209  * Add mark to object
00210  * @arg obj             Object to mark
00211  */
00212 void nl_object_mark(struct nl_object *obj)
00213 {
00214         obj->ce_flags |= NL_OBJ_MARK;
00215 }
00216 
00217 /**
00218  * Remove mark from object
00219  * @arg obj             Object to unmark
00220  */
00221 void nl_object_unmark(struct nl_object *obj)
00222 {
00223         obj->ce_flags &= ~NL_OBJ_MARK;
00224 }
00225 
00226 /**
00227  * Return true if object is marked
00228  * @arg obj             Object to check
00229  * @return true if object is marked, otherwise false
00230  */
00231 int nl_object_is_marked(struct nl_object *obj)
00232 {
00233         return (obj->ce_flags & NL_OBJ_MARK);
00234 }
00235 
00236 /** @} */
00237 
00238 /**
00239  * @name Utillities
00240  * @{
00241  */
00242 
00243 /**
00244  * Dump this object according to the specified parameters
00245  * @arg obj             object to dump
00246  * @arg params          dumping parameters
00247  */
00248 void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
00249 {
00250         dump_from_ops(obj, params);
00251 }
00252 
00253 void nl_object_dump_buf(struct nl_object *obj, char *buf, size_t len)
00254 {
00255         struct nl_dump_params dp = {
00256                 .dp_buf = buf,
00257                 .dp_buflen = len,
00258         };
00259 
00260         return nl_object_dump(obj, &dp);
00261 }
00262 
00263 /**
00264  * Check if the identifiers of two objects are identical 
00265  * @arg a               an object
00266  * @arg b               another object of same type
00267  *
00268  * @return true if both objects have equal identifiers, otherwise false.
00269  */
00270 int nl_object_identical(struct nl_object *a, struct nl_object *b)
00271 {
00272         struct nl_object_ops *ops = obj_ops(a);
00273         int req_attrs;
00274 
00275         /* Both objects must be of same type */
00276         if (ops != obj_ops(b))
00277                 return 0;
00278 
00279         req_attrs = ops->oo_id_attrs;
00280         if (req_attrs == ~0)
00281                 req_attrs = a->ce_mask & b->ce_mask;
00282 
00283         /* Both objects must provide all required attributes to uniquely
00284          * identify an object */
00285         if ((a->ce_mask & req_attrs) != req_attrs ||
00286             (b->ce_mask & req_attrs) != req_attrs)
00287                 return 0;
00288 
00289         /* Can't judge unless we can compare */
00290         if (ops->oo_compare == NULL)
00291                 return 0;
00292 
00293         return !(ops->oo_compare(a, b, req_attrs, 0));
00294 }
00295 
00296 /**
00297  * Compute bitmask representing difference in attribute values
00298  * @arg a               an object
00299  * @arg b               another object of same type
00300  *
00301  * The bitmask returned is specific to an object type, each bit set represents
00302  * an attribute which mismatches in either of the two objects. Unavailability
00303  * of an attribute in one object and presence in the other is regarded a
00304  * mismatch as well.
00305  *
00306  * @return Bitmask describing differences or 0 if they are completely identical.
00307  */
00308 uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
00309 {
00310         struct nl_object_ops *ops = obj_ops(a);
00311 
00312         if (ops != obj_ops(b) || ops->oo_compare == NULL)
00313                 return UINT_MAX;
00314 
00315         return ops->oo_compare(a, b, ~0, 0);
00316 }
00317 
00318 /**
00319  * Match a filter against an object
00320  * @arg obj             object to check
00321  * @arg filter          object of same type acting as filter
00322  *
00323  * @return 1 if the object matches the filter or 0
00324  *           if no filter procedure is available or if the
00325  *           filter does not match.
00326  */
00327 int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
00328 {
00329         struct nl_object_ops *ops = obj_ops(obj);
00330 
00331         if (ops != obj_ops(filter) || ops->oo_compare == NULL)
00332                 return 0;
00333         
00334         return !(ops->oo_compare(obj, filter, filter->ce_mask,
00335                                  LOOSE_COMPARISON));
00336 }
00337 
00338 /**
00339  * Convert bitmask of attributes to a character string
00340  * @arg obj             object of same type as attribute bitmask
00341  * @arg attrs           bitmask of attribute types
00342  * @arg buf             destination buffer
00343  * @arg len             length of destination buffer
00344  *
00345  * Converts the bitmask of attribute types into a list of attribute
00346  * names separated by comas.
00347  *
00348  * @return destination buffer.
00349  */
00350 char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
00351                           char *buf, size_t len)
00352 {
00353         struct nl_object_ops *ops = obj_ops(obj);
00354 
00355         if (ops->oo_attrs2str != NULL)
00356                 return ops->oo_attrs2str(attrs, buf, len);
00357         else {
00358                 memset(buf, 0, len);
00359                 return buf;
00360         }
00361 }
00362 
00363 /**
00364  * Return list of attributes present in an object
00365  * @arg obj             an object
00366  * @arg buf             destination buffer
00367  * @arg len             length of destination buffer
00368  *
00369  * @return destination buffer.
00370  */
00371 char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
00372 {
00373         return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
00374 }
00375 
00376 /** @} */
00377 
00378 /**
00379  * @name Attributes
00380  * @{
00381  */
00382 
00383 int nl_object_get_refcnt(struct nl_object *obj)
00384 {
00385         return obj->ce_refcnt;
00386 }
00387 
00388 struct nl_cache *nl_object_get_cache(struct nl_object *obj)
00389 {
00390         return obj->ce_cache;
00391 }
00392 
00393 /** @} */
00394 
00395 /** @} */