[PATCH v2] cache_mngr: add include callback v2
Thomas Haller
thaller at redhat.com
Sat Sep 24 07:23:39 PDT 2016
On Mon, 2016-09-12 at 21:54 +0200, Tobias Jungel wrote:
> This patch adds change_func_v2_t to add a more detailed callback in
> case of a cache change. In case the new change function is set using
> nl_cache_mngr_set_change_func_v2, nl_cache_include_v2 and thus
> cache_include_v2 will be used perform the cache inclusion.
>
> The parameter of change_func_v2_t are the following:
> * struct nl_cache * => cache
> * struct nl_object * => the old/deleted nl_object
> * struct nl_object * => the new nl_object
> * uint64_t => the result of nl_object_diff64 in case of a change
> * int => NL_ACT_*
> * void * => data
>
> Signed-off-by: Tobias Jungel <tobias.jungel at bisdn.de>
Hi Tobias,
adding a v2 callback is not so nice... Ok, I don't see how to do it
better, if you need this functionality.
Can you justify shortly why you (really) need this functionality?
> ---
> include/netlink-private/cache-api.h | 1 +
> include/netlink-private/types.h | 1 +
> include/netlink/cache.h | 10 +++++
> lib/cache.c | 68
> +++++++++++++++++++++++++++++-----
> lib/cache_mngr.c | 73
> ++++++++++++++++++++++++++++++++++++-
> libnl-3.sym | 2 +
> 6 files changed, 144 insertions(+), 11 deletions(-)
>
> diff --git a/include/netlink-private/cache-api.h b/include/netlink-
> private/cache-api.h
> index f3d9f01..c306eb5 100644
> --- a/include/netlink-private/cache-api.h
> +++ b/include/netlink-private/cache-api.h
> @@ -236,6 +236,7 @@ struct nl_cache_ops
> *
> * @see nl_cache_include()
> */
> + // TODO this has to be updated as well to support cb_v2
> int (*co_include_event)(struct nl_cache *cache, struct
> nl_object *obj,
this is private API, so you can just change it as there is no stable
ABI between libnl-route-3.so and libnl-3.so.
> change_func_t change_cb, void
> *data);
>
> diff --git a/include/netlink-private/types.h b/include/netlink-
> private/types.h
> index e80c8a1..4702162 100644
> --- a/include/netlink-private/types.h
> +++ b/include/netlink-private/types.h
> @@ -96,6 +96,7 @@ struct nl_cache_assoc
> {
> struct nl_cache * ca_cache;
> change_func_t ca_change;
> + change_func_v2_t ca_change_v2;
> void * ca_change_data;
> };
>
> diff --git a/include/netlink/cache.h b/include/netlink/cache.h
> index 71eaceb..ad8da60 100644
> --- a/include/netlink/cache.h
> +++ b/include/netlink/cache.h
> @@ -35,6 +35,8 @@ enum {
>
> struct nl_cache;
> typedef void (*change_func_t)(struct nl_cache *, struct nl_object *,
> int, void *);
> +typedef void (*change_func_v2_t)(struct nl_cache *, struct nl_object
> *,
> + struct nl_object *, uint64_t, int, void *);
>
> /**
> * @ingroup cache
> @@ -88,6 +90,10 @@ extern int nl_cache_include
> (struct nl_cache *,
> struct nl_object *,
> change_func_t,
> void *);
> +extern int nl_cache_include_v2(struct
> nl_cache *,
> + struct nl_object
> *,
> + change_func_v2_t
> ,
> + void *);
> extern void nl_cache_set_arg1(struct nl_cache
> *, int);
> extern void nl_cache_set_arg2(struct nl_cache
> *, int);
> extern void nl_cache_set_flags(struct
> nl_cache *, unsigned int);
> @@ -154,6 +160,10 @@ extern int nl_cache_mngr_
> add(struct nl_cache_mngr *,
> extern int nl_cache_mngr_add_cache(struct
> nl_cache_mngr *mngr,
> struct
> nl_cache *cache,
> change_func_
> t cb, void *data);
> +extern int nl_cache_mngr_set_change_func_v2(s
> truct nl_cache_mngr *mngr,
> + str
> uct nl_cache *cache,
> + cha
> nge_func_v2_t cb,
> + voi
> d *data);
> extern int nl_cache_mngr_get_fd(struct
> nl_cache_mngr *);
> extern int nl_cache_mngr_poll(struct
> nl_cache_mngr *,
> int);
> diff --git a/lib/cache.c b/lib/cache.c
> index d8592b6..8e9de0d 100644
> --- a/lib/cache.c
> +++ b/lib/cache.c
> @@ -784,30 +784,45 @@ int nl_cache_pickup(struct nl_sock *sk, struct
> nl_cache *cache)
> }
>
> static int cache_include(struct nl_cache *cache, struct nl_object
> *obj,
> - struct nl_msgtype *type, change_func_t cb,
> void *data)
> + struct nl_msgtype *type, change_func_t cb,
> + change_func_v2_t cb_v2, void *data)
> {
> struct nl_object *old;
> + struct nl_object *clone = NULL;
trailing whitespace
> + uint64_t diff;
>
> switch (type->mt_act) {
> case NL_ACT_NEW:
> case NL_ACT_DEL:
> old = nl_cache_search(cache, obj);
> if (old) {
> + if (cb_v2) {
> + clone = nl_object_clone(old);
> + diff = nl_object_diff64(old, obj);
> + }
> /*
> * Some objects types might support merging
> the new
> * object with the old existing cache
> object.
> * Handle them first.
> */
> if (nl_object_update(old, obj) == 0) {
> - if (cb)
> + if (cb_v2) {
> + cb_v2(cache, clone, obj,
> diff,
> + NL_ACT_CHANGE, data);
in this case the old-argument "clone" was never part of the cache.
I think that is rather unexpected, isn't it?
Maybe there should be a new NL_ACT_UPDATE for this case. Then you could
also avoid calculating "diff", because it's clear that with
NL_ACT_UPDATE:
- diff is 0
- old is a clone before the update (but itself was never inside the
cache)
- new is the updated object aftet the update.
after all, "diff" is only mildly useful because all the flags are
internal API, so a user doesn't know what these flags mean anyway.
For that reason, maybe the "diff" argument shouldn't be passed to the
callback, but well...
> + nl_object_put(clone);
> + } else if (cb)
> cb(cache, old,
> NL_ACT_CHANGE, data);
> nl_object_put(old);
> return 0;
> }
> + nl_object_put(clone);
>
> nl_cache_remove(old);
> if (type->mt_act == NL_ACT_DEL) {
> - if (cb)
> + if (cb_v2)
> + cb_v2(cache, old, NULL, 0,
> NL_ACT_DEL,
> + data);
When the command of on "if" spawns more then one line, please { }.
Same below.
> + else if (cb)
> cb(cache, old, NL_ACT_DEL,
> data);
> nl_object_put(old);
> }
> @@ -815,10 +830,20 @@ static int cache_include(struct nl_cache
> *cache, struct nl_object *obj,
>
> if (type->mt_act == NL_ACT_NEW) {
> nl_cache_move(cache, obj);
> - if (old == NULL && cb)
> - cb(cache, obj, NL_ACT_NEW, data);
> - else if (old) {
> - if (nl_object_diff(old, obj) && cb)
> + if (old == NULL) {
> + if (cb_v2)
> + cb_v2(cache, NULL, obj, 0,
> NL_ACT_NEW,
> + data);
> + else if (cb)
> + cb(cache, obj, NL_ACT_NEW,
> data);
> + } else if (old) {
> + uint64_t diff = 0;
> + if (cb || cb_v2)
whitespace.
>
> + diff = nl_object_diff64(old,
> obj);
> + if (diff && cb_v2)
> + cb_v2(cache, old, obj, diff,
> NL_ACT_CHANGE,
> + data);
> + else if (diff && cb)
> cb(cache, obj,
> NL_ACT_CHANGE, data);
>
> nl_object_put(old);
> @@ -845,7 +870,27 @@ int nl_cache_include(struct nl_cache *cache,
> struct nl_object *obj,
> for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
> if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
> return cache_include(cache, obj, &ops-
> >co_msgtypes[i],
> - change_cb, data);
> + change_cb, NULL, data);
> +
> + NL_DBG(3, "Object %p does not seem to belong to cache %p
> <%s>\n",
> + obj, cache, nl_cache_name(cache));
> +
> + return -NLE_MSGTYPE_NOSUPPORT;
> +}
> +
> +int nl_cache_include_v2(struct nl_cache *cache, struct nl_object
> *obj,
> + change_func_v2_t change_cb, void *data)
> +{
> + struct nl_cache_ops *ops = cache->c_ops;
> + int i;
> +
> + if (ops->co_obj_ops != obj->ce_ops)
> + return -NLE_OBJ_MISMATCH;
> +
> + for (i = 0; ops->co_msgtypes[i].mt_id >= 0; i++)
> + if (ops->co_msgtypes[i].mt_id == obj->ce_msgtype)
> + return cache_include(cache, obj, &ops-
> >co_msgtypes[i],
> + NULL, change_cb,
> data);
>
> NL_DBG(3, "Object %p does not seem to belong to cache %p
> <%s>\n",
> obj, cache, nl_cache_name(cache));
> @@ -857,7 +902,12 @@ static int resync_cb(struct nl_object *c, struct
> nl_parser_param *p)
> {
> struct nl_cache_assoc *ca = p->pp_arg;
>
> - return nl_cache_include(ca->ca_cache, c, ca->ca_change, ca-
> >ca_change_data);
> + if (ca->ca_change_v2)
> + return nl_cache_include_v2(ca->ca_cache, c, ca-
> >ca_change_v2,
> + ca->ca_change_data);
> + else
> + return nl_cache_include(ca->ca_cache, c, ca-
> >ca_change,
> + ca->ca_change_data);
> }
>
> int nl_cache_resync(struct nl_sock *sk, struct nl_cache *cache,
> diff --git a/lib/cache_mngr.c b/lib/cache_mngr.c
> index 1f23eb1..8715931 100644
> --- a/lib/cache_mngr.c
> +++ b/lib/cache_mngr.c
> @@ -61,8 +61,13 @@ static int include_cb(struct nl_object *obj,
> struct nl_parser_param *p)
> if (ops->co_include_event)
> return ops->co_include_event(ca->ca_cache, obj, ca-
> >ca_change,
> ca->ca_change_data);
> - else
> - return nl_cache_include(ca->ca_cache, obj, ca-
> >ca_change, ca->ca_change_data);
> + else {
> + if (ca->ca_change_v2)
> + return nl_cache_include_v2(ca->ca_cache,
> obj, ca->ca_change_v2, ca->ca_change_data);
> + else
> + return nl_cache_include(ca->ca_cache, obj,
> ca->ca_change, ca->ca_change_data);
> + }
> +
> }
>
> static int event_input(struct nl_msg *msg, void *arg)
> @@ -349,6 +354,70 @@ errout_free_cache:
> }
>
> /**
> + * Set change_func_v2 for cache manager
> + * @arg mngr Cache manager.
> + * @arg cache Cache associated with the callback
> + * @arg cb Function to be called upon changes.
> + * @arg data Argument passed on to change callback
> + *
> + * Adds callback change_func_v2 to a registered cache. This callback
> provides
> + * in like the standard change_func the added or remove netlink
> object. In case
> + * of a change the old and the new object is provided as well as the
> according
> + * diff. If this callback is registered this has a higher priority
> then the
> + * change_func registered during cache registration. Hence only one
> callback is
> + * executed.
> + *
> + * The first netlink object in the callback is refering to the old
> object and
> + * the second to the new. This means on NL_ACT_CHANGE the first is
> the previous
> + * object in the cache and the second the updated version. On
> NL_ACT_DEL the
> + * first is the deleted object the second is NULL. On NL_ACT_NEW the
> first is
> + * NULL and the second the new netlink object.
> + *
> + * The user is responsible for calling nl_cache_mngr_poll() or
> monitor
> + * the socket and call nl_cache_mngr_data_ready() to allow the
> library
> + * to process netlink notification events.
> + *
> + * @see nl_cache_mngr_poll()
> + * @see nl_cache_mngr_data_ready()
> + *
> + * @return 0 on success or a negative error code.
> + * @return -NLE_PROTO_MISMATCH Protocol mismatch between cache
> manager and
> + * cache type
> + * @return -NLE_OPNOTSUPP Cache type does not support updates
> + * @return -NLE_RANGE Cache of this type is not registered
> + */
> +int nl_cache_mngr_set_change_func_v2(struct nl_cache_mngr *mngr,
> + struct nl_cache *cache,
> + change_func_v2_t cb, void
is a user supposed to call first nl_cache_mngr_add_cache() followed
by nl_cache_mngr_set_change_func_v2()?
That seems confusing, maybe there should be a
nl_cache_mngr_add_cache_v2().
> *data)
> +{
> + struct nl_cache_ops *ops;
> + int i;
> +
> + ops = cache->c_ops;
> + if (!ops)
> + return -NLE_INVAL;
> +
> + if (ops->co_protocol != mngr->cm_protocol)
> + return -NLE_PROTO_MISMATCH;
> +
> + if (ops->co_groups == NULL)
> + return -NLE_OPNOTSUPP;
> +
> + for (i = 0; i < mngr->cm_nassocs; i++)
> + if (mngr->cm_assocs[i].ca_cache == cache)
> + break;
> +
> + if (i >= mngr->cm_nassocs) {
> + return -NLE_RANGE;
> + }
> +
> + mngr->cm_assocs[i].ca_change_v2 = cb;
> + mngr->cm_assocs[i].ca_change_data = data; // TODO different
> data for v2?
> +
> + return 0;
> +}
> +
> +/**
> * Get socket file descriptor
> * @arg mngr Cache Manager
> *
> diff --git a/libnl-3.sym b/libnl-3.sym
> index 9119e66..0ba82e0 100644
> --- a/libnl-3.sym
> +++ b/libnl-3.sym
> @@ -68,6 +68,7 @@ global:
> nl_cache_get_ops;
> nl_cache_get_prev;
> nl_cache_include;
> + nl_cache_include_v2;
a linker symbols section must not be modified/extended after the
release. New symbols must go to a separate section, that is:
libnl_3_2_29.
> nl_cache_is_empty;
> nl_cache_mark_all;
> nl_cache_mngr_add;
> @@ -82,6 +83,7 @@ global:
> nl_cache_mngt_register;
> nl_cache_mngt_require;
> nl_cache_mngt_require_safe;
> + nl_cache_mngr_set_change_func_v2;
> nl_cache_mngt_unprovide;
> nl_cache_mngt_unregister;
> nl_cache_move;
Thomas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/libnl/attachments/20160924/9ac54387/attachment.sig>
More information about the libnl
mailing list