From 81649ac54979cfd96571d7295b12fcccf58b0fd9 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Tue, 31 Oct 2006 00:32:41 +0100 Subject: [PATCH] rnd-20061031-1-src * added caching of custom artwork information for faster startup times --- ChangeLog | 3 + src/conftime.h | 2 +- src/libgame/setup.c | 284 +++++++++++++++++++++++++++++++------------- 3 files changed, 207 insertions(+), 82 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89dffbee..2af34128 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2006-10-30 + * added caching of custom artwork information for faster startup times + 2006-10-29 * fixed graphical bug when using fewer menu entries on level selection screen than usual (with "menu.list_size.LEVELS" directive) diff --git a/src/conftime.h b/src/conftime.h index 51a37dfa..7bf99c14 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "[2006-10-30 19:51]" +#define COMPILE_DATE_STRING "[2006-10-31 00:28]" diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 6d187a02..9a65d0f1 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -92,7 +92,8 @@ static int compareTreeInfoEntries(const void *, const void *); static int token_value_position = TOKEN_VALUE_POSITION_DEFAULT; static int token_comment_position = TOKEN_COMMENT_POSITION_DEFAULT; -static SetupFileHash *artworkinfo_hash = NULL; +static SetupFileHash *artworkinfo_hash_old = NULL; +static SetupFileHash *artworkinfo_hash_new = NULL; /* ------------------------------------------------------------------------- */ @@ -1654,7 +1655,11 @@ static void *loadSetupFileData(char *filename, boolean use_hash) /* find end of token to determine start of value */ for (line_ptr = token; *line_ptr; line_ptr++) { +#if 1 + if (*line_ptr == ':' || *line_ptr == '=') +#else if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == ':') +#endif { *line_ptr = '\0'; /* terminate token string */ value = line_ptr + 1; /* set beginning of value */ @@ -1663,6 +1668,11 @@ static void *loadSetupFileData(char *filename, boolean use_hash) } } + /* cut trailing whitespaces from token */ + for (line_ptr = &token[strlen(token)]; line_ptr >= token; line_ptr--) + if ((*line_ptr == ' ' || *line_ptr == '\t') && *(line_ptr + 1) == '\0') + *line_ptr = '\0'; + /* cut leading whitespaces from value */ for (; *value; value++) if (*value != ' ' && *value != '\t') @@ -1962,6 +1972,9 @@ static void setTreeInfoToDefaultsFromParent(TreeInfo *ti, TreeInfo *parent) static void freeTreeInfo(TreeInfo *ti) { + if (ti == NULL) + return; + checked_free(ti->subdir); checked_free(ti->fullpath); checked_free(ti->basepath); @@ -1993,6 +2006,8 @@ static void freeTreeInfo(TreeInfo *ti) checked_free(ti->level_filename); checked_free(ti->level_filetype); } + + checked_free(ti); } void setSetupInfo(struct TokenInfo *token_info, @@ -2109,78 +2124,222 @@ static void createParentTreeInfoNode(TreeInfo *node_parent) static void LoadArtworkInfoCache() { - if (artworkinfo_hash == NULL) + if (artworkinfo_hash_old == NULL) { char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME); /* try to load artwork info hash from already existing cache file */ - artworkinfo_hash = loadSetupFileHash(filename); + artworkinfo_hash_old = loadSetupFileHash(filename); /* if no artwork info cache file was found, start with empty hash */ - if (artworkinfo_hash == NULL) - artworkinfo_hash = newSetupFileHash(); + if (artworkinfo_hash_old == NULL) + artworkinfo_hash_old = newSetupFileHash(); free(filename); } + + if (artworkinfo_hash_new == NULL) + artworkinfo_hash_new = newSetupFileHash(); } static void SaveArtworkInfoCache() { char *filename = getPath2(getSetupDir(), ARTWORKINFO_CACHE_FILENAME); - saveSetupFileHash(artworkinfo_hash, filename); + saveSetupFileHash(artworkinfo_hash_new, filename); free(filename); } -static TreeInfo *getArtworkInfoFromCache(char *identifier, int type) +static char *getCacheTokenPrefix(char *prefix1, char *prefix2) +{ + static char *prefix = NULL; + + checked_free(prefix); + + prefix = getStringCat2WithSeparator(prefix1, prefix2, "."); + + return prefix; +} + +/* (identical to above function, but separate string buffer needed -- nasty) */ +static char *getCacheToken(char *prefix, char *suffix) +{ + static char *token = NULL; + + checked_free(token); + + token = getStringCat2WithSeparator(prefix, suffix, "."); + + return token; +} + +static char *getFileTimestamp(char *filename) +{ + struct stat file_status; + + if (stat(filename, &file_status) != 0) /* cannot stat file */ + return getStringCopy(i_to_a(0)); + + return getStringCopy(i_to_a(file_status.st_mtime)); +} + +static boolean modifiedFileTimestamp(char *filename, char *timestamp_string) { + struct stat file_status; + + if (timestamp_string == NULL) + return TRUE; + + if (stat(filename, &file_status) != 0) /* cannot stat file */ + return TRUE; + + return (file_status.st_mtime != atoi(timestamp_string)); +} + +static TreeInfo *getArtworkInfoCacheEntry(LevelDirTree *level_node, int type) +{ + char *identifier = level_node->subdir; char *type_string = ARTWORK_DIRECTORY(type); - char *token_prefix = getStringCat2WithSeparator(type_string, identifier, "."); - char *cache_entry = getHashEntry(artworkinfo_hash, token_prefix); + char *token_prefix = getCacheTokenPrefix(type_string, identifier); + char *token_main = getCacheToken(token_prefix, "CACHED"); + char *cache_entry = getHashEntry(artworkinfo_hash_old, token_main); boolean cached = (cache_entry != NULL && strEqual(cache_entry, "true")); - TreeInfo *artwork_new = NULL; + TreeInfo *artwork_info = NULL; + +#if 0 + printf("::: '%s' in cache: %d\n", token_main, cached); +#endif if (cached) { int i; +#if 0 printf("::: LOADING existing hash entry for '%s' ...\n", identifier); +#endif - artwork_new = newTreeInfo(); - setTreeInfoToDefaults(artwork_new, type); + artwork_info = newTreeInfo(); + setTreeInfoToDefaults(artwork_info, type); /* set all structure fields according to the token/value pairs */ - ldi = *artwork_new; + ldi = *artwork_info; for (i = 0; artworkinfo_tokens[i].type != -1; i++) { - char *token = getStringCat2WithSeparator(token_prefix, - artworkinfo_tokens[i].text, "."); - char *value = getHashEntry(artworkinfo_hash, token); + char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text); + char *value = getHashEntry(artworkinfo_hash_old, token); +#if 0 printf("::: - setting '%s' => '%s'\n", token, value); +#endif setSetupInfo(artworkinfo_tokens, i, value); /* check if cache entry for this item is invalid or incomplete */ if (value == NULL) { +#if 0 printf("::: - WARNING: cache entry '%s' invalid\n", token); +#endif cached = FALSE; } - - checked_free(token); } - *artwork_new = ldi; + *artwork_info = ldi; + } + if (cached) + { + char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node), + LEVELINFO_FILENAME); + char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), + ARTWORKINFO_FILENAME(type)); + + /* check if corresponding "levelinfo.conf" file has changed */ + token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO"); + cache_entry = getHashEntry(artworkinfo_hash_old, token_main); + + if (modifiedFileTimestamp(filename_levelinfo, cache_entry)) + cached = FALSE; + + /* check if corresponding ".conf" file has changed */ + token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO"); + cache_entry = getHashEntry(artworkinfo_hash_old, token_main); + + if (modifiedFileTimestamp(filename_artworkinfo, cache_entry)) + cached = FALSE; + +#if 0 if (!cached) - freeTreeInfo(artwork_new); + printf("::: '%s': INVALIDATED FROM CACHE\n", identifier); +#endif + + checked_free(filename_levelinfo); + checked_free(filename_artworkinfo); } - free(token_prefix); + if (!cached && artwork_info != NULL) + { + freeTreeInfo(artwork_info); - return artwork_new; + return NULL; + } + + return artwork_info; +} + +static void setArtworkInfoCacheEntry(TreeInfo *artwork_info, + LevelDirTree *level_node, int type) +{ + char *identifier = level_node->subdir; + char *type_string = ARTWORK_DIRECTORY(type); + char *token_prefix = getCacheTokenPrefix(type_string, identifier); + char *token_main = getCacheToken(token_prefix, "CACHED"); + boolean set_cache_timestamps = TRUE; + int i; + +#if 0 + printf("::: adding '%s' to cache!\n", token_main); +#endif + + setHashEntry(artworkinfo_hash_new, token_main, "true"); + + if (set_cache_timestamps) + { + char *filename_levelinfo = getPath2(getLevelDirFromTreeInfo(level_node), + LEVELINFO_FILENAME); + char *filename_artworkinfo = getPath2(getSetupArtworkDir(artwork_info), + ARTWORKINFO_FILENAME(type)); + char *timestamp_levelinfo = getFileTimestamp(filename_levelinfo); + char *timestamp_artworkinfo = getFileTimestamp(filename_artworkinfo); + + token_main = getCacheToken(token_prefix, "TIMESTAMP_LEVELINFO"); + setHashEntry(artworkinfo_hash_new, token_main, timestamp_levelinfo); + + token_main = getCacheToken(token_prefix, "TIMESTAMP_ARTWORKINFO"); + setHashEntry(artworkinfo_hash_new, token_main, timestamp_artworkinfo); + + checked_free(filename_levelinfo); + checked_free(filename_artworkinfo); + checked_free(timestamp_levelinfo); + checked_free(timestamp_artworkinfo); + } + + ldi = *artwork_info; + for (i = 0; artworkinfo_tokens[i].type != -1; i++) + { + char *token = getCacheToken(token_prefix, artworkinfo_tokens[i].text); + char *value = getSetupValue(artworkinfo_tokens[i].type, + artworkinfo_tokens[i].value); + if (value != NULL) + { + setHashEntry(artworkinfo_hash_new, token, value); + +#if 0 + printf("::: - setting '%s' => '%s'\n\n", token, value); +#endif + } + } } @@ -2741,6 +2900,8 @@ void LoadArtworkInfo() void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, LevelDirTree *level_node) { + int type = (*artwork_node)->type; + /* recursively check all level directories for artwork sub-directories */ while (level_node) @@ -2748,78 +2909,39 @@ void LoadArtworkInfoFromLevelInfo(ArtworkDirTree **artwork_node, /* check all tree entries for artwork, but skip parent link entries */ if (!level_node->parent_link) { - TreeInfo *topnode_last = *artwork_node; - char *path = getPath2(getLevelDirFromTreeInfo(level_node), - ARTWORK_DIRECTORY((*artwork_node)->type)); - TreeInfo *artwork_new = getArtworkInfoFromCache(level_node->subdir, - (*artwork_node)->type); - boolean cached = FALSE; + TreeInfo *artwork_new = getArtworkInfoCacheEntry(level_node, type); + boolean cached = (artwork_new != NULL); - if (artwork_new != NULL) + if (cached) { pushTreeInfo(artwork_node, artwork_new); - cached = TRUE; } else { - LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, - (*artwork_node)->type); - } + TreeInfo *topnode_last = *artwork_node; + char *path = getPath2(getLevelDirFromTreeInfo(level_node), + ARTWORK_DIRECTORY(type)); -#if 1 - if (!cached && topnode_last != *artwork_node) -#else - if (topnode_last != *artwork_node) -#endif - { - free((*artwork_node)->identifier); - free((*artwork_node)->name); - free((*artwork_node)->name_sorting); + LoadArtworkInfoFromArtworkDir(artwork_node, NULL, path, type); - (*artwork_node)->identifier = getStringCopy(level_node->subdir); - (*artwork_node)->name = getStringCopy(level_node->name); - (*artwork_node)->name_sorting = getStringCopy(level_node->name); + if (topnode_last != *artwork_node) /* check for newly added node */ + { + artwork_new = *artwork_node; - (*artwork_node)->sort_priority = level_node->sort_priority; - (*artwork_node)->color = LEVELCOLOR((*artwork_node)); + setString(&artwork_new->identifier, level_node->subdir); + setString(&artwork_new->name, level_node->name); + setString(&artwork_new->name_sorting, level_node->name_sorting); -#if 1 - { - char *identifier = level_node->subdir; - char *type_string = ARTWORK_DIRECTORY((*artwork_node)->type); - char *type_identifier = - getStringCat2WithSeparator(type_string, identifier, "."); - int i; - - printf("::: adding hash entry for set '%s' ...\n", type_identifier); - - setHashEntry(artworkinfo_hash, type_identifier, "true"); - - ldi = **artwork_node; - for (i = 0; artworkinfo_tokens[i].type != -1; i++) - { - char *token = getStringCat2WithSeparator(type_identifier, - artworkinfo_tokens[i].text, - "."); - char *value = getSetupValue(artworkinfo_tokens[i].type, - artworkinfo_tokens[i].value); - if (value != NULL) - { - setHashEntry(artworkinfo_hash, token, value); - - printf("::: - setting '%s' => '%s'\n\n", - token, value); - } - - checked_free(token); - } - - free(type_identifier); + artwork_new->sort_priority = level_node->sort_priority; + artwork_new->color = LEVELCOLOR(artwork_new); } -#endif + + free(path); } - free(path); + /* insert artwork info (from old cache or filesystem) into new cache */ + if (artwork_new != NULL) + setArtworkInfoCacheEntry(artwork_new, level_node, type); } if (level_node->node_group != NULL) -- 2.34.1