2
0
Fork 0

Added per-action context

This commit is contained in:
Stefan Bühler 2008-12-10 00:23:27 +01:00
parent f74d274589
commit 4a02223f7c
4 changed files with 81 additions and 52 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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) {