libnl
3.2.3
|
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 /** @} */