[core] rewrite config parser

* no more hash values - only lists and list of key-value pairs
 * "master" config:
   the config loaded on startup can use all features,
   configs loaded later (vhost on demand from sql...) can't use
   include* and cannot modify global vars.
 * scoped variables
   - add a global var store in the server struct
   - global vars can be set with "global foo = bar"
   - if a variable already exists in a scope it will be modified on a
	 write, otherwise a new local variable is created
   - global vars won't be modified if not in "master" mode
   - vars can be made explicitly local with "local foo = bar"; create a
	 local copy with "local foo = foo"
   - globals vars are available in live config loads for reading
   - each file and action block {...} creates a new scope; if/else branches do
	 NOT create a new scope
 * to append a value to a list use "l + [v]" (not "l + v" anymore);
   lists are concatenated with "+"
 * [...] always marks a list
 * (...) is a list if it contains a "," or "=>", otherwise it justs
   groups an expression
 * a list can either contain key-value pairs or other values. mixing is
   not allowed
personal/stbuehler/wip
Stefan Bühler 10 years ago
parent a1fbaab86b
commit e76ebe2021

@ -85,11 +85,15 @@ LI_API liHandlerResult li_action_execute(liVRequest *vr);
LI_API void li_action_release(liServer *srv, liAction *a);
LI_API void li_action_acquire(liAction *a);
/* create new action */
LI_API liAction *li_action_new_setting(liOptionSet setting);
LI_API liAction *li_action_new_settingptr(liOptionPtrSet setting);
LI_API liAction *li_action_new_function(liActionFuncCB func, liActionCleanupCB fcleanup, liActionFreeCB ffree, gpointer param);
LI_API liAction *li_action_new_list(void);
LI_API liAction *li_action_new_condition(liCondition *cond, liAction *target, liAction *target_else);
LI_API liAction *li_action_new_balancer(liBackendSelectCB bselect, liBackendFallbackCB bfallback, liBackendFinishedCB bfinished, liBalancerFreeCB bfree, gpointer param, gboolean provide_backlog);
LI_API liAction* li_action_new(void);
LI_API liAction* li_action_new_setting(liOptionSet setting);
LI_API liAction* li_action_new_settingptr(liOptionPtrSet setting);
LI_API liAction* li_action_new_function(liActionFuncCB func, liActionCleanupCB fcleanup, liActionFreeCB ffree, gpointer param);
LI_API liAction* li_action_new_list(void);
LI_API liAction* li_action_new_condition(liCondition *cond, liAction *target, liAction *target_else);
LI_API liAction* li_action_new_balancer(liBackendSelectCB bselect, liBackendFallbackCB bfallback, liBackendFinishedCB bfinished, liBalancerFreeCB bfree, gpointer param, gboolean provide_backlog);
/* assert(list->refcount == 1)! converts list to a list in place if necessary */
LI_API void li_action_append_inplace(liAction *list, liAction *element);
#endif

@ -3,56 +3,12 @@
#include <lighttpd/base.h>
typedef struct liConfigParserContext liConfigParserContext;
typedef enum {
LI_CFG_PARSER_CAST_NONE,
LI_CFG_PARSER_CAST_INT,
LI_CFG_PARSER_CAST_STR
} liCastType;
struct liConfigParserContext {
/* ragel vars */
int cs;
int *stack;
int top;
int stacksize; /* not really used by ragel but need to remember it */
char *p, *pe, *eof;
gchar *mark;
gboolean in_setup_block;
gboolean action_call_with_param;
gboolean condition_with_key;
gboolean condition_nonbool;
gboolean condition_negated;
liCompOperator op;
liCastType cast;
GHashTable *uservars; /* foo = ...; */
GQueue *action_list_stack; /* first entry is current action list */
GQueue *value_stack; /* stack of liValue* */
GQueue *value_op_stack; /* stack of gchar* */
GQueue *condition_stack; /* stack of condition* */
/* information about currenty parsed file */
gchar *filename;
gchar *ptr; /* pointer to the data */
gsize len;
gsize line; /* holds current line */
};
#define LI_CONFIG_ERROR li_config_error_quark()
LI_API GQuark li_config_error_quark(void);
LI_API gboolean li_config_parse(liServer *srv, const gchar *config_path);
/* returns a new config parser stack with the first context in it */
LI_API GList* li_config_parser_init(liServer *srv);
LI_API void li_config_parser_finish(liServer *srv, GList *ctx_stack, gboolean free_all);
/* loads a file into memory and parses it */
LI_API gboolean li_config_parser_file(liServer *srv, GList *ctx_stack, const gchar *path);
/* parse more config snippets at runtime. does not support includes and modifying global vars */
LI_API liAction* li_config_parse_live(liWorker *wrk, const gchar *sourcename, const char *source, gsize sourcelen, GError **error);
#endif

@ -82,6 +82,8 @@ struct liServer {
GHashTable *plugins; /**< const gchar* => (liPlugin*) */
liPlugin *core_plugin;
GHashTable *config_global_vars; /** for later reuse, (GString*) => (liValue*) */
/* registered by plugins */
GHashTable *options; /**< const gchar* => (liServerOption*) */
GHashTable *optionptrs; /**< const gchar* => (liServerOptionPtr*) */

@ -33,6 +33,7 @@ typedef struct liActionFunc liActionFunc;
typedef struct liBalancerFunc liBalancerFunc;
typedef enum {
LI_ACTION_TNOTHING,
LI_ACTION_TSETTING,
LI_ACTION_TSETTINGPTR,
LI_ACTION_TFUNCTION,

@ -18,6 +18,8 @@ void li_action_release(liServer *srv, liAction *a) {
assert(g_atomic_int_get(&a->refcount) > 0);
if (g_atomic_int_dec_and_test(&a->refcount)) {
switch (a->type) {
case LI_ACTION_TNOTHING:
break;
case LI_ACTION_TSETTING:
break;
case LI_ACTION_TSETTINGPTR:
@ -54,6 +56,15 @@ void li_action_acquire(liAction *a) {
g_atomic_int_inc(&a->refcount);
}
liAction* li_action_new(void) {
liAction *a = g_slice_new(liAction);
a->refcount = 1;
a->type = LI_ACTION_TNOTHING;
return a;
}
liAction *li_action_new_setting(liOptionSet setting) {
liAction *a = g_slice_new(liAction);
@ -128,12 +139,35 @@ liAction *li_action_new_balancer(liBackendSelectCB bselect, liBackendFallbackCB
return a;
}
void li_action_append_inplace(liAction *list, liAction *element) {
assert(NULL != list && NULL != element);
assert(1 == g_atomic_int_get(&list->refcount));
if (LI_ACTION_TLIST != list->type) {
liAction *wrapped = NULL;
if (LI_ACTION_TNOTHING != list->type) {
wrapped = li_action_new();
*wrapped = *list;
}
memset(list, 0, sizeof(*list));
list->refcount = 1;
list->type = LI_ACTION_TLIST;
list->data.list = g_array_new(FALSE, TRUE, sizeof(liAction *));
if (NULL != wrapped) g_array_append_val(list->data.list, wrapped);
}
if (LI_ACTION_TNOTHING != element->type) {
li_action_acquire(element);
g_array_append_val(list->data.list, element);
}
}
static void action_stack_element_release(liServer *srv, liVRequest *vr, action_stack_element *ase) {
liAction *a = ase->act;
if (!ase || !a) return;
switch (a->type) {
case LI_ACTION_TNOTHING:
case LI_ACTION_TSETTING:
case LI_ACTION_TSETTINGPTR:
break;
@ -313,6 +347,9 @@ liHandlerResult li_action_execute(liVRequest *vr) {
ase_ndx = as->stack->len - 1; /* sometimes the stack gets modified - reread "ase" after that */
switch (a->type) {
case LI_ACTION_TNOTHING:
action_stack_pop(srv, vr, as);
break;
case LI_ACTION_TSETTING:
vr->options[a->data.setting.ndx] = a->data.setting.value;
action_stack_pop(srv, vr, as);

@ -5,7 +5,7 @@
#include <fcntl.h>
GQuark li_chunk_error_quark(void) {
return g_quark_from_string("g-chunk-error-quark");
return g_quark_from_string("li-chunk-error-quark");
}
/******************

@ -17,8 +17,6 @@ static liValue* lua_params_to_value(liServer *srv, lua_State *L) {
case 0:
case 1: /* first parameter is the table the __call method is for */
return NULL;
case 2:
return li_value_from_lua(srv, L);
default:
val = li_value_new_list();
g_array_set_size(val->data.list, lua_gettop(L) - 1);

File diff suppressed because it is too large Load Diff

@ -93,6 +93,7 @@ liServer* li_server_new(const gchar *module_dir, gboolean module_resident) {
srv->prepare_callbacks = g_array_new(FALSE, TRUE, sizeof(liServerPrepareCallbackData));
srv->mainaction = NULL;
srv->config_global_vars = li_value_new_hashtable();
srv->action_mutex = g_mutex_new();
@ -166,6 +167,9 @@ void li_server_free(liServer* srv) {
}
li_action_release(srv, srv->mainaction);
srv->mainaction = NULL;
g_hash_table_destroy(srv->config_global_vars);
srv->config_global_vars = NULL;
li_event_clear(&srv->state_ready_watcher);
g_mutex_free(srv->statelock);

Loading…
Cancel
Save