Added per-action context
This commit is contained in:
parent
f74d274589
commit
4a02223f7c
|
@ -17,11 +17,19 @@ struct action_stack {
|
|||
GArray* stack;
|
||||
};
|
||||
|
||||
typedef handler_t (*ActionFunc)(vrequest *vr, gpointer param);
|
||||
/* param is the param registered with the callbacks;
|
||||
* in context the function can save extra data (like data for the stat-call)
|
||||
* If the context gets popped from the action stack and context is not zero,
|
||||
* the cleanup callback gets called.
|
||||
* you should not use *context without a cleanup callback!!!
|
||||
*/
|
||||
typedef handler_t (*ActionFunc)(vrequest *vr, gpointer param, gpointer *context);
|
||||
typedef handler_t (*ActionCleanup)(vrequest *vr, gpointer param, gpointer context);
|
||||
typedef void (*ActionFree)(server *srv, gpointer param);
|
||||
|
||||
struct action_func {
|
||||
ActionFunc func;
|
||||
ActionCleanup cleanup;
|
||||
ActionFree free;
|
||||
gpointer param;
|
||||
};
|
||||
|
@ -48,8 +56,8 @@ struct action {
|
|||
|
||||
/* no new/free function, so just use the struct direct (i.e. not a pointer) */
|
||||
LI_API void action_stack_init(action_stack *as);
|
||||
LI_API void action_stack_reset(server *srv, action_stack *as);
|
||||
LI_API void action_stack_clear(server *srv, action_stack *as);
|
||||
LI_API void action_stack_reset(vrequest *vr, action_stack *as);
|
||||
LI_API void action_stack_clear(vrequest *vr, action_stack *as);
|
||||
|
||||
/** handle sublist now, remember current position (stack) */
|
||||
LI_API void action_enter(struct vrequest *vr, action *a);
|
||||
|
@ -60,7 +68,7 @@ LI_API void action_release(server *srv, action *a);
|
|||
LI_API void action_acquire(action *a);
|
||||
/* create new action */
|
||||
LI_API action *action_new_setting(option_set setting);
|
||||
LI_API action *action_new_function(ActionFunc func, ActionFree ffree, gpointer param);
|
||||
LI_API action *action_new_function(ActionFunc func, ActionCleanup fcleanup, ActionFree ffree, gpointer param);
|
||||
LI_API action *action_new_list();
|
||||
LI_API action *action_new_condition(condition *cond, action *target, action *target_else);
|
||||
|
||||
|
|
|
@ -6,7 +6,11 @@ typedef struct action_stack_element action_stack_element;
|
|||
|
||||
struct action_stack_element {
|
||||
action *act;
|
||||
guint pos;
|
||||
union {
|
||||
gpointer context;
|
||||
guint pos;
|
||||
} data;
|
||||
gboolean finished;
|
||||
};
|
||||
|
||||
void action_release(server *srv, action *a) {
|
||||
|
@ -54,13 +58,14 @@ action *action_new_setting(option_set setting) {
|
|||
return a;
|
||||
}
|
||||
|
||||
action *action_new_function(ActionFunc func, ActionFree ffree, gpointer param) {
|
||||
action *action_new_function(ActionFunc func, ActionCleanup fcleanup, ActionFree ffree, gpointer param) {
|
||||
action *a;
|
||||
|
||||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TFUNCTION;
|
||||
a->data.function.func = func;
|
||||
a->data.function.cleanup = fcleanup;
|
||||
a->data.function.free = ffree;
|
||||
a->data.function.param = param;
|
||||
|
||||
|
@ -91,28 +96,35 @@ action *action_new_condition(condition *cond, action *target, action *target_els
|
|||
return a;
|
||||
}
|
||||
|
||||
void action_stack_element_release(server *srv, action_stack_element *ase) {
|
||||
if (!ase || !ase->act) return;
|
||||
static void action_stack_element_release(server *srv, vrequest *vr, action_stack_element *ase) {
|
||||
action *a = ase->act;
|
||||
if (!ase || !a) return;
|
||||
if (a->type == ACTION_TFUNCTION && ase->data.context && a->data.function.cleanup) {
|
||||
a->data.function.cleanup(vr, a->data.function.param, ase->data.context);
|
||||
}
|
||||
action_release(srv, ase->act);
|
||||
ase->act = NULL;
|
||||
ase->data.context = NULL;
|
||||
}
|
||||
|
||||
void action_stack_init(action_stack *as) {
|
||||
as->stack = g_array_sized_new(FALSE, TRUE, sizeof(action_stack_element), 15);
|
||||
}
|
||||
|
||||
void action_stack_reset(server *srv, action_stack *as) {
|
||||
void action_stack_reset(vrequest *vr, action_stack *as) {
|
||||
server *srv = vr->con->srv;
|
||||
guint i;
|
||||
for (i = as->stack->len; i-- > 0; ) {
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, i));
|
||||
action_stack_element_release(srv, vr, &g_array_index(as->stack, action_stack_element, i));
|
||||
}
|
||||
g_array_set_size(as->stack, 0);
|
||||
}
|
||||
|
||||
void action_stack_clear(server *srv, action_stack *as) {
|
||||
void action_stack_clear(vrequest *vr, action_stack *as) {
|
||||
server *srv = vr->con->srv;
|
||||
guint i;
|
||||
for (i = as->stack->len; i-- > 0; ) {
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, i));
|
||||
action_stack_element_release(srv, vr, &g_array_index(as->stack, action_stack_element, i));
|
||||
}
|
||||
g_array_free(as->stack, TRUE);
|
||||
as->stack = NULL;
|
||||
|
@ -121,7 +133,7 @@ void action_stack_clear(server *srv, action_stack *as) {
|
|||
/** handle sublist now, remember current position (stack) */
|
||||
void action_enter(vrequest *vr, action *a) {
|
||||
action_acquire(a);
|
||||
action_stack_element ase = { a, 0 };
|
||||
action_stack_element ase = { a, { 0 }, FALSE };
|
||||
g_array_append_val(vr->action_stack.stack, ase);
|
||||
}
|
||||
|
||||
|
@ -129,48 +141,45 @@ static action_stack_element *action_stack_top(action_stack* as) {
|
|||
return as->stack->len > 0 ? &g_array_index(as->stack, action_stack_element, as->stack->len - 1) : NULL;
|
||||
}
|
||||
|
||||
static void action_stack_pop(server *srv, action_stack *as) {
|
||||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, as->stack->len - 1));
|
||||
static void action_stack_pop(server *srv, vrequest *vr, action_stack *as) {
|
||||
action_stack_element_release(srv, vr, &g_array_index(as->stack, action_stack_element, as->stack->len - 1));
|
||||
g_array_set_size(as->stack, as->stack->len - 1);
|
||||
}
|
||||
|
||||
static action* action_stack_element_action(action_stack_element *ase) {
|
||||
action *a = ase->act;
|
||||
if (a->type == ACTION_TLIST) {
|
||||
return ase->pos < a->data.list->len ? g_array_index(a->data.list, action*, ase->pos) : NULL;
|
||||
} else {
|
||||
return ase->pos == 0 ? a : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
handler_t action_execute(vrequest *vr) {
|
||||
action *a;
|
||||
action_stack *as = &vr->action_stack;
|
||||
action_stack_element *ase;
|
||||
handler_t res;
|
||||
gboolean condres;
|
||||
server *srv = vr->con->srv;
|
||||
|
||||
while (NULL != (ase = action_stack_top(as))) {
|
||||
a = action_stack_element_action(ase);
|
||||
if (!a) {
|
||||
action_stack_pop(vr->con->srv, as);
|
||||
if (ase->finished) {
|
||||
/* a TFUNCTION may enter sub actions _and_ return GO_ON, so we cannot pop the last element
|
||||
* but we have to remember we already executed it
|
||||
*/
|
||||
action_stack_pop(srv, vr, as);
|
||||
continue;
|
||||
}
|
||||
|
||||
a = ase->act;
|
||||
vr->con->wrk->stats.actions_executed++;
|
||||
|
||||
switch (a->type) {
|
||||
case ACTION_TSETTING:
|
||||
vr->con->options[a->data.setting.ndx] = a->data.setting.value;
|
||||
action_stack_pop(srv, vr, as);
|
||||
break;
|
||||
case ACTION_TFUNCTION:
|
||||
res = a->data.function.func(vr, a->data.function.param);
|
||||
res = a->data.function.func(vr, a->data.function.param, &ase->data.context);
|
||||
switch (res) {
|
||||
case HANDLER_GO_ON:
|
||||
case HANDLER_FINISHED:
|
||||
ase->finished = TRUE;
|
||||
break;
|
||||
case HANDLER_ERROR:
|
||||
action_stack_reset(vr->con->srv, as);
|
||||
action_stack_reset(vr, as);
|
||||
case HANDLER_COMEBACK:
|
||||
case HANDLER_WAIT_FOR_EVENT:
|
||||
case HANDLER_WAIT_FOR_FD:
|
||||
|
@ -183,6 +192,7 @@ handler_t action_execute(vrequest *vr) {
|
|||
switch (res) {
|
||||
case HANDLER_GO_ON:
|
||||
case HANDLER_FINISHED:
|
||||
action_stack_pop(srv, vr, as);
|
||||
if (condres) {
|
||||
action_enter(vr, a->data.condition.target);
|
||||
}
|
||||
|
@ -191,7 +201,7 @@ handler_t action_execute(vrequest *vr) {
|
|||
}
|
||||
break;
|
||||
case HANDLER_ERROR:
|
||||
action_stack_reset(vr->con->srv, as);
|
||||
action_stack_reset(vr, as);
|
||||
case HANDLER_COMEBACK:
|
||||
case HANDLER_WAIT_FOR_EVENT:
|
||||
case HANDLER_WAIT_FOR_FD:
|
||||
|
@ -199,10 +209,14 @@ handler_t action_execute(vrequest *vr) {
|
|||
}
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
action_enter(vr, a);
|
||||
if (ase->data.pos >= a->data.list->len) {
|
||||
action_stack_pop(srv, vr, as);
|
||||
} else {
|
||||
action_enter(vr, g_array_index(a->data.list, action*, ase->data.pos));
|
||||
ase->data.pos++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
ase->pos++;
|
||||
}
|
||||
return HANDLER_FINISHED;
|
||||
}
|
||||
|
|
|
@ -140,8 +140,9 @@ static gboolean core_setup_set(server *srv, plugin* p, value *val) {
|
|||
return plugin_set_default_option(srv, val_name->data.string->str, val_val);
|
||||
}
|
||||
|
||||
static handler_t core_handle_static(vrequest *vr, gpointer param) {
|
||||
static handler_t core_handle_static(vrequest *vr, gpointer param, gpointer *context) {
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
int fd;
|
||||
|
||||
/* build physical path: docroot + uri.path */
|
||||
|
@ -200,10 +201,10 @@ static action* core_static(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_static, NULL, NULL);
|
||||
return action_new_function(core_handle_static, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static handler_t core_handle_test(vrequest *vr, gpointer param) {
|
||||
static handler_t core_handle_test(vrequest *vr, gpointer param, gpointer *context) {
|
||||
connection *con = vr->con;
|
||||
server *srv = con->srv;
|
||||
worker *wrk = con->wrk;
|
||||
|
@ -216,6 +217,7 @@ static handler_t core_handle_test(vrequest *vr, gpointer param) {
|
|||
guint64 avg1, avg2, avg3;
|
||||
gchar suffix1[2] = {0,0}, suffix2[2] = {0,0}, suffix3[2] = {0,0};
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
if (!vrequest_handle_direct(vr)) return HANDLER_GO_ON;
|
||||
|
||||
|
@ -281,11 +283,12 @@ static action* core_test(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_test, NULL, NULL);
|
||||
return action_new_function(core_handle_test, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static handler_t core_handle_blank(vrequest *vr, gpointer param) {
|
||||
static handler_t core_handle_blank(vrequest *vr, gpointer param, gpointer *context) {
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
if (!vrequest_handle_direct(vr)) return HANDLER_GO_ON;
|
||||
|
||||
|
@ -302,12 +305,13 @@ static action* core_blank(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_blank, NULL, NULL);
|
||||
return action_new_function(core_handle_blank, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static handler_t core_handle_profile_mem(vrequest *vr, gpointer param) {
|
||||
static handler_t core_handle_profile_mem(vrequest *vr, gpointer param, gpointer *context) {
|
||||
UNUSED(vr);
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
/*g_mem_profile();*/
|
||||
profiler_dump();
|
||||
|
@ -323,7 +327,7 @@ static action* core_profile_mem(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_profile_mem, NULL, NULL);
|
||||
return action_new_function(core_handle_profile_mem, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static gboolean core_listen(server *srv, plugin* p, value *val) {
|
||||
|
@ -623,10 +627,10 @@ static void core_option_log_timestamp_free(server *srv, plugin *p, size_t ndx, o
|
|||
}
|
||||
|
||||
static gboolean core_option_mime_types_parse(server *srv, plugin *p, size_t ndx, value *val, option_value *oval) {
|
||||
GArray *arr;
|
||||
UNUSED(srv);
|
||||
UNUSED(p);
|
||||
UNUSED(ndx);
|
||||
GArray *arr;
|
||||
|
||||
|
||||
/* default value */
|
||||
|
@ -675,11 +679,12 @@ static void core_option_mime_types_free(server *srv, plugin *p, size_t ndx, opti
|
|||
g_array_free(oval.list, TRUE);
|
||||
}
|
||||
|
||||
static handler_t core_handle_header_add(vrequest *vr, gpointer param) {
|
||||
UNUSED(param);
|
||||
static handler_t core_handle_header_add(vrequest *vr, gpointer param, gpointer *context) {
|
||||
GArray *l = (GArray*)param;
|
||||
GString *k = g_array_index(l, value*, 0)->data.string;
|
||||
GString *v = g_array_index(l, value*, 1)->data.string;
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
http_header_insert(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v));
|
||||
|
||||
|
@ -712,15 +717,16 @@ static action* core_header_add(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_header_add, core_header_free, value_extract(val).list);
|
||||
return action_new_function(core_handle_header_add, NULL, core_header_free, value_extract(val).list);
|
||||
}
|
||||
|
||||
|
||||
static handler_t core_handle_header_append(vrequest *vr, gpointer param) {
|
||||
UNUSED(param);
|
||||
static handler_t core_handle_header_append(vrequest *vr, gpointer param, gpointer *context) {
|
||||
GArray *l = (GArray*)param;
|
||||
GString *k = g_array_index(l, value*, 0)->data.string;
|
||||
GString *v = g_array_index(l, value*, 1)->data.string;
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
http_header_append(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v));
|
||||
|
||||
|
@ -748,15 +754,16 @@ static action* core_header_append(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_header_append, core_header_free, value_extract(val).list);
|
||||
return action_new_function(core_handle_header_append, NULL, core_header_free, value_extract(val).list);
|
||||
}
|
||||
|
||||
|
||||
static handler_t core_handle_header_overwrite(vrequest *vr, gpointer param) {
|
||||
UNUSED(param);
|
||||
static handler_t core_handle_header_overwrite(vrequest *vr, gpointer param, gpointer *context) {
|
||||
GArray *l = (GArray*)param;
|
||||
GString *k = g_array_index(l, value*, 0)->data.string;
|
||||
GString *v = g_array_index(l, value*, 1)->data.string;
|
||||
UNUSED(param);
|
||||
UNUSED(context);
|
||||
|
||||
http_header_overwrite(vr->response.headers, GSTR_LEN(k), GSTR_LEN(v));
|
||||
|
||||
|
@ -784,7 +791,7 @@ static action* core_header_overwrite(server *srv, plugin* p, value *val) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return action_new_function(core_handle_header_overwrite, core_header_free, value_extract(val).list);
|
||||
return action_new_function(core_handle_header_overwrite, NULL, core_header_free, value_extract(val).list);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ void vrequest_free(vrequest* vr) {
|
|||
filters_clean(&vr->filters_in);
|
||||
filters_clean(&vr->filters_out);
|
||||
|
||||
action_stack_clear(vr->con->srv, &vr->action_stack);
|
||||
action_stack_clear(vr, &vr->action_stack);
|
||||
|
||||
g_slice_free(vrequest, vr);
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ void vrequest_reset(vrequest *vr) {
|
|||
filters_reset(&vr->filters_in);
|
||||
filters_reset(&vr->filters_out);
|
||||
|
||||
action_stack_reset(vr->con->srv, &vr->action_stack);
|
||||
action_stack_reset(vr, &vr->action_stack);
|
||||
}
|
||||
|
||||
void vrequest_error(vrequest *vr) {
|
||||
|
|
Loading…
Reference in New Issue