From 1bb10529252786e34ccd3db3e78d060bea5e9343 Mon Sep 17 00:00:00 2001 From: Michael Hohmuth Date: Thu, 4 Aug 2011 23:22:26 +0000 Subject: Database: Bug fix: The filename seek index is invalid if FLAG_DIRCACHE is set on a database entry and the dircache went offline. In this case, retrieve() and get_next() need to abort and take the ramcache offline as well. git-svn-id: svn://svn.rockbox.org/rockbox/branches/v3_9@30257 a1c6a512-1295-4272-9138-f99709370657 --- apps/tagcache.c | 52 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/apps/tagcache.c b/apps/tagcache.c index 9f4769258f..91347c048e 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -719,12 +719,25 @@ 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) - && is_dircache_intact()) + if (tag == tag_filename && (idx->flag & FLAG_DIRCACHE)) { - dircache_copy_path((struct dircache_entry *)seek, - buf, size); - return true; + /* for tag_filename, seek is a dircache index */ + if (is_dircache_intact()) + { + dircache_copy_path((struct dircache_entry *)seek, + buf, size); + return true; + } + else + { + /* The seek is useless now, there's nothing we can return. */ + logf("retrieve: dircache gone, cannot read file name"); + tagcache_unload_ramcache(); + // XXX do this when there's a way to not trigger an + // update before reloading: + // tagcache_start_scan(); + return false; + } } else # endif @@ -1477,16 +1490,29 @@ static bool get_next(struct tagcache_search *tcs) { #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) - if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE) - && is_dircache_intact()) + if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE)) { - dircache_copy_path((struct dircache_entry *)tcs->position, - buf, sizeof buf); - tcs->result = buf; - tcs->result_len = strlen(buf) + 1; - tcs->ramresult = false; + if (is_dircache_intact()) + { + dircache_copy_path((struct dircache_entry *)tcs->position, + buf, sizeof buf); + tcs->result = buf; + tcs->result_len = strlen(buf) + 1; + tcs->ramresult = false; - return true; + return true; + } + else + { + /* The seek is useless now, there's nothing we can return. */ + logf("get_next: dircache gone, cannot read file name"); + tagcache_unload_ramcache(); + // XXX do this when there's a way to not trigger an + // update before reloading: + // tagcache_start_scan(); + tcs->valid = false; + return false; + } } else #endif -- cgit v1.2.3