diff --git a/apps/tagcache.c b/apps/tagcache.c index 2b4f1a2181..044fcab6e7 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -299,6 +299,15 @@ bool tagcache_is_sorted_tag(int type) return false; } +/** + * Returns true if specified flag is still present, i.e., dircache + * has not been reloaded. + */ +static bool is_dircache_intact(void) +{ + return dircache_get_appflag(DIRCACHE_APPFLAG_TAGCACHE); +} + static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write) { int fd; @@ -531,7 +540,7 @@ static int find_index(const char *filename) long idx_id = -1; #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) - if (tc_stat.ramcache && dircache_is_enabled()) + if (tc_stat.ramcache && is_dircache_intact()) idx_id = find_entry_ram(filename, NULL); #endif @@ -703,7 +712,8 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, struct tagfile_entry *ep; # ifdef HAVE_DIRCACHE - if (tag == tag_filename && idx->flag & FLAG_DIRCACHE) + if (tag == tag_filename && (idx->flag & FLAG_DIRCACHE) + && is_dircache_intact()) { dircache_copy_path((struct dirent *)seek, buf, size); @@ -1292,7 +1302,7 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, } #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ - ? (flag & FLAG_DIRCACHE) : 1) + ? ((flag & FLAG_DIRCACHE) && is_dircache_intact()) : 1) static bool get_next(struct tagcache_search *tcs) { @@ -1657,7 +1667,7 @@ static void add_tagcache(char *path, unsigned long mtime /* Check if the file is already cached. */ #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) - if (tc_stat.ramcache && dircache_is_enabled()) + if (tc_stat.ramcache && is_dircache_intact()) { idx_id = find_entry_ram(path, dc); } @@ -3776,6 +3786,8 @@ static bool load_tagcache(void) sleep(1); # endif + dircache_set_appflag(DIRCACHE_APPFLAG_TAGCACHE); + logf("loading tagcache to ram..."); fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); @@ -3931,25 +3943,20 @@ static bool load_tagcache(void) else # endif { - - /* Enabled for flash based targets. Too slow otherwise. */ -# ifdef HAVE_FLASH_STORAGE + /* This will be very slow unless dircache is enabled + or target is flash based, but do it anyway for + consistency. */ /* Check if entry has been removed. */ if (global_settings.tagcache_autoupdate) { - int testfd; - - testfd = open(buf, O_RDONLY); - if (testfd < 0) + if (!file_exists(buf)) { logf("Entry no longer valid."); logf("-> %s", buf); delete_entry(fe->idx_id); continue; } - close(testfd); } -# endif } continue ; @@ -3992,7 +3999,7 @@ static bool load_tagcache(void) static bool check_deleted_files(void) { - int fd, testfd; + int fd; char buf[TAG_MAXLEN+32]; struct tagfile_entry tfe; @@ -4033,14 +4040,12 @@ static bool check_deleted_files(void) continue; /* Now check if the file exists. */ - testfd = open(buf, O_RDONLY); - if (testfd < 0) + if (!file_exists(buf)) { logf("Entry no longer valid."); logf("-> %s / %d", buf, tfe.tag_length); delete_entry(tfe.idx_id); } - close(testfd); } close(fd); @@ -4336,16 +4341,11 @@ static void tagcache_thread(void) if (global_settings.tagcache_autoupdate) { build_tagcache("/"); - /* Don't do auto removal without dircache or flash - * storage (very slow). */ -#ifdef HAVE_FLASH_STORAGE + + /* This will be very slow unless dircache is enabled + or target is flash based, but do it anyway for + consistency. */ check_deleted_files(); -#else -# ifdef HAVE_DIRCACHE - if (dircache_is_enabled()) - check_deleted_files(); -# endif -#endif } logf("tagcache check done"); diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 8e9cffb73e..983f0b03cf 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -60,6 +60,7 @@ static unsigned long dircache_size = 0; static unsigned long entry_count = 0; static unsigned long reserve_used = 0; static unsigned int cache_build_ticks = 0; +static unsigned long appflags = 0; static char dircache_cur_path[MAX_PATH*2]; static struct event_queue dircache_queue; @@ -450,6 +451,7 @@ int dircache_load(void) dircache_root = buffer_alloc(maindata.size + DIRCACHE_RESERVE); entry_count = maindata.entry_count; + appflags = maindata.appflags; bytes_read = read(fd, dircache_root, MIN(DIRCACHE_LIMIT, maindata.size)); close(fd); remove(DIRCACHE_FILE); @@ -493,6 +495,7 @@ int dircache_save(void) maindata.size = dircache_size; maindata.root_entry = dircache_root; maindata.entry_count = entry_count; + maindata.appflags = appflags; /* Save the info structure */ bytes_written = write(fd, &maindata, sizeof(struct dircache_maindata)); @@ -532,6 +535,7 @@ static int dircache_do_rebuild(void) /* Measure how long it takes build the cache. */ start_tick = current_tick; dircache_initializing = true; + appflags = 0; #ifdef SIMULATOR pdir = opendir_uncached("/"); @@ -722,6 +726,22 @@ bool dircache_is_initializing(void) return dircache_initializing || thread_enabled; } +/** + * Set application flags used to determine if dircache is still intact. + */ +void dircache_set_appflag(long mask) +{ + appflags |= mask; +} + +/** + * Get application flags used to determine if dircache is still intact. + */ +bool dircache_get_appflag(long mask) +{ + return appflags & mask; +} + /** * Returns the current number of entries (directories and files) in the cache. */ diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index 7d2111697c..a703d0be41 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h @@ -28,6 +28,8 @@ /* FIXME: We should use ROCKBOX_DIR here but it's defined in apps/ */ #define DIRCACHE_FILE "/.rockbox/dircache.dat" +#define DIRCACHE_APPFLAG_TAGCACHE 0x0001 + /* Internal structures. */ struct travel_data { struct dircache_entry *first; @@ -49,6 +51,7 @@ struct dircache_maindata { long magic; long size; long entry_count; + long appflags; struct dircache_entry *root_entry; }; @@ -87,6 +90,8 @@ int dircache_build(int last_size); void* dircache_steal_buffer(long *size); bool dircache_is_enabled(void); bool dircache_is_initializing(void); +void dircache_set_appflag(long mask); +bool dircache_get_appflag(long mask); int dircache_get_entry_count(void); int dircache_get_cache_size(void); int dircache_get_reserve_used(void);