Index: load_cache/load_cache.c =================================================================== --- load_cache/load_cache.c (revision 759) +++ load_cache/load_cache.c (revision 760) @@ -2,8 +2,15 @@ #include #include #include + +/* These are required for stat() and are C89. */ +#include +#include + #include "load_cache.h" +static void ldch_free_file_low(ldch_ctx_t *ctx, ldch_file_t *file); + char *ldch_strdup(const char *s) { int l = strlen(s); @@ -11,6 +18,15 @@ return memcpy(o, s, l+1); } +double ldch_file_mtime(const char *path) +{ + struct stat st; + if (stat(path, &st) != 0) + return -1; + return st.st_mtime; +} + + void ldch_init(ldch_ctx_t *ctx) { memset(ctx, 0, sizeof(ldch_ctx_t)); @@ -65,17 +81,27 @@ ldch_file_t *file = htsp_get(&ctx->files, filename); void **d; ldch_data_t *data; + double fmd = ldch_file_mtime(filename); + if (fmd < 0) + return NULL; + /* get low level */ if (file == NULL) { - file = low->parse(low, low_call_ctx, filename); + file = low->parse_alloc(low, low_call_ctx, filename); if (file == NULL) return NULL; - + if (low->parse(low, low_call_ctx, file, filename) != 0) + ldch_unload(ctx, file); + file->last_low_parsed = fmd; } else { if (low->uid != file->low_parser->uid) return NULL; /* can't parse the same file twice, with different low level */ + if (fmd > file->last_low_parsed) { /* changed on disk */ + ldch_free_file_low(ctx, file); + low->parse(low, low_call_ctx, file, filename); + } } /* get high level parsing donw */ @@ -120,7 +146,7 @@ free(data); } -static void ldch_free_file(ldch_ctx_t *ctx, ldch_file_t *file) +static void ldch_free_file_low(ldch_ctx_t *ctx, ldch_file_t *file) { long n; @@ -131,7 +157,11 @@ if (file->low_parser->free_payload != NULL) file->low_parser->free_payload(file); +} +static void ldch_free_file(ldch_ctx_t *ctx, ldch_file_t *file) +{ + ldch_free_file_low(ctx, file); free(file->name); free(file); } Index: load_cache/load_cache.h =================================================================== --- load_cache/load_cache.h (revision 759) +++ load_cache/load_cache.h (revision 760) @@ -11,8 +11,9 @@ struct ldch_low_parser_s { char *name; ldch_uid_t uid; - ldch_file_t *(*parse)(ldch_low_parser_t *parser, void *call_ctx, const char *fn); - void (*free_payload)(ldch_file_t *file); + ldch_file_t *(*parse_alloc)(ldch_low_parser_t *parser, void *call_ctx, const char *fn); /* called when the file is first loaded; should allocate (ldch_file_t *) */ + int (*parse)(ldch_low_parser_t *parser, void *call_ctx, ldch_file_t *file, const char *fn); /* called after parse_alloc() on initial load or after free_payload() on reload */ + void (*free_payload)(ldch_file_t *file); /* should free the in-memory document/parse-tree; a call to parse() may follow when reloading */ void (*unreg)(ldch_ctx_t *ctx, ldch_low_parser_t *low); void *used_data; }; @@ -38,6 +39,7 @@ vtp0_t data; /* -> (ldch_data_t *), indexed by high_parser uid */ void *user_data; ldch_low_parser_t *low_parser; + double last_low_parsed; /* time stamp the file was last low-level parsed */ size_t low_payload_size; char low_payload[1]; /* real size: low_payload_size (caches low level parsed data) */ };