void check_cache(struct cache_item* pFirstItem) { time_t time_stamp; time(&time_stamp); int current_time_stamp = ((int)(time_stamp)); struct cache_item* ptr = pFirstItem; while(ptr != NULL) { if (ptr->next_item == NULL) { break; } if (current_time_stamp - ptr->next_item->time_stamp >= 15) { in_addr ip_addr; ip_addr.s_addr = ptr->next_item->ip; Debug("\n\n**** Removing cache entry, [%s, ", inet_ntoa(ip_addr)); DebugMAC(ptr->next_item->mac); Debug("] *****\n\n"); remove_cache_item(ptr); } ptr = ptr->next_item; } }
static void cache_cleaner_thread(void *none) { /* Find where it all happens */ char covers_path[PATH_MAX]; if (make_cache_root_path(covers_path, PATH_MAX-10)) { return; } strcat(covers_path, "covers"); const size_t covers_path_length = strlen(covers_path); deadbeef->mutex_lock(thread_mutex); while (!terminate) { time_t oldest_mtime = time(NULL); /* Loop through the artist directories */ DIR *covers_dir = opendir(covers_path); struct dirent *covers_subdir; while (!terminate && covers_dir && (covers_subdir = readdir(covers_dir))) { const int32_t cache_secs = cache_expiry_seconds; deadbeef->mutex_unlock(thread_mutex); if (cache_secs > 0 && path_ok(covers_path_length, covers_subdir->d_name)) { trace("Analyse %s for expired files\n", covers_subdir->d_name); const time_t cache_expiry = time(NULL) - cache_secs; /* Loop through the image files in this artist directory */ char subdir_path[PATH_MAX]; sprintf(subdir_path, "%s/%s", covers_path, covers_subdir->d_name); const size_t subdir_path_length = strlen(subdir_path); DIR *subdir = opendir(subdir_path); struct dirent *entry; while (subdir && (entry = readdir(subdir))) { if (path_ok(subdir_path_length, entry->d_name)) { char entry_path[PATH_MAX]; sprintf(entry_path, "%s/%s", subdir_path, entry->d_name); /* Test against the cache expiry time (cache invalidation resets are not handled here) */ struct stat stat_buf; if (!stat(entry_path, &stat_buf)) { if (stat_buf.st_mtime <= cache_expiry) { trace("%s expired from cache\n", entry_path); remove_cache_item(entry_path, subdir_path, covers_subdir->d_name, entry->d_name); } else if (stat_buf.st_mtime < oldest_mtime) { oldest_mtime = stat_buf.st_mtime; } } } } if (subdir) { closedir (subdir); } } usleep(100000); deadbeef->mutex_lock(thread_mutex); } if (covers_dir) { closedir (covers_dir); covers_dir = NULL; } /* Sleep until just after the oldest file expires */ if (cache_expiry_seconds > 0 && !terminate) { struct timespec wake_time = { .tv_sec = time(NULL) + max(60, oldest_mtime - time(NULL) + cache_expiry_seconds), .tv_nsec = 999999 }; trace("Cache cleaner sleeping for %d seconds\n", max(60, oldest_mtime - time(NULL) + cache_expiry_seconds)); pthread_cond_timedwait((pthread_cond_t *)thread_cond, (pthread_mutex_t *)thread_mutex, &wake_time); } /* Just go back to sleep if cache expiry is disabled */ while (cache_expiry_seconds <= 0 && !terminate) { trace("Cache cleaner sleeping forever\n"); pthread_cond_wait((pthread_cond_t *)thread_cond, (pthread_mutex_t *)thread_mutex); } } deadbeef->mutex_unlock(thread_mutex); } void cache_configchanged(void) { const int32_t new_cache_expiry_seconds = deadbeef->conf_get_int("artwork.cache.period", 48) * 60 * 60; if (new_cache_expiry_seconds != cache_expiry_seconds) { deadbeef->mutex_lock(thread_mutex); cache_expiry_seconds = new_cache_expiry_seconds; deadbeef->cond_signal(thread_cond); deadbeef->mutex_unlock(thread_mutex); } } void stop_cache_cleaner(void) { if (tid) { deadbeef->mutex_lock(thread_mutex); terminate = 1; deadbeef->cond_signal(thread_cond); deadbeef->mutex_unlock(thread_mutex); deadbeef->thread_join(tid); tid = 0; trace("Cache cleaner thread stopped\n"); } if (thread_mutex) { deadbeef->mutex_free(thread_mutex); thread_mutex = 0; } if (thread_cond) { deadbeef->cond_free(thread_cond); thread_cond = 0; } if (files_mutex) { deadbeef->mutex_free(files_mutex); files_mutex = 0; } } int start_cache_cleaner(void) { terminate = 0; cache_expiry_seconds = deadbeef->conf_get_int("artwork.cache.period", 48) * 60 * 60; files_mutex = deadbeef->mutex_create_nonrecursive(); thread_mutex = deadbeef->mutex_create_nonrecursive(); thread_cond = deadbeef->cond_create(); if (files_mutex && thread_mutex && thread_cond) { tid = deadbeef->thread_start_low_priority(cache_cleaner_thread, NULL); trace("Cache cleaner thread started\n"); } if (!tid) { stop_cache_cleaner(); return -1; } return 0; }