diff options
-rw-r--r-- | include/afb/afb-req-common.h | 24 | ||||
-rw-r--r-- | src/afb-context.c | 4 | ||||
-rw-r--r-- | src/afb-context.h | 2 | ||||
-rw-r--r-- | src/afb-hook.c | 14 | ||||
-rw-r--r-- | src/afb-hook.h | 6 | ||||
-rw-r--r-- | src/afb-session.c | 20 | ||||
-rw-r--r-- | src/afb-session.h | 2 | ||||
-rw-r--r-- | src/afb-trace.c | 19 | ||||
-rw-r--r-- | src/afb-xreq.c | 19 |
9 files changed, 89 insertions, 21 deletions
diff --git a/include/afb/afb-req-common.h b/include/afb/afb-req-common.h index 1bb017ef..adb0acf4 100644 --- a/include/afb/afb-req-common.h +++ b/include/afb/afb-req-common.h @@ -77,6 +77,8 @@ struct afb_req_itf int (*has_permission)(void *closure, const char *permission); char *(*get_application_id)(void *closure); + + void *(*context_make)(void *closure, int replace, void *(*create_value)(void *creation_closure), void (*free_value)(void*), void *creation_closure); }; /* @@ -257,12 +259,22 @@ static inline void afb_req_context_set(struct afb_req req, void *context, void ( */ static inline void *afb_req_context(struct afb_req req, void *(*create_context)(), void (*free_context)(void*)) { - void *result = afb_req_context_get(req); - if (!result) { - result = create_context(); - afb_req_context_set(req, result, free_context); - } - return result; + return req.itf->context_make(req.closure, 0, (void *(*)(void*))(void*)create_context, free_context, 0); +} + +/* + * Gets the pointer stored by the binding for the session of 'request'. + * If no previous pointer is stored or if 'replace' is not zero, a new value + * is generated using the function 'create_context' called with the 'closure'. + * If 'create_context' is NULL the generated value is 'closure'. + * When a value is created, the function 'free_context' is recorded and will + * be called (with the created value as argument) to free the created value when + * it is not more used. + * This function is atomic: it ensures that 2 threads will not race together. + */ +static inline void *afb_req_context_make(struct afb_req req, int replace, void *(*create_context)(void *closure), void (*free_context)(void*), void *closure) +{ + return req.itf->context_make(req.closure, replace, create_context, free_context, closure); } /* diff --git a/src/afb-context.c b/src/afb-context.c index 11abcd48..759ee90e 100644 --- a/src/afb-context.c +++ b/src/afb-context.c @@ -118,10 +118,10 @@ const char *afb_context_sent_uuid(struct afb_context *context) return afb_session_uuid(context->session); } -void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*)) +void *afb_context_make(struct afb_context *context, int replace, void *(*make_value)(void *closure), void (*free_value)(void *item), void *closure) { assert(context->session != NULL); - return afb_session_cookie(context->session, context->api_key, make_value, free_value); + return afb_session_cookie(context->session, context->api_key, make_value, free_value, closure, replace); } void *afb_context_get(struct afb_context *context) diff --git a/src/afb-context.h b/src/afb-context.h index 47e488c4..a3e4e568 100644 --- a/src/afb-context.h +++ b/src/afb-context.h @@ -48,7 +48,7 @@ extern const char *afb_context_uuid(struct afb_context *context); extern void *afb_context_get(struct afb_context *context); extern int afb_context_set(struct afb_context *context, void *value, void (*free_value)(void*)); -extern void *afb_context_data(struct afb_context *context, void *(*make_value)(void), void (*free_value)(void*)); +extern void *afb_context_make(struct afb_context *context, int replace, void *(*make_value)(void *closure), void (*free_value)(void *item), void *closure); extern void afb_context_close(struct afb_context *context); extern void afb_context_refresh(struct afb_context *context); diff --git a/src/afb-hook.c b/src/afb-hook.c index 188aabae..b3a13a7e 100644 --- a/src/afb-hook.c +++ b/src/afb-hook.c @@ -359,6 +359,11 @@ static void hook_xreq_get_application_id_default_cb(void *closure, const struct _hook_xreq_(xreq, "get_application_id() -> %s", result); } +static void hook_xreq_context_make_default_cb(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result) +{ + _hook_xreq_(xreq, "context_make(replace=%s, %p, %p, %p) -> %p", replace?"yes":"no", create_value, free_value, create_closure, result); +} + static struct afb_hook_xreq_itf hook_xreq_default_itf = { .hook_xreq_begin = hook_xreq_begin_default_cb, .hook_xreq_end = hook_xreq_end_default_cb, @@ -384,7 +389,8 @@ static struct afb_hook_xreq_itf hook_xreq_default_itf = { .hook_xreq_subcall_req = hook_xreq_subcall_req_default_cb, .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result_default_cb, .hook_xreq_has_permission = hook_xreq_has_permission_default_cb, - .hook_xreq_get_application_id = hook_xreq_get_application_id_default_cb + .hook_xreq_get_application_id = hook_xreq_get_application_id_default_cb, + .hook_xreq_context_make = hook_xreq_context_make_default_cb }; /****************************************************************************** @@ -544,6 +550,12 @@ char *afb_hook_xreq_get_application_id(const struct afb_xreq *xreq, char *result return result; } +void *afb_hook_xreq_context_make(const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result) +{ + _HOOK_XREQ_(context_make, xreq, replace, create_value, free_value, create_closure, result); + return result; +} + /****************************************************************************** * section: hooking xreqs *****************************************************************************/ diff --git a/src/afb-hook.h b/src/afb-hook.h index b3707a6d..be4ba54a 100644 --- a/src/afb-hook.h +++ b/src/afb-hook.h @@ -76,6 +76,7 @@ struct afb_hookid #define afb_hook_flag_req_subcall_req_result 0x00400000 #define afb_hook_flag_req_has_permission 0x00800000 #define afb_hook_flag_req_get_application_id 0x01000000 +#define afb_hook_flag_req_context_make 0x02000000 /* common flags */ #define afb_hook_flags_req_life (afb_hook_flag_req_begin|afb_hook_flag_req_end) @@ -90,7 +91,8 @@ struct afb_hookid /* extra flags */ #define afb_hook_flags_req_ref (afb_hook_flag_req_addref|afb_hook_flag_req_unref) -#define afb_hook_flags_req_context (afb_hook_flag_req_context_get|afb_hook_flag_req_context_set) +#define afb_hook_flags_req_context (afb_hook_flag_req_context_get|afb_hook_flag_req_context_set\ + |afb_hook_flag_req_context_make) #define afb_hook_flags_req_stores (afb_hook_flag_req_store|afb_hook_flag_req_unstore) /* predefined groups */ @@ -127,6 +129,7 @@ struct afb_hook_xreq_itf { void (*hook_xreq_subcall_req_result)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int status, struct json_object *result); void (*hook_xreq_has_permission)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, const char *permission, int result); void (*hook_xreq_get_application_id)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, char *result); + void (*hook_xreq_context_make)(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result); }; extern void afb_hook_init_xreq(struct afb_xreq *xreq); @@ -161,6 +164,7 @@ extern void afb_hook_xreq_subcall_req(const struct afb_xreq *xreq, const char *a extern void afb_hook_xreq_subcall_req_result(const struct afb_xreq *xreq, int status, struct json_object *result); extern int afb_hook_xreq_has_permission(const struct afb_xreq *xreq, const char *permission, int result); extern char *afb_hook_xreq_get_application_id(const struct afb_xreq *xreq, char *result); +extern void *afb_hook_xreq_context_make(const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result); /********************************************************* * section hooking export (daemon interface) diff --git a/src/afb-session.c b/src/afb-session.c index db7a99a3..61bce09a 100644 --- a/src/afb-session.c +++ b/src/afb-session.c @@ -433,7 +433,7 @@ static struct cookie *cookie_add(struct afb_session *session, int idx, const voi return cookie; } -void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*)) +void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void *closure), void (*freecb)(void *item), void *closure, int replace) { int idx; void *value; @@ -441,11 +441,19 @@ void *afb_session_cookie(struct afb_session *session, const void *key, void *(*m lock(session); cookie = cookie_search(session, key, &idx); - if (cookie) - value = cookie->value; - else { - value = makecb ? makecb() : NULL; - if (makecb || freecb) { + if (cookie) { + if (!replace) + value = cookie->value; + else { + value = makecb ? makecb(closure) : closure; + if (cookie->value != value && cookie->freecb) + cookie->freecb(cookie->value); + cookie->value = value; + cookie->freecb = freecb; + } + } else { + value = makecb ? makecb(closure) : closure; + if (replace || makecb || freecb) { cookie = cookie_add(session, idx, key, value, freecb); if (!cookie) { if (makecb && freecb) diff --git a/src/afb-session.h b/src/afb-session.h index ccedb4ab..b5dc3944 100644 --- a/src/afb-session.h +++ b/src/afb-session.h @@ -36,6 +36,6 @@ extern void afb_session_new_token(struct afb_session *session); extern const char *afb_session_token(struct afb_session *session); extern void *afb_session_get_cookie(struct afb_session *session, const void *key); -extern void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void), void (*freecb)(void*)); +extern void *afb_session_cookie(struct afb_session *session, const void *key, void *(*makecb)(void *closure), void (*freecb)(void *item), void *closure, int replace); extern int afb_session_set_cookie(struct afb_session *session, const void *key, void *value, void (*freecb)(void*)); diff --git a/src/afb-trace.c b/src/afb-trace.c index e4134103..5e82274a 100644 --- a/src/afb-trace.c +++ b/src/afb-trace.c @@ -221,6 +221,7 @@ static struct flag xreq_flags[] = { /* must be sorted by names */ { "common", afb_hook_flags_req_common }, { "context", afb_hook_flags_req_context }, { "context_get", afb_hook_flag_req_context_get }, + { "context_make", afb_hook_flag_req_context_make }, { "context_set", afb_hook_flag_req_context_set }, { "end", afb_hook_flag_req_end }, { "event", afb_hook_flags_req_event }, @@ -472,6 +473,21 @@ static void hook_xreq_get_application_id(void *closure, const struct afb_hookid "result", result); } +static void hook_xreq_context_make(void *closure, const struct afb_hookid *hookid, const struct afb_xreq *xreq, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure, void *result) +{ + char pc[50], pf[50], pv[50], pr[50]; + snprintf(pc, sizeof pc, "%p", create_value); + snprintf(pf, sizeof pf, "%p", free_value); + snprintf(pv, sizeof pv, "%p", create_closure); + snprintf(pr, sizeof pr, "%p", result); + hook_xreq(closure, hookid, xreq, "context_make", "{sb ss ss ss ss}", + "replace", replace, + "create", pc, + "free", pf, + "closure", pv, + "result", pr); +} + static struct afb_hook_xreq_itf hook_xreq_itf = { .hook_xreq_begin = hook_xreq_begin, .hook_xreq_end = hook_xreq_end, @@ -497,7 +513,8 @@ static struct afb_hook_xreq_itf hook_xreq_itf = { .hook_xreq_subcall_req = hook_xreq_subcall_req, .hook_xreq_subcall_req_result = hook_xreq_subcall_req_result, .hook_xreq_has_permission = hook_xreq_has_permission, - .hook_xreq_get_application_id = hook_xreq_get_application_id + .hook_xreq_get_application_id = hook_xreq_get_application_id, + .hook_xreq_context_make = hook_xreq_context_make }; /*******************************************************************************/ diff --git a/src/afb-xreq.c b/src/afb-xreq.c index 13deeb06..696bf9d4 100644 --- a/src/afb-xreq.c +++ b/src/afb-xreq.c @@ -527,6 +527,12 @@ static char *xreq_get_application_id_cb(void*closure) return xreq->cred && xreq->cred->id ? strdup(xreq->cred->id) : NULL; } +static void *xreq_context_make_cb(void *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure) +{ + struct afb_xreq *xreq = closure; + return afb_context_make(&xreq->context, replace, create_value, free_value, create_closure); +} + /******************************************************************************/ static struct json_object *xreq_hooked_json_cb(void *closure) @@ -696,6 +702,13 @@ static char *xreq_hooked_get_application_id_cb(void*closure) return afb_hook_xreq_get_application_id(xreq, r); } +static void *xreq_hooked_context_make_cb(void *closure, int replace, void *(*create_value)(void*), void (*free_value)(void*), void *create_closure) +{ + struct afb_xreq *xreq = closure; + void *result = xreq_context_make_cb(closure, replace, create_value, free_value, create_closure); + return afb_hook_xreq_context_make(xreq, replace, create_value, free_value, create_closure, result); +} + /******************************************************************************/ const struct afb_req_itf xreq_itf = { @@ -719,7 +732,8 @@ const struct afb_req_itf xreq_itf = { .store = xreq_store_cb, .subcall_req = xreq_subcall_req_cb, .has_permission = xreq_has_permission_cb, - .get_application_id = xreq_get_application_id_cb + .get_application_id = xreq_get_application_id_cb, + .context_make = xreq_context_make_cb }; const struct afb_req_itf xreq_hooked_itf = { @@ -743,7 +757,8 @@ const struct afb_req_itf xreq_hooked_itf = { .store = xreq_hooked_store_cb, .subcall_req = xreq_hooked_subcall_req_cb, .has_permission = xreq_hooked_has_permission_cb, - .get_application_id = xreq_hooked_get_application_id_cb + .get_application_id = xreq_hooked_get_application_id_cb, + .context_make = xreq_hooked_context_make_cb }; /******************************************************************************/ |