Implement clean default values for options

personal/stbuehler/wip
Stefan Bühler 15 years ago
parent 5d0d12c0bd
commit c54a085552

@ -232,19 +232,24 @@ void release_option(server *srv, option_set *mark) { /** Does not free the optio
/* Nothing to free */
break;
case VALUE_STRING:
g_string_free(mark->value.string, TRUE);
if (mark->value.string)
g_string_free(mark->value.string, TRUE);
break;
case VALUE_LIST:
value_list_free(mark->value.list);
if (mark->value.list)
value_list_free(mark->value.list);
break;
case VALUE_HASH:
g_hash_table_destroy(mark->value.hash);
if (mark->value.hash)
g_hash_table_destroy(mark->value.hash);
break;
case VALUE_ACTION:
action_release(srv, mark->value.action);
if (mark->value.action)
action_release(srv, mark->value.action);
break;
case VALUE_CONDITION:
condition_release(srv, mark->value.cond);
if (mark->value.cond)
condition_release(srv, mark->value.cond);
break;
}
} else {
@ -302,9 +307,11 @@ gboolean call_setup(server *srv, const char *name, value *val) {
void plugins_prepare_callbacks(server *srv) {
GHashTableIter iter;
plugin *p;
gpointer v;
g_hash_table_iter_init(&iter, srv->plugins);
while (g_hash_table_iter_next(&iter, NULL, (gpointer*) &p)) {
while (g_hash_table_iter_next(&iter, NULL, &v)) {
p = (plugin*) v;
if (p->handle_close)
g_array_append_val(srv->plugins_handle_close, p);
}
@ -318,3 +325,57 @@ void plugins_handle_close(connection *con) {
p->handle_close(con, p);
}
}
gboolean plugins_load_default_options(server *srv) {
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, srv->options);
while (g_hash_table_iter_next(&iter, &k, &v)) {
server_option *sopt = v;
option_value oval = { 0 };
if (!sopt->parse_option) {
switch (sopt->type) {
case VALUE_NONE:
break;
case VALUE_BOOLEAN:
oval.boolean = GPOINTER_TO_INT(sopt->default_value);
case VALUE_NUMBER:
oval.number = GPOINTER_TO_INT(sopt->default_value);
break;
case VALUE_STRING:
oval.string = g_string_new((const char*) sopt->default_value);
break;
default:
oval.ptr = NULL;
}
} else {
if (!sopt->parse_option(srv, sopt->p, sopt->module_index, NULL, &oval)) {
/* errors should be logged by parse function */
return FALSE;
}
}
srv->option_def_values[sopt->index] = oval;
}
return TRUE;
}
void plugins_free_default_options(server *srv) {
static const option_value oempty = {0};
GHashTableIter iter;
gpointer k, v;
g_hash_table_iter_init(&iter, srv->options);
while (g_hash_table_iter_next(&iter, &k, &v)) {
server_option *sopt = v;
option_set mark;
mark.sopt = sopt;
mark.ndx = sopt->index;
mark.value = srv->option_def_values[sopt->index];
release_option(srv, &mark);
srv->option_def_values[sopt->index] = oempty;
}
return TRUE;
}

@ -38,7 +38,6 @@ typedef void (*PluginInit) (server *srv, plugin *p);
typedef void (*PluginFree) (server *srv, plugin *p);
typedef gboolean (*PluginParseOption) (server *srv, plugin *p, size_t ndx, value *val, option_value *oval);
typedef void (*PluginFreeOption) (server *srv, plugin *p, size_t ndx, option_value oval);
typedef gpointer (*PluginDefaultValue) (server *srv, plugin *p, gsize ndx);
typedef action* (*PluginCreateAction) (server *srv, plugin *p, value *val);
typedef gboolean (*PluginSetup) (server *srv, plugin *p, value *val);
@ -77,7 +76,7 @@ struct plugin_option {
const gchar *name;
value_type type;
PluginDefaultValue default_value;
gpointer default_value;
PluginParseOption parse_option;
PluginFreeOption free_option;
};
@ -96,16 +95,28 @@ struct plugin_setup {
struct server_option {
plugin *p;
/** the plugin must free the _content_ of the value
/** the plugin must free the _content_ of the value (e.g. with option_free)
* val is zero to get the global default value if nothing is specified
* save result in value
*
* Default behaviour (NULL) is to just use the value as value
* Default behaviour (NULL) is to extract the inner value from val
*/
PluginDefaultValue default_value; /* default value callback - if no callback is provided, default value will be NULL, 0 or FALSE */
PluginParseOption parse_option;
/** the free_option handler has to free all allocated resources;
* it may get called with 0 initialized options, so you have to
* check the value.
*/
PluginFreeOption free_option;
/** if parse_option is NULL, the default_value is used; it is only used
* for the following value types:
* - BOOLEAN, NUMBER: casted with GPOINTER_TO_INT, i.e. set it with GINT_TO_POINTER
* the numbers are limited to the 32-bit range according to the glib docs
* - STRING: used for g_string_new, i.e. a const char*
*/
gpointer default_value;
size_t index, module_index;
value_type type;
};
@ -143,6 +154,9 @@ LI_API action* create_action(server *srv, const gchar *name, value *value);
/** For setup function, e.g. 'listen "127.0.0.1:8080"' */
LI_API gboolean call_setup(server *srv, const char *name, value *val);
LI_API gboolean plugins_load_default_options(server *srv);
LI_API void plugins_free_default_options(server *srv);
/* needs connection *con and plugin *p */
#define OPTION(idx) _OPTION(con, p, idx)
#define _OPTION(con, p, idx) (con->options[p->opt_base_index + idx])

@ -419,32 +419,7 @@ static gboolean core_workers(server *srv, plugin* p, value *val) {
return TRUE;
}
gpointer core_option_max_keep_alive_idle_default(server *srv, plugin *p, gsize ndx) {
UNUSED(srv);
UNUSED(p);
UNUSED(ndx);
return GINT_TO_POINTER(5);
}
gpointer core_option_server_tag_default(server *srv, plugin *p, gsize ndx) {
UNUSED(srv);
UNUSED(p);
UNUSED(ndx);
return g_string_new_len(CONST_STR_LEN("lighttpd-2.0~sandbox")); /* TODO: fix mem leak */
}
gpointer core_option_log_default(server *srv, plugin *p, gsize ndx) {
UNUSED(srv);
UNUSED(p);
UNUSED(ndx);
GArray *arr = g_array_sized_new(FALSE, TRUE, sizeof(log_t*), 5);
return arr;
}
gboolean core_option_log_parse(server *srv, plugin *p, size_t ndx, value *val, option_value *oval) {
static gboolean core_option_log_parse(server *srv, plugin *p, size_t ndx, value *val, option_value *oval) {
GHashTableIter iter;
gpointer k, v;
log_level_t level;
@ -454,7 +429,9 @@ gboolean core_option_log_parse(server *srv, plugin *p, size_t ndx, value *val, o
UNUSED(p);
UNUSED(ndx);
oval->list = arr;
g_array_set_size(arr, 5);
if (!val) return TRUE; /* default value */
g_hash_table_iter_init(&iter, val->data.hash);
while (g_hash_table_iter_next(&iter, &k, &v)) {
@ -476,36 +453,38 @@ gboolean core_option_log_parse(server *srv, plugin *p, size_t ndx, value *val, o
}
}
oval->list = arr;
return TRUE;
}
void core_option_log_free(server *srv, plugin *p, size_t ndx, option_value oval) {
static void core_option_log_free(server *srv, plugin *p, size_t ndx, option_value oval) {
UNUSED(p);
UNUSED(ndx);
GArray *arr = oval.list;
if (!arr) return;
for (guint i = 0; i < arr->len; i++) {
if (NULL != g_array_index(arr, log_t*, i))
log_unref(srv, g_array_index(arr, log_t*, i));
}
g_array_free(arr, TRUE);
}
gboolean core_option_log_timestamp_parse(server *srv, plugin *p, size_t ndx, value *val, option_value *oval) {
static gboolean core_option_log_timestamp_parse(server *srv, plugin *p, size_t ndx, value *val, option_value *oval) {
UNUSED(p);
UNUSED(ndx);
if (!val) return TRUE;
oval->ptr = log_timestamp_new(srv, val->data.string);
return TRUE;
}
void core_option_log_timestamp_free(server *srv, plugin *p, size_t ndx, option_value oval) {
static void core_option_log_timestamp_free(server *srv, plugin *p, size_t ndx, option_value oval) {
UNUSED(p);
UNUSED(ndx);
if (!oval.ptr) return;
log_timestamp_free(srv, oval.ptr);
}
@ -513,12 +492,12 @@ static const plugin_option options[] = {
{ "debug.log_request_handling", VALUE_BOOLEAN, NULL, NULL, NULL },
{ "log.timestamp", VALUE_STRING, NULL, core_option_log_timestamp_parse, core_option_log_timestamp_free },
{ "log", VALUE_HASH, core_option_log_default, core_option_log_parse, core_option_log_free },
{ "log", VALUE_HASH, NULL, core_option_log_parse, core_option_log_free },
{ "static-file.exclude", VALUE_LIST, NULL, NULL, NULL },
{ "server.tag", VALUE_STRING, core_option_server_tag_default, NULL, NULL },
{ "server.max_keep_alive_idle", VALUE_NUMBER, core_option_max_keep_alive_idle_default, NULL, NULL },
{ "server.tag", VALUE_STRING, "lighttpd-2.0~sandbox", NULL, NULL },
{ "server.max_keep_alive_idle", VALUE_NUMBER, GINT_TO_POINTER(5), NULL, NULL },
{ NULL, 0, NULL, NULL, NULL }
};

@ -122,12 +122,14 @@ void server_free(server* srv) {
action_release(srv, srv->mainaction);
if (srv->option_def_values) {
plugins_free_default_options(srv);
g_slice_free1(srv->option_count * sizeof(*srv->option_def_values), srv->option_def_values);
}
server_plugins_free(srv);
g_array_free(srv->plugins_handle_close, TRUE); /* TODO: */
if (srv->option_def_values)
g_slice_free1(srv->option_count * sizeof(*srv->option_def_values), srv->option_def_values);
/* free logs */
g_thread_join(srv->logs.thread);
{
@ -255,8 +257,6 @@ void server_listen(server *srv, int fd) {
void server_start(server *srv) {
guint i;
GHashTableIter iter;
gpointer k, v;
server_state srvstate = g_atomic_int_get(&srv->state);
if (srvstate == SERVER_STOPPING || srvstate == SERVER_RUNNING) return; /* no restart after stop */
g_atomic_int_set(&srv->state, SERVER_RUNNING);
@ -273,11 +273,10 @@ void server_start(server *srv) {
srv->option_def_values = g_slice_alloc0(srv->option_count * sizeof(*srv->option_def_values));
/* set default option values */
g_hash_table_iter_init(&iter, srv->options);
while (g_hash_table_iter_next(&iter, &k, &v)) {
server_option *so = v;
if (so->default_value)
srv->option_def_values[so->index].ptr = so->default_value(srv, so->p, so->index);
if (!plugins_load_default_options(srv)) {
ERROR(srv, "%s", "Error while loading option default values");
server_stop(srv);
return;
}
plugins_prepare_callbacks(srv);

Loading…
Cancel
Save