From e4c0a39723c620ca2326b449212bd0b37f301b5e Mon Sep 17 00:00:00 2001 From: Stephen Casner Date: Sat, 9 Dec 2017 18:42:50 -0800 Subject: [PATCH] Update cache when changing log levels so change is effective If any log messages with a particular tag string had already been output before the call was made to adjust the logging level then the new setting would not take effect because the level was cached. This change updates the cached level to the new value and also finds and updates the existing entry in the full uncached list rather than adding a new entry to the end of the list. --- components/log/log.c | 46 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/components/log/log.c b/components/log/log.c index 6a9756a24..f052f310a 100644 --- a/components/log/log.c +++ b/components/log/log.c @@ -96,6 +96,7 @@ static uint32_t s_log_cache_misses = 0; static inline bool get_cached_log_level(const char* tag, esp_log_level_t* level); static inline bool get_uncached_log_level(const char* tag, esp_log_level_t* level); +static inline bool update_cached_log_level(const char* tag, esp_log_level_t level); static inline void add_to_cache(const char* tag, esp_log_level_t level); static void heap_bubble_down(int index); static inline void heap_swap(int i, int j); @@ -121,8 +122,20 @@ void esp_log_level_set(const char* tag, esp_log_level_t level) xSemaphoreGive(s_log_mutex); return; } + // otherwise update the cached entry if it exists + update_cached_log_level(tag, level); - // allocate new linked list entry and append it to the endo of the list + // Walk the linked list of all tags and see if given tag is present in the list. + // If so, update it. This is slow because tags are compared as strings. + for (uncached_tag_entry_t* it = s_log_tags_head; it != NULL; it = it->next) { + if (strcmp(tag, it->tag) == 0) { + it->level = level; + xSemaphoreGive(s_log_mutex); + return; + } + } + + // allocate new linked list entry and append it to the end of the list size_t entry_size = offsetof(uncached_tag_entry_t, tag) + strlen(tag) + 1; uncached_tag_entry_t* new_entry = (uncached_tag_entry_t*) malloc(entry_size); if (!new_entry) { @@ -222,6 +235,37 @@ static inline bool get_cached_log_level(const char* tag, esp_log_level_t* level) return true; } +static inline bool update_cached_log_level(const char* tag, esp_log_level_t level) +{ + // Look for `tag` in cache + int i; + for (i = 0; i < s_log_cache_entry_count; ++i) { +#ifdef LOG_BUILTIN_CHECKS + assert(i == 0 || s_log_cache[(i - 1) / 2].generation < s_log_cache[i].generation); +#endif + if (strcmp(s_log_cache[i].tag, tag) == 0) { + break; + } + } + if (i == s_log_cache_entry_count) { // Not found in cache + return false; + } + // Set new level from cache + s_log_cache[i].level = level; + // If cache has been filled, start taking ordering into account + // (other options are: dynamically resize cache, add "dummy" entries + // to the cache; this option was chosen because code is much simpler, + // and the unfair behavior of cache will show it self at most once, when + // it has just been filled) + if (s_log_cache_entry_count == TAG_CACHE_SIZE) { + // Update item generation + s_log_cache[i].generation = s_log_cache_max_generation++; + // Restore heap ordering + heap_bubble_down(i); + } + return true; +} + static inline void add_to_cache(const char* tag, esp_log_level_t level) { uint32_t generation = s_log_cache_max_generation++;