object.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  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. * @ingroup cache
  13. * @defgroup object Object
  14. * @{
  15. */
  16. #include <netlink-local.h>
  17. #include <netlink/netlink.h>
  18. #include <netlink/cache.h>
  19. #include <netlink/object.h>
  20. #include <netlink/utils.h>
  21. static inline struct nl_object_ops *obj_ops(struct nl_object *obj)
  22. {
  23. if (!obj->ce_ops)
  24. BUG();
  25. return obj->ce_ops;
  26. }
  27. /**
  28. * @name Object Creation/Deletion
  29. * @{
  30. */
  31. /**
  32. * Allocate a new object of kind specified by the operations handle
  33. * @arg ops cache operations handle
  34. * @return The new object or NULL
  35. */
  36. struct nl_object *nl_object_alloc(struct nl_object_ops *ops)
  37. {
  38. struct nl_object *new;
  39. if (ops->oo_size < sizeof(*new))
  40. BUG();
  41. new = calloc(1, ops->oo_size);
  42. if (!new) {
  43. nl_errno(ENOMEM);
  44. return NULL;
  45. }
  46. new->ce_refcnt = 1;
  47. nl_init_list_head(&new->ce_list);
  48. new->ce_ops = ops;
  49. if (ops->oo_constructor)
  50. ops->oo_constructor(new);
  51. NL_DBG(4, "Allocated new object %p\n", new);
  52. return new;
  53. }
  54. /**
  55. * Allocate a new object of kind specified by the name
  56. * @arg kind name of object type
  57. * @return The new object or nULL
  58. */
  59. struct nl_object *nl_object_alloc_name(const char *kind)
  60. {
  61. struct nl_cache_ops *ops;
  62. ops = nl_cache_ops_lookup(kind);
  63. if (!ops) {
  64. nl_error(ENOENT, "Unable to lookup cache kind \"%s\"", kind);
  65. return NULL;
  66. }
  67. return nl_object_alloc(ops->co_obj_ops);
  68. }
  69. struct nl_derived_object {
  70. NLHDR_COMMON
  71. char data;
  72. };
  73. /**
  74. * Allocate a new object and copy all data from an existing object
  75. * @arg obj object to inherite data from
  76. * @return The new object or NULL.
  77. */
  78. struct nl_object *nl_object_clone(struct nl_object *obj)
  79. {
  80. struct nl_object *new;
  81. struct nl_object_ops *ops = obj_ops(obj);
  82. int doff = offsetof(struct nl_derived_object, data);
  83. int size;
  84. new = nl_object_alloc(ops);
  85. if (!new)
  86. return NULL;
  87. size = ops->oo_size - doff;
  88. if (size < 0)
  89. BUG();
  90. new->ce_ops = obj->ce_ops;
  91. new->ce_msgtype = obj->ce_msgtype;
  92. if (size)
  93. memcpy((void *)new + doff, (void *)obj + doff, size);
  94. if (ops->oo_clone) {
  95. if (ops->oo_clone(new, obj) < 0) {
  96. nl_object_free(new);
  97. return NULL;
  98. }
  99. } else if (size && ops->oo_free_data)
  100. BUG();
  101. return new;
  102. }
  103. /**
  104. * Free a cacheable object
  105. * @arg obj object to free
  106. *
  107. * @return 0 or a negative error code.
  108. */
  109. void nl_object_free(struct nl_object *obj)
  110. {
  111. struct nl_object_ops *ops;
  112. if (!obj)
  113. return;
  114. ops = obj_ops(obj);
  115. if (obj->ce_refcnt > 0)
  116. NL_DBG(1, "Warning: Freeing object in use...\n");
  117. if (obj->ce_cache)
  118. nl_cache_remove(obj);
  119. if (ops->oo_free_data)
  120. ops->oo_free_data(obj);
  121. free(obj);
  122. NL_DBG(4, "Freed object %p\n", obj);
  123. }
  124. /** @} */
  125. /**
  126. * @name Reference Management
  127. * @{
  128. */
  129. /**
  130. * Acquire a reference on a object
  131. * @arg obj object to acquire reference from
  132. */
  133. void nl_object_get(struct nl_object *obj)
  134. {
  135. obj->ce_refcnt++;
  136. NL_DBG(4, "New reference to object %p, total %d\n",
  137. obj, obj->ce_refcnt);
  138. }
  139. /**
  140. * Release a reference from an object
  141. * @arg obj object to release reference from
  142. */
  143. void nl_object_put(struct nl_object *obj)
  144. {
  145. if (!obj)
  146. return;
  147. obj->ce_refcnt--;
  148. NL_DBG(4, "Returned object reference %p, %d remaining\n",
  149. obj, obj->ce_refcnt);
  150. if (obj->ce_refcnt < 0)
  151. BUG();
  152. if (obj->ce_refcnt <= 0)
  153. nl_object_free(obj);
  154. }
  155. /**
  156. * Check whether this object is used by multiple users
  157. * @arg obj object to check
  158. * @return true or false
  159. */
  160. int nl_object_shared(struct nl_object *obj)
  161. {
  162. return obj->ce_refcnt > 1;
  163. }
  164. /** @} */
  165. /**
  166. * @name Marks
  167. * @{
  168. */
  169. /**
  170. * Add mark to object
  171. * @arg obj Object to mark
  172. */
  173. void nl_object_mark(struct nl_object *obj)
  174. {
  175. obj->ce_flags |= NL_OBJ_MARK;
  176. }
  177. /**
  178. * Remove mark from object
  179. * @arg obj Object to unmark
  180. */
  181. void nl_object_unmark(struct nl_object *obj)
  182. {
  183. obj->ce_flags &= ~NL_OBJ_MARK;
  184. }
  185. /**
  186. * Return true if object is marked
  187. * @arg obj Object to check
  188. * @return true if object is marked, otherwise false
  189. */
  190. int nl_object_is_marked(struct nl_object *obj)
  191. {
  192. return (obj->ce_flags & NL_OBJ_MARK);
  193. }
  194. /** @} */
  195. /**
  196. * @name Utillities
  197. * @{
  198. */
  199. /**
  200. * Dump this object according to the specified parameters
  201. * @arg obj object to dump
  202. * @arg params dumping parameters
  203. */
  204. void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
  205. {
  206. dump_from_ops(obj, params);
  207. }
  208. /**
  209. * Check if the identifiers of two objects are identical
  210. * @arg a an object
  211. * @arg b another object of same type
  212. *
  213. * @return true if both objects have equal identifiers, otherwise false.
  214. */
  215. int nl_object_identical(struct nl_object *a, struct nl_object *b)
  216. {
  217. struct nl_object_ops *ops = obj_ops(a);
  218. int req_attrs;
  219. /* Both objects must be of same type */
  220. if (ops != obj_ops(b))
  221. return 0;
  222. req_attrs = ops->oo_id_attrs;
  223. /* Both objects must provide all required attributes to uniquely
  224. * identify an object */
  225. if ((a->ce_mask & req_attrs) != req_attrs ||
  226. (b->ce_mask & req_attrs) != req_attrs)
  227. return 0;
  228. /* Can't judge unless we can compare */
  229. if (ops->oo_compare == NULL)
  230. return 0;
  231. return !(ops->oo_compare(a, b, req_attrs, 0));
  232. }
  233. /**
  234. * Compute bitmask representing difference in attribute values
  235. * @arg a an object
  236. * @arg b another object of same type
  237. *
  238. * The bitmask returned is specific to an object type, each bit set represents
  239. * an attribute which mismatches in either of the two objects. Unavailability
  240. * of an attribute in one object and presence in the other is regarded a
  241. * mismatch as well.
  242. *
  243. * @return Bitmask describing differences or 0 if they are completely identical.
  244. */
  245. uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
  246. {
  247. struct nl_object_ops *ops = obj_ops(a);
  248. if (ops != obj_ops(b) || ops->oo_compare == NULL)
  249. return UINT_MAX;
  250. return ops->oo_compare(a, b, ~0, 0);
  251. }
  252. /**
  253. * Match a filter against an object
  254. * @arg obj object to check
  255. * @arg filter object of same type acting as filter
  256. *
  257. * @return 1 if the object matches the filter or 0
  258. * if no filter procedure is available or if the
  259. * filter does not match.
  260. */
  261. int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
  262. {
  263. struct nl_object_ops *ops = obj_ops(obj);
  264. if (ops != obj_ops(filter) || ops->oo_compare == NULL)
  265. return 0;
  266. return !(ops->oo_compare(obj, filter, filter->ce_mask,
  267. LOOSE_FLAG_COMPARISON));
  268. }
  269. /**
  270. * Convert bitmask of attributes to a character string
  271. * @arg obj object of same type as attribute bitmask
  272. * @arg attrs bitmask of attribute types
  273. * @arg buf destination buffer
  274. * @arg len length of destination buffer
  275. *
  276. * Converts the bitmask of attribute types into a list of attribute
  277. * names separated by comas.
  278. *
  279. * @return destination buffer.
  280. */
  281. char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
  282. char *buf, size_t len)
  283. {
  284. struct nl_object_ops *ops = obj_ops(obj);
  285. if (ops->oo_attrs2str != NULL)
  286. return ops->oo_attrs2str(attrs, buf, len);
  287. else {
  288. memset(buf, 0, len);
  289. return buf;
  290. }
  291. }
  292. /**
  293. * Return list of attributes present in an object
  294. * @arg obj an object
  295. * @arg buf destination buffer
  296. * @arg len length of destination buffer
  297. *
  298. * @return destination buffer.
  299. */
  300. char *nl_object_attr_list(struct nl_object *obj, char *buf, size_t len)
  301. {
  302. return nl_object_attrs2str(obj, obj->ce_mask, buf, len);
  303. }
  304. /** @} */
  305. /**
  306. * @name Attributes
  307. * @{
  308. */
  309. int nl_object_get_refcnt(struct nl_object *obj)
  310. {
  311. return obj->ce_refcnt;
  312. }
  313. struct nl_cache *nl_object_get_cache(struct nl_object *obj)
  314. {
  315. return obj->ce_cache;
  316. }
  317. /** @} */
  318. /** @} */