An offhand comment from Russell made me realize that the configuration file

caching would not work properly for users.conf and any other file read from
more than one place.  I needed to add the filename which requested the config
file to get it to work properly.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@107791 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.6.1
Tilghman Lesher 17 years ago
parent c89a4be6e7
commit d02f74ebfe

@ -64,7 +64,7 @@ struct ast_variable {
char stuff[0]; char stuff[0];
}; };
typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file); typedef struct ast_config *config_load_func(const char *database, const char *table, const char *configfile, struct ast_config *config, struct ast_flags flags, const char *suggested_include_file, const char *who_asked);
typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap); typedef struct ast_variable *realtime_var_get(const char *database, const char *table, va_list ap);
typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap); typedef struct ast_config *realtime_multi_get(const char *database, const char *table, va_list ap);
typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap); typedef int realtime_update(const char *database, const char *table, const char *keyfield, const char *entity, va_list ap);
@ -86,6 +86,7 @@ struct ast_config_engine {
/*! \brief Load a config file /*! \brief Load a config file
* \param filename path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR * \param filename path of file to open. If no preceding '/' character, path is considered relative to AST_CONFIG_DIR
* Create a config structure from a given configuration file. * Create a config structure from a given configuration file.
* \param who_asked The module which is making this request.
* \param flags Optional flags: * \param flags Optional flags:
* CONFIG_FLAG_WITHCOMMENTS - load the file with comments intact; * CONFIG_FLAG_WITHCOMMENTS - load the file with comments intact;
* CONFIG_FLAG_FILEUNCHANGED - check the file mtime and return CONFIG_STATUS_FILEUNCHANGED if the mtime is the same; or * CONFIG_FLAG_FILEUNCHANGED - check the file mtime and return CONFIG_STATUS_FILEUNCHANGED if the mtime is the same; or
@ -94,7 +95,9 @@ struct ast_config_engine {
* \retval an ast_config data structure on success * \retval an ast_config data structure on success
* \retval NULL on error * \retval NULL on error
*/ */
struct ast_config *ast_config_load(const char *filename, struct ast_flags flags); struct ast_config *ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags);
#define ast_config_load(filename, flags) ast_config_load2(filename, __FILE__, flags)
/*! \brief Destroys a config /*! \brief Destroys a config
* \param config pointer to config data structure * \param config pointer to config data structure
@ -282,7 +285,7 @@ int ast_variable_update(struct ast_category *category, const char *variable,
int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator); int config_text_file_save(const char *filename, const struct ast_config *cfg, const char *generator);
struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file); struct ast_config *ast_config_internal_load(const char *configfile, struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl_file, const char *who_asked);
/*! \brief Support code to parse config file arguments /*! \brief Support code to parse config file arguments
* *

@ -92,6 +92,7 @@ struct cache_file_mtime {
AST_LIST_HEAD(includes, cache_file_include) includes; AST_LIST_HEAD(includes, cache_file_include) includes;
unsigned int has_exec:1; unsigned int has_exec:1;
time_t mtime; time_t mtime;
char *who_asked;
char filename[0]; char filename[0];
}; };
@ -854,7 +855,7 @@ enum config_cache_attribute_enum {
ATTRIBUTE_EXEC = 1, ATTRIBUTE_EXEC = 1,
}; };
static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename) static void config_cache_attribute(const char *configfile, enum config_cache_attribute_enum attrtype, const char *filename, const char *who_asked)
{ {
struct cache_file_mtime *cfmtime; struct cache_file_mtime *cfmtime;
struct cache_file_include *cfinclude; struct cache_file_include *cfinclude;
@ -867,13 +868,15 @@ static void config_cache_attribute(const char *configfile, enum config_cache_att
break; break;
} }
if (!cfmtime) { if (!cfmtime) {
cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(configfile) + 1); cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(configfile) + 1 + strlen(who_asked) + 1);
if (!cfmtime) { if (!cfmtime) {
AST_LIST_UNLOCK(&cfmtime_head); AST_LIST_UNLOCK(&cfmtime_head);
return; return;
} }
AST_LIST_HEAD_INIT(&cfmtime->includes); AST_LIST_HEAD_INIT(&cfmtime->includes);
strcpy(cfmtime->filename, configfile); strcpy(cfmtime->filename, configfile);
cfmtime->who_asked = cfmtime->filename + strlen(configfile) + 1;
strcpy(cfmtime->who_asked, who_asked);
/* Note that the file mtime is initialized to 0, i.e. 1970 */ /* Note that the file mtime is initialized to 0, i.e. 1970 */
AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list); AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list);
} }
@ -918,7 +921,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
struct ast_str *comment_buffer, struct ast_str *comment_buffer,
struct ast_str *lline_buffer, struct ast_str *lline_buffer,
const char *suggested_include_file, const char *suggested_include_file,
struct ast_category **last_cat, struct ast_variable **last_var) struct ast_category **last_cat, struct ast_variable **last_var, const char *who_asked)
{ {
char *c; char *c;
char *cur = buf; char *cur = buf;
@ -1054,21 +1057,21 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
We create a tmp file, then we #include it, then we delete it. */ We create a tmp file, then we #include it, then we delete it. */
if (!do_include) { if (!do_include) {
if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL); config_cache_attribute(configfile, ATTRIBUTE_EXEC, NULL, who_asked);
snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self()); snprintf(exec_file, sizeof(exec_file), "/var/tmp/exec.%d.%ld", (int)time(NULL), (long)pthread_self());
snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file); snprintf(cmd, sizeof(cmd), "%s > %s 2>&1", cur, exec_file);
ast_safe_system(cmd); ast_safe_system(cmd);
cur = exec_file; cur = exec_file;
} else { } else {
if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE)) if (!ast_test_flag(&flags, CONFIG_FLAG_NOCACHE))
config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur); config_cache_attribute(configfile, ATTRIBUTE_INCLUDE, cur, who_asked);
exec_file[0] = '\0'; exec_file[0] = '\0';
} }
/* A #include */ /* A #include */
/* record this inclusion */ /* record this inclusion */
inclu = ast_include_new(cfg, configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name)); inclu = ast_include_new(cfg, configfile, cur, !do_include, cur2, lineno, real_inclusion_name, sizeof(real_inclusion_name));
do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name) ? 1 : 0; do_include = ast_config_internal_load(cur, cfg, flags, real_inclusion_name, who_asked) ? 1 : 0;
if (!ast_strlen_zero(exec_file)) if (!ast_strlen_zero(exec_file))
unlink(exec_file); unlink(exec_file);
if (!do_include) { if (!do_include) {
@ -1121,7 +1124,7 @@ static int process_text_line(struct ast_config *cfg, struct ast_category **cat,
return 0; return 0;
} }
static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file) static struct ast_config *config_text_file_load(const char *database, const char *table, const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
{ {
char fn[256]; char fn[256];
char buf[8192]; char buf[8192];
@ -1196,15 +1199,17 @@ static struct ast_config *config_text_file_load(const char *database, const char
/* Find our cached entry for this configuration file */ /* Find our cached entry for this configuration file */
AST_LIST_LOCK(&cfmtime_head); AST_LIST_LOCK(&cfmtime_head);
AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) { AST_LIST_TRAVERSE(&cfmtime_head, cfmtime, list) {
if (!strcmp(cfmtime->filename, fn)) if (!strcmp(cfmtime->filename, fn) && !strcmp(cfmtime->who_asked, who_asked))
break; break;
} }
if (!cfmtime) { if (!cfmtime) {
cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(fn) + 1); cfmtime = ast_calloc(1, sizeof(*cfmtime) + strlen(fn) + 1 + strlen(who_asked) + 1);
if (!cfmtime) if (!cfmtime)
continue; continue;
AST_LIST_HEAD_INIT(&cfmtime->includes); AST_LIST_HEAD_INIT(&cfmtime->includes);
strcpy(cfmtime->filename, fn); strcpy(cfmtime->filename, fn);
cfmtime->who_asked = cfmtime->filename + strlen(fn) + 1;
strcpy(cfmtime->who_asked, who_asked);
/* Note that the file mtime is initialized to 0, i.e. 1970 */ /* Note that the file mtime is initialized to 0, i.e. 1970 */
AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list); AST_LIST_INSERT_TAIL(&cfmtime_head, cfmtime, list);
} }
@ -1232,7 +1237,8 @@ static struct ast_config *config_text_file_load(const char *database, const char
#else #else
ast_copy_string(fn2, cfinclude->include); ast_copy_string(fn2, cfinclude->include);
#endif #endif
if (config_text_file_load(NULL, NULL, fn2, NULL, flags, "") == NULL) { /* that last field needs to be looked at in this case... TODO */ if (config_text_file_load(NULL, NULL, fn2, NULL, flags, "", who_asked) == NULL) {
/* that second-to-last field needs to be looked at in this case... TODO */
unchanged = 0; unchanged = 0;
/* One change is enough to short-circuit and reload the whole shebang */ /* One change is enough to short-circuit and reload the whole shebang */
break; break;
@ -1346,7 +1352,7 @@ static struct ast_config *config_text_file_load(const char *database, const char
if (process_buf) { if (process_buf) {
char *buf = ast_strip(process_buf); char *buf = ast_strip(process_buf);
if (!ast_strlen_zero(buf)) { if (!ast_strlen_zero(buf)) {
if (process_text_line(cfg, &cat, buf, lineno, fn, flags, comment_buffer, lline_buffer, suggested_include_file, &last_cat, &last_var)) { if (process_text_line(cfg, &cat, buf, lineno, fn, flags, comment_buffer, lline_buffer, suggested_include_file, &last_cat, &last_var, who_asked)) {
cfg = NULL; cfg = NULL;
break; break;
} }
@ -1815,7 +1821,7 @@ int read_config_maps(void)
configtmp = ast_config_new(); configtmp = ast_config_new();
configtmp->max_include_level = 1; configtmp->max_include_level = 1;
config = ast_config_internal_load(extconfig_conf, configtmp, flags, ""); config = ast_config_internal_load(extconfig_conf, configtmp, flags, "", "config.c");
if (!config) { if (!config) {
ast_config_destroy(configtmp); ast_config_destroy(configtmp);
return 0; return 0;
@ -1956,7 +1962,7 @@ static struct ast_config_engine text_file_engine = {
.load_func = config_text_file_load, .load_func = config_text_file_load,
}; };
struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file) struct ast_config *ast_config_internal_load(const char *filename, struct ast_config *cfg, struct ast_flags flags, const char *suggested_include_file, const char *who_asked)
{ {
char db[256]; char db[256];
char table[256]; char table[256];
@ -1986,7 +1992,7 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con
} }
} }
result = loader->load_func(db, table, filename, cfg, flags, suggested_include_file); result = loader->load_func(db, table, filename, cfg, flags, suggested_include_file, who_asked);
if (result && result != CONFIG_STATUS_FILEUNCHANGED) if (result && result != CONFIG_STATUS_FILEUNCHANGED)
result->include_level--; result->include_level--;
@ -1996,7 +2002,7 @@ struct ast_config *ast_config_internal_load(const char *filename, struct ast_con
return result; return result;
} }
struct ast_config *ast_config_load(const char *filename, struct ast_flags flags) struct ast_config *ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
{ {
struct ast_config *cfg; struct ast_config *cfg;
struct ast_config *result; struct ast_config *result;
@ -2005,7 +2011,7 @@ struct ast_config *ast_config_load(const char *filename, struct ast_flags flags)
if (!cfg) if (!cfg)
return NULL; return NULL;
result = ast_config_internal_load(filename, cfg, flags, ""); result = ast_config_internal_load(filename, cfg, flags, "", who_asked);
if (!result || result == CONFIG_STATUS_FILEUNCHANGED) if (!result || result == CONFIG_STATUS_FILEUNCHANGED)
ast_config_destroy(cfg); ast_config_destroy(cfg);

@ -407,7 +407,7 @@ static int destroy_curl(const char *url, const char *unused, const char *keyfiel
} }
static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl) static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
{ {
struct ast_str *query; struct ast_str *query;
char buf1[200]; char buf1[200];
@ -463,7 +463,7 @@ static struct ast_config *config_curl(const char *url, const char *unused, const
} }
if (!strcmp(var_name, "#include")) { if (!strcmp(var_name, "#include")) {
if (!ast_config_internal_load(var_val, cfg, loader_flags, "")) if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
return NULL; return NULL;
} }

@ -1006,7 +1006,7 @@ static int compare_categories(const void *a, const void *b)
* called on a reload * called on a reload
*/ */
static struct ast_config *config_ldap(const char *basedn, const char *table_name, static struct ast_config *config_ldap(const char *basedn, const char *table_name,
const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *sugg_incl) const char *file, struct ast_config *cfg, struct ast_flags config_flags, const char *sugg_incl, const char *who_asked)
{ {
unsigned int vars_count = 0; unsigned int vars_count = 0;
struct ast_variable **vars; struct ast_variable **vars;
@ -1088,7 +1088,7 @@ static struct ast_config *config_ldap(const char *basedn, const char *table_name
for (i = 0; i < vars_count; i++) { for (i = 0; i < vars_count; i++) {
if (!strcmp(categories[i].variable_name, "#include")) { if (!strcmp(categories[i].variable_name, "#include")) {
struct ast_flags config_flags = { 0 }; struct ast_flags config_flags = { 0 };
if (!ast_config_internal_load(categories[i].variable_value, cfg, config_flags, "")) if (!ast_config_internal_load(categories[i].variable_value, cfg, config_flags, "", who_asked))
break; break;
continue; continue;
} }

@ -625,7 +625,7 @@ static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
return sth; return sth;
} }
static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl) static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
{ {
struct ast_variable *new_v; struct ast_variable *new_v;
struct ast_category *cur_cat; struct ast_category *cur_cat;
@ -682,7 +682,7 @@ static struct ast_config *config_odbc(const char *database, const char *table, c
while ((res = SQLFetch(stmt)) != SQL_NO_DATA) { while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
if (!strcmp (q.var_name, "#include")) { if (!strcmp (q.var_name, "#include")) {
if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "")) { if (!ast_config_internal_load(q.var_val, cfg, loader_flags, "", who_asked)) {
SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLFreeHandle(SQL_HANDLE_STMT, stmt);
ast_odbc_release_obj(obj); ast_odbc_release_obj(obj);
return NULL; return NULL;

@ -658,7 +658,7 @@ static int destroy_pgsql(const char *database, const char *table, const char *ke
static struct ast_config *config_pgsql(const char *database, const char *table, static struct ast_config *config_pgsql(const char *database, const char *table,
const char *file, struct ast_config *cfg, const char *file, struct ast_config *cfg,
struct ast_flags flags, const char *suggested_incl) struct ast_flags flags, const char *suggested_incl, const char *who_asked)
{ {
PGresult *result = NULL; PGresult *result = NULL;
long num_rows; long num_rows;
@ -723,7 +723,7 @@ static struct ast_config *config_pgsql(const char *database, const char *table,
char *field_var_val = PQgetvalue(result, rowIndex, 2); char *field_var_val = PQgetvalue(result, rowIndex, 2);
char *field_cat_metric = PQgetvalue(result, rowIndex, 3); char *field_cat_metric = PQgetvalue(result, rowIndex, 3);
if (!strcmp(field_var_name, "#include")) { if (!strcmp(field_var_name, "#include")) {
if (!ast_config_internal_load(field_var_val, cfg, flags, "")) { if (!ast_config_internal_load(field_var_val, cfg, flags, "", who_asked)) {
PQclear(result); PQclear(result);
ast_mutex_unlock(&pgsql_lock); ast_mutex_unlock(&pgsql_lock);
return NULL; return NULL;

@ -178,6 +178,7 @@ struct cfg_entry_args {
struct ast_category *cat; struct ast_category *cat;
char *cat_name; char *cat_name;
struct ast_flags flags; struct ast_flags flags;
const char *who_asked;
}; };
/*! /*!
@ -277,7 +278,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames);
* \see add_cfg_entry() * \see add_cfg_entry()
*/ */
static struct ast_config * config_handler(const char *database, const char *table, const char *file, static struct ast_config * config_handler(const char *database, const char *table, const char *file,
struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl); struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked);
/*! /*!
* \brief Helper function to parse a va_list object into 2 dynamic arrays of * \brief Helper function to parse a va_list object into 2 dynamic arrays of
@ -710,7 +711,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
char *val; char *val;
val = argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL]; val = argv[RES_CONFIG_SQLITE_CONFIG_VAR_VAL];
cfg = ast_config_internal_load(val, args->cfg, args->flags, ""); cfg = ast_config_internal_load(val, args->cfg, args->flags, "", args->who_asked);
if (!cfg) { if (!cfg) {
ast_log(LOG_WARNING, "Unable to include %s\n", val); ast_log(LOG_WARNING, "Unable to include %s\n", val);
@ -753,7 +754,7 @@ static int add_cfg_entry(void *arg, int argc, char **argv, char **columnNames)
} }
static struct ast_config *config_handler(const char *database, const char *table, const char *file, static struct ast_config *config_handler(const char *database, const char *table, const char *file,
struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl) struct ast_config *cfg, struct ast_flags flags, const char *suggested_incl, const char *who_asked)
{ {
struct cfg_entry_args args; struct cfg_entry_args args;
char *query, *errormsg; char *query, *errormsg;
@ -779,6 +780,7 @@ static struct ast_config *config_handler(const char *database, const char *table
args.cat = NULL; args.cat = NULL;
args.cat_name = NULL; args.cat_name = NULL;
args.flags = flags; args.flags = flags;
args.who_asked = who_asked;
ast_mutex_lock(&mutex); ast_mutex_lock(&mutex);

Loading…
Cancel
Save