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