object.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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-2008 Thomas Graf <[email protected]>
  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. return NULL;
  44. new->ce_refcnt = 1;
  45. nl_init_list_head(&new->ce_list);
  46. new->ce_ops = ops;
  47. if (ops->oo_constructor)
  48. ops->oo_constructor(new);
  49. NL_DBG(4, "Allocated new object %p\n", new);
  50. return new;
  51. }
  52. #ifdef disabled
  53. /**
  54. * Allocate a new object of kind specified by the name
  55. * @arg kind name of object type
  56. * @return The new object or nULL
  57. */
  58. int nl_object_alloc_name(const char *kind, struct nl_object **result)
  59. {
  60. struct nl_cache_ops *ops;
  61. ops = nl_cache_ops_lookup(kind);
  62. if (!ops)
  63. return -NLE_OPNOTSUPP;
  64. if (!(*result = nl_object_alloc(ops->co_obj_ops)))
  65. return -NLE_NOMEM;
  66. return 0;
  67. }
  68. #endif
  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 = obj_ops(obj);
  112. if (obj->ce_refcnt > 0)
  113. NL_DBG(1, "Warning: Freeing object in use...\n");
  114. if (obj->ce_cache)
  115. nl_cache_remove(obj);
  116. if (ops->oo_free_data)
  117. ops->oo_free_data(obj);
  118. free(obj);
  119. NL_DBG(4, "Freed object %p\n", obj);
  120. }
  121. /** @} */
  122. /**
  123. * @name Reference Management
  124. * @{
  125. */
  126. /**
  127. * Acquire a reference on a object
  128. * @arg obj object to acquire reference from
  129. */
  130. void nl_object_get(struct nl_object *obj)
  131. {
  132. obj->ce_refcnt++;
  133. NL_DBG(4, "New reference to object %p, total %d\n",
  134. obj, obj->ce_refcnt);
  135. }
  136. /**
  137. * Release a reference from an object
  138. * @arg obj object to release reference from
  139. */
  140. void nl_object_put(struct nl_object *obj)
  141. {
  142. if (!obj)
  143. return;
  144. obj->ce_refcnt--;
  145. NL_DBG(4, "Returned object reference %p, %d remaining\n",
  146. obj, obj->ce_refcnt);
  147. if (obj->ce_refcnt < 0)
  148. BUG();
  149. if (obj->ce_refcnt <= 0)
  150. nl_object_free(obj);
  151. }
  152. /** @} */
  153. /**
  154. * @name Utillities
  155. * @{
  156. */
  157. #ifdef disabled
  158. /**
  159. * Dump this object according to the specified parameters
  160. * @arg obj object to dump
  161. * @arg params dumping parameters
  162. */
  163. void nl_object_dump(struct nl_object *obj, struct nl_dump_params *params)
  164. {
  165. dump_from_ops(obj, params);
  166. }
  167. /**
  168. * Check if the identifiers of two objects are identical
  169. * @arg a an object
  170. * @arg b another object of same type
  171. *
  172. * @return true if both objects have equal identifiers, otherwise false.
  173. */
  174. int nl_object_identical(struct nl_object *a, struct nl_object *b)
  175. {
  176. struct nl_object_ops *ops = obj_ops(a);
  177. int req_attrs;
  178. /* Both objects must be of same type */
  179. if (ops != obj_ops(b))
  180. return 0;
  181. req_attrs = ops->oo_id_attrs;
  182. /* Both objects must provide all required attributes to uniquely
  183. * identify an object */
  184. if ((a->ce_mask & req_attrs) != req_attrs ||
  185. (b->ce_mask & req_attrs) != req_attrs)
  186. return 0;
  187. /* Can't judge unless we can compare */
  188. if (ops->oo_compare == NULL)
  189. return 0;
  190. return !(ops->oo_compare(a, b, req_attrs, 0));
  191. }
  192. #endif
  193. /**
  194. * Compute bitmask representing difference in attribute values
  195. * @arg a an object
  196. * @arg b another object of same type
  197. *
  198. * The bitmask returned is specific to an object type, each bit set represents
  199. * an attribute which mismatches in either of the two objects. Unavailability
  200. * of an attribute in one object and presence in the other is regarded a
  201. * mismatch as well.
  202. *
  203. * @return Bitmask describing differences or 0 if they are completely identical.
  204. */
  205. uint32_t nl_object_diff(struct nl_object *a, struct nl_object *b)
  206. {
  207. struct nl_object_ops *ops = obj_ops(a);
  208. if (ops != obj_ops(b) || ops->oo_compare == NULL)
  209. return UINT_MAX;
  210. return ops->oo_compare(a, b, ~0, 0);
  211. }
  212. /**
  213. * Match a filter against an object
  214. * @arg obj object to check
  215. * @arg filter object of same type acting as filter
  216. *
  217. * @return 1 if the object matches the filter or 0
  218. * if no filter procedure is available or if the
  219. * filter does not match.
  220. */
  221. int nl_object_match_filter(struct nl_object *obj, struct nl_object *filter)
  222. {
  223. struct nl_object_ops *ops = obj_ops(obj);
  224. if (ops != obj_ops(filter) || ops->oo_compare == NULL)
  225. return 0;
  226. return !(ops->oo_compare(obj, filter, filter->ce_mask,
  227. LOOSE_COMPARISON));
  228. }
  229. /**
  230. * Convert bitmask of attributes to a character string
  231. * @arg obj object of same type as attribute bitmask
  232. * @arg attrs bitmask of attribute types
  233. * @arg buf destination buffer
  234. * @arg len length of destination buffer
  235. *
  236. * Converts the bitmask of attribute types into a list of attribute
  237. * names separated by comas.
  238. *
  239. * @return destination buffer.
  240. */
  241. char *nl_object_attrs2str(struct nl_object *obj, uint32_t attrs,
  242. char *buf, size_t len)
  243. {
  244. struct nl_object_ops *ops = obj_ops(obj);
  245. if (ops->oo_attrs2str != NULL)
  246. return ops->oo_attrs2str(attrs, buf, len);
  247. else {
  248. memset(buf, 0, len);
  249. return buf;
  250. }
  251. }
  252. /** @} */
  253. /** @} */