summaryrefslogtreecommitdiff
path: root/main/config.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-02-19 19:09:07 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-02-19 19:09:07 +0000
commit75067daac7b3afa750cd974c22371d0690ee0f0b (patch)
tree0c24521f03d1de0903af639bd46de7183b74558e /main/config.c
parent61a4a98ed92d0a658e19226bee5e2f11435cb965 (diff)
config: Add file size and nanosecond resolution fields to the cached modified config file information.
Repeatedly modifying config files and reloading too fast sometimes fails to reload the configuration because the cached modification timestamp has one second resolution. * Added file size and nanosecond resolution fields to the cached config file modification timestamp information. Now if the file size changes or the file system supports nanosecond resolution the modified file has a better chance of being detected for reload. * Added a missing unlock in an off-nominal code path. (closes issue AST-1303) Review: https://reviewboard.asterisk.org/r/3235/ ........ Merged revisions 408387 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 408388 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 408389 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@408390 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/config.c')
-rw-r--r--main/config.c85
1 files changed, 76 insertions, 9 deletions
diff --git a/main/config.c b/main/config.c
index 446bac2df..a45f57311 100644
--- a/main/config.c
+++ b/main/config.c
@@ -89,7 +89,12 @@ struct cache_file_mtime {
AST_LIST_ENTRY(cache_file_mtime) list;
AST_LIST_HEAD_NOLOCK(includes, cache_file_include) includes;
unsigned int has_exec:1;
- time_t mtime;
+ /*! stat() file size */
+ unsigned long stat_size;
+ /*! stat() file modtime nanoseconds */
+ unsigned long stat_mtime_nsec;
+ /*! stat() file modtime seconds since epoc */
+ time_t stat_mtime;
/*! String stuffed in filename[] after the filename string. */
const char *who_asked;
@@ -1214,6 +1219,61 @@ enum config_cache_attribute_enum {
ATTRIBUTE_EXEC = 1,
};
+/*!
+ * \internal
+ * \brief Clear the stat() data in the cached file modtime struct.
+ *
+ * \param cfmtime Cached file modtime.
+ *
+ * \return Nothing
+ */
+static void cfmstat_clear(struct cache_file_mtime *cfmtime)
+{
+ cfmtime->stat_size = 0;
+ cfmtime->stat_mtime_nsec = 0;
+ cfmtime->stat_mtime = 0;
+}
+
+/*!
+ * \internal
+ * \brief Save the stat() data to the cached file modtime struct.
+ *
+ * \param cfmtime Cached file modtime.
+ * \param statbuf Buffer filled in by stat().
+ *
+ * \return Nothing
+ */
+static void cfmstat_save(struct cache_file_mtime *cfmtime, struct stat *statbuf)
+{
+ cfmtime->stat_size = statbuf->st_size;
+#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) || (defined(_POSIX_C_SOURCE) && 200809L <= _POSIX_C_SOURCE) || (defined(_XOPEN_SOURCE) && 700 <= _XOPEN_SOURCE)
+ cfmtime->stat_mtime_nsec = statbuf->st_mtim.tv_nsec;
+#else
+ cfmtime->stat_mtime_nsec = statbuf->st_mtimensec;
+#endif
+ cfmtime->stat_mtime = statbuf->st_mtime;
+}
+
+/*!
+ * \internal
+ * \brief Compare the stat() data with the cached file modtime struct.
+ *
+ * \param cfmtime Cached file modtime.
+ * \param statbuf Buffer filled in by stat().
+ *
+ * \retval non-zero if different.
+ */
+static int cfmstat_cmp(struct cache_file_mtime *cfmtime, struct stat *statbuf)
+{
+ struct cache_file_mtime cfm_buf;
+
+ cfmstat_save(&cfm_buf, statbuf);
+
+ return cfmtime->stat_size != cfm_buf.stat_size
+ || cfmtime->stat_mtime != cfm_buf.stat_mtime
+ || cfmtime->stat_mtime_nsec != cfm_buf.stat_mtime_nsec;
+}
+
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;
@@ -1236,10 +1296,11 @@ static void config_cache_attribute(const char *configfile, enum config_cache_att
AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
}
- if (!stat(configfile, &statbuf))
- cfmtime->mtime = 0;
- else
- cfmtime->mtime = statbuf.st_mtime;
+ if (!stat(configfile, &statbuf)) {
+ cfmstat_clear(cfmtime);
+ } else {
+ cfmstat_save(cfmtime, &statbuf);
+ }
switch (attrtype) {
case ATTRIBUTE_INCLUDE:
@@ -1621,14 +1682,19 @@ static struct ast_config *config_text_file_load(const char *database, const char
}
if (!cfmtime) {
cfmtime = cfmtime_new(fn, who_asked);
- if (!cfmtime)
+ if (!cfmtime) {
+ AST_LIST_UNLOCK(&cfmtime_head);
continue;
+ }
/* Note that the file mtime is initialized to 0, i.e. 1970 */
AST_LIST_INSERT_SORTALPHA(&cfmtime_head, cfmtime, list, filename);
}
}
- if (cfmtime && (!cfmtime->has_exec) && (cfmtime->mtime == statbuf.st_mtime) && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) {
+ if (cfmtime
+ && !cfmtime->has_exec
+ && !cfmstat_cmp(cfmtime, &statbuf)
+ && ast_test_flag(&flags, CONFIG_FLAG_FILEUNCHANGED)) {
/* File is unchanged, what about the (cached) includes (if any)? */
int unchanged = 1;
AST_LIST_TRAVERSE(&cfmtime->includes, cfinclude, list) {
@@ -1685,8 +1751,9 @@ static struct ast_config *config_text_file_load(const char *database, const char
return NULL;
}
- if (cfmtime)
- cfmtime->mtime = statbuf.st_mtime;
+ if (cfmtime) {
+ cfmstat_save(cfmtime, &statbuf);
+ }
if (!(f = fopen(fn, "r"))) {
ast_debug(1, "No file to parse: %s\n", fn);