From 8e2bdcaab6857daed1174487e4262d1a4c5db9ab Mon Sep 17 00:00:00 2001 From: Miika Pekkarinen Date: Sat, 20 Jun 2009 16:17:54 +0000 Subject: [PATCH] A bunch of stability fixes into tagcache engine and database browser. Mainly data retrieval problems, races, data corruption of sorted index files at the end with junk data, access to unitialized memory and so on. Should fix FS#8710 and may fix FS#8414. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21402 a1c6a512-1295-4272-9138-f99709370657 --- apps/tagcache.c | 214 ++++++++++++++++++++++++++++++------------------ apps/tagcache.h | 33 ++++---- apps/tagtree.c | 68 ++++++++------- 3 files changed, 192 insertions(+), 123 deletions(-) diff --git a/apps/tagcache.c b/apps/tagcache.c index d4ec1078d8..d7a377e7e2 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -410,7 +410,7 @@ static long find_entry_ram(const char *filename, } #endif -static long find_entry_disk(const char *filename) +static long find_entry_disk(const char *filename, bool localfd) { struct tagcache_header tch; static long last_pos = -1; @@ -427,7 +427,7 @@ static long find_entry_disk(const char *filename) return -2; fd = filenametag_fd; - if (fd < 0) + if (fd < 0 || localfd) { last_pos = -1; if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0) @@ -458,6 +458,8 @@ static long find_entry_disk(const char *filename) { logf("too long tag #1"); close(fd); + if (!localfd) + filenametag_fd = -1; last_pos = -1; return -2; } @@ -466,6 +468,8 @@ static long find_entry_disk(const char *filename) { logf("read error #2"); close(fd); + if (!localfd) + filenametag_fd = -1; last_pos = -1; return -3; } @@ -491,12 +495,12 @@ static long find_entry_disk(const char *filename) goto check_again; } - if (fd != filenametag_fd) + if (fd != filenametag_fd || localfd) close(fd); return -4; } - if (fd != filenametag_fd) + if (fd != filenametag_fd || localfd) close(fd); return tfe.idx_id; @@ -512,7 +516,7 @@ static int find_index(const char *filename) #endif if (idx_id < 0) - idx_id = find_entry_disk(filename); + idx_id = find_entry_disk(filename, true); return idx_id; } @@ -554,8 +558,14 @@ static bool get_index(int masterfd, int idxid, if (hdr->indices[idxid].flag & FLAG_DELETED) return false; - memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry)); - return true; +# ifdef HAVE_DIRCACHE + if (!(hdr->indices[idxid].flag & FLAG_DIRCACHE) + || is_dircache_intact()) +#endif + { + memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry)); + return true; + } } #else (void)use_ram; @@ -1006,17 +1016,20 @@ static bool add_uniqbuf(struct tagcache_search *tcs, unsigned long id) static bool build_lookup_list(struct tagcache_search *tcs) { struct index_entry entry; - int i; + int i, j; tcs->seek_list_count = 0; #ifdef HAVE_TC_RAMCACHE - if (tcs->ramsearch) + if (tcs->ramsearch +# ifdef HAVE_DIRCACHE + && (tcs->type != tag_filename || is_dircache_intact()) +# endif + ) { - int j; - for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) { + struct tagcache_seeklist_entry *seeklist; struct index_entry *idx = &hdr->indices[i]; if (tcs->seek_list_count == SEEK_LIST_SIZE) break ; @@ -1046,26 +1059,37 @@ static bool build_lookup_list(struct tagcache_search *tcs) continue; /* Lets add it. */ - tcs->seek_list[tcs->seek_list_count] = idx->tag_seek[tcs->type]; - tcs->seek_flags[tcs->seek_list_count] = idx->flag; + seeklist = &tcs->seeklist[tcs->seek_list_count]; + seeklist->seek = idx->tag_seek[tcs->type]; + seeklist->flag = idx->flag; + seeklist->idx_id = i; tcs->seek_list_count++; } tcs->seek_pos = i; - + return tcs->seek_list_count > 0; } #endif + if (tcs->masterfd < 0) + { + struct master_header tcmh; + tcs->masterfd = open_master_fd(&tcmh, false); + } + lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + sizeof(struct master_header), SEEK_SET); while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ) == sizeof(struct index_entry)) { + struct tagcache_seeklist_entry *seeklist; + if (tcs->seek_list_count == SEEK_LIST_SIZE) break ; - + + i = tcs->seek_pos; tcs->seek_pos++; /* Check if entry has been deleted. */ @@ -1073,13 +1097,13 @@ static bool build_lookup_list(struct tagcache_search *tcs) continue; /* Go through all filters.. */ - for (i = 0; i < tcs->filter_count; i++) + for (j = 0; j < tcs->filter_count; j++) { - if (entry.tag_seek[tcs->filter_tag[i]] != tcs->filter_seek[i]) + if (entry.tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j]) break ; } - if (i < tcs->filter_count) + if (j < tcs->filter_count) continue ; /* Check for conditions. */ @@ -1091,8 +1115,10 @@ static bool build_lookup_list(struct tagcache_search *tcs) continue; /* Lets add it. */ - tcs->seek_list[tcs->seek_list_count] = entry.tag_seek[tcs->type]; - tcs->seek_flags[tcs->seek_list_count] = entry.flag; + seeklist = &tcs->seeklist[tcs->seek_list_count]; + seeklist->seek = entry.tag_seek[tcs->type]; + seeklist->flag = entry.flag; + seeklist->idx_id = i; tcs->seek_list_count++; yield(); @@ -1155,15 +1181,17 @@ static bool check_all_headers(void) return true; } +bool tagcache_is_busy(void) +{ + return read_lock || write_lock; +} + bool tagcache_search(struct tagcache_search *tcs, int tag) { struct tagcache_header tag_hdr; struct master_header master_hdr; int i; - if (tcs->initialized) - tagcache_search_finish(tcs); - while (read_lock) sleep(1); @@ -1174,6 +1202,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) tcs->position = sizeof(struct tagcache_header); tcs->type = tag; tcs->seek_pos = 0; + tcs->list_position = 0; tcs->seek_list_count = 0; tcs->filter_count = 0; tcs->masterfd = -1; @@ -1192,19 +1221,24 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) else #endif { + /* Always open as R/W so we can pass tcs to functions that modify data also + * without failing. */ + tcs->masterfd = open_master_fd(&master_hdr, true); + if (tcs->masterfd < 0) + return false; + if (!TAGCACHE_IS_NUMERIC(tcs->type)) { tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false); if (tcs->idxfd[tcs->type] < 0) return false; + + tcs->entry_count = tag_hdr.entry_count; + } + else + { + tcs->entry_count = master_hdr.tch.entry_count; } - - /* Always open as R/W so we can pass tcs to functions that modify data also - * without failing. */ - tcs->masterfd = open_master_fd(&master_hdr, true); - - if (tcs->masterfd < 0) - return false; } tcs->valid = true; @@ -1272,14 +1306,6 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, return true; } -/* TODO: Remove this mess. */ -#ifdef HAVE_DIRCACHE -#define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ - ? ((flag & FLAG_DIRCACHE) && is_dircache_intact()) : 1) -#else -#define TAG_FILENAME_RAM(tcs) (tcs->type != tag_filename) -#endif - static bool get_next(struct tagcache_search *tcs) { static char buf[TAG_MAXLEN+32]; @@ -1298,11 +1324,20 @@ static bool get_next(struct tagcache_search *tcs) /* Relative fetch. */ if (tcs->filter_count > 0 || tcs->clause_count > 0 - || TAGCACHE_IS_NUMERIC(tcs->type)) + || TAGCACHE_IS_NUMERIC(tcs->type) +#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) + /* We need to retrieve flag status for dircache. */ + || (tcs->ramsearch && tcs->type == tag_filename) +#endif + ) { + struct tagcache_seeklist_entry *seeklist; + /* Check for end of list. */ - if (tcs->seek_list_count == 0) + if (tcs->list_position == tcs->seek_list_count) { + tcs->list_position = 0; + /* Try to fetch more. */ if (!build_lookup_list(tcs)) { @@ -1311,15 +1346,28 @@ static bool get_next(struct tagcache_search *tcs) } } - tcs->seek_list_count--; - flag = tcs->seek_flags[tcs->seek_list_count]; - tcs->position = tcs->seek_list[tcs->seek_list_count]; + seeklist = &tcs->seeklist[tcs->list_position]; + flag = seeklist->flag; + tcs->position = seeklist->seek; + tcs->idx_id = seeklist->idx_id; + tcs->list_position++; } + else + { + if (tcs->entry_count == 0) + { + tcs->valid = false; + return false; + } + + tcs->entry_count--; + } + + tcs->result_seek = tcs->position; if (TAGCACHE_IS_NUMERIC(tcs->type)) { snprintf(buf, sizeof(buf), "%d", tcs->position); - tcs->result_seek = tcs->position; tcs->result = buf; tcs->result_len = strlen(buf) + 1; return true; @@ -1327,55 +1375,54 @@ static bool get_next(struct tagcache_search *tcs) /* Direct fetch. */ #ifdef HAVE_TC_RAMCACHE - if (tcs->ramsearch && TAG_FILENAME_RAM(tcs)) + if (tcs->ramsearch) { - struct tagfile_entry *ep; - if (tcs->entry_count == 0) - { - tcs->valid = false; - return false; - } - tcs->entry_count--; - - tcs->result_seek = tcs->position; - -# ifdef HAVE_DIRCACHE - if (tcs->type == tag_filename) +#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) + if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE) + && is_dircache_intact()) { dircache_copy_path((struct dirent *)tcs->position, buf, sizeof buf); tcs->result = buf; tcs->result_len = strlen(buf) + 1; - tcs->idx_id = FLAG_GET_ATTR(flag); tcs->ramresult = false; return true; } -# endif - - ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; - tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; - tcs->result = ep->tag_data; - tcs->result_len = strlen(tcs->result) + 1; - tcs->idx_id = ep->idx_id; - tcs->ramresult = true; - - return true; + else +#endif + if (tcs->type != tag_filename) + { + struct tagfile_entry *ep; + + ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; + tcs->result = ep->tag_data; + tcs->result_len = strlen(tcs->result) + 1; + tcs->idx_id = ep->idx_id; + tcs->ramresult = true; + + /* Increase position for the next run. This may get overwritten. */ + tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; + + return true; + } } #endif if (!open_files(tcs, tcs->type)) + { + tcs->valid = false; return false; + } /* Seek stream to the correct position and continue to direct fetch. */ lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET); - tcs->result_seek = tcs->position; if (ecread(tcs->idxfd[tcs->type], &entry, 1, tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry)) { - /* End of data. */ + logf("read error #5"); tcs->valid = false; return false; } @@ -1384,6 +1431,7 @@ static bool get_next(struct tagcache_search *tcs) { tcs->valid = false; logf("too long tag #2"); + logf("P:%X/%X", tcs->position, entry.tag_length); return false; } @@ -1536,12 +1584,12 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) struct index_entry *entry; int idx_id; - if (!tc_stat.ready) + if (!tc_stat.ready || !tc_stat.ramcache) return false; /* Find the corresponding entry in tagcache. */ idx_id = find_entry_ram(filename, NULL); - if (idx_id < 0 || !tc_stat.ramcache) + if (idx_id < 0) return false; entry = &hdr->indices[idx_id]; @@ -1644,14 +1692,11 @@ static void add_tagcache(char *path, unsigned long mtime { idx_id = find_entry_ram(path, dc); } - else #endif - { - if (filenametag_fd >= 0) - { - idx_id = find_entry_disk(path); - } - } + + /* Be sure the entry doesn't exist. */ + if (filenametag_fd >= 0 && idx_id < 0) + idx_id = find_entry_disk(path, false); /* Check if file has been modified. */ if (idx_id >= 0) @@ -2548,6 +2593,13 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) /* Sort the buffer data and write it to the index file. */ lseek(fd, sizeof(struct tagcache_header), SEEK_SET); + /** + * We need to truncate the index file now. There can be junk left + * at the end of file (however, we _should_ always follow the + * entry_count and don't crash with that). + */ + ftruncate(fd, lseek(fd, 0, SEEK_CUR)); + i = tempbuf_sort(fd); if (i < 0) goto error_exit; @@ -3328,7 +3380,10 @@ bool tagcache_import_changelog(void) close(masterfd); if (filenametag_fd >= 0) + { close(filenametag_fd); + filenametag_fd = -1; + } write_lock--; @@ -3919,7 +3974,6 @@ static bool load_tagcache(void) } idx->flag |= FLAG_DIRCACHE; - FLAG_SET_ATTR(idx->flag, fe->idx_id); idx->tag_seek[tag_filename] = (long)dc; } else diff --git a/apps/tagcache.h b/apps/tagcache.h index f2b975c566..0908e3571c 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h @@ -112,8 +112,6 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, #define FLAG_DIRTYNUM 0x0004 /* Numeric data has been modified */ #define FLAG_TRKNUMGEN 0x0008 /* Track number has been generated */ #define FLAG_RESURRECTED 0x0010 /* Statistics data has been resurrected */ -#define FLAG_GET_ATTR(flag) ((flag >> 16) & 0x0000ffff) -#define FLAG_SET_ATTR(flag,attr) flag = (flag & 0x0000ffff) | (attr << 16) enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, clause_lt, clause_lteq, clause_contains, clause_not_contains, @@ -156,20 +154,26 @@ struct tagcache_search_clause char *str; }; +struct tagcache_seeklist_entry { + int32_t seek; + int32_t flag; + int32_t idx_id; +}; + struct tagcache_search { /* For internal use only. */ int fd, masterfd; int idxfd[TAG_COUNT]; - long seek_list[SEEK_LIST_SIZE]; - long seek_flags[SEEK_LIST_SIZE]; - long filter_tag[TAGCACHE_MAX_FILTERS]; - long filter_seek[TAGCACHE_MAX_FILTERS]; + struct tagcache_seeklist_entry seeklist[SEEK_LIST_SIZE]; + int seek_list_count; + int32_t filter_tag[TAGCACHE_MAX_FILTERS]; + int32_t filter_seek[TAGCACHE_MAX_FILTERS]; int filter_count; struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES]; int clause_count; - int seek_list_count; + int list_position; int seek_pos; - long position; + int32_t position; int entry_count; bool valid; bool initialized; @@ -178,13 +182,13 @@ struct tagcache_search { int unique_list_count; /* Exported variables. */ - bool ramsearch; - bool ramresult; + bool ramsearch; /* Is ram copy of the tagcache being used. */ + bool ramresult; /* False if result is not static, and must be copied. */ int type; - char *result; - int result_len; - long result_seek; - int idx_id; + char *result; /* The result data for all tags. */ + int result_len; /* Length of the result including \0 */ + int32_t result_seek; /* Current position in the tag data. */ + int32_t idx_id; /* Entry number in the master index. */ }; void tagcache_build(const char *path); @@ -201,6 +205,7 @@ bool tagcache_is_numeric_tag(int type); bool tagcache_find_index(struct tagcache_search *tcs, const char *filename); bool tagcache_check_clauses(struct tagcache_search *tcs, struct tagcache_search_clause **clause, int count); +bool tagcache_is_busy(void); bool tagcache_search(struct tagcache_search *tcs, int tag); void tagcache_search_set_uniqbuf(struct tagcache_search *tcs, void *buffer, long length); diff --git a/apps/tagtree.c b/apps/tagtree.c index 9635052ef3..691b2273de 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -23,6 +23,9 @@ * Basic structure on this file was copied from dbtree.c and modified to * support the tag cache interface. */ + +/* #define LOGF_ENABLE */ + #include #include #include @@ -96,7 +99,6 @@ static long *uniqbuf; #define MAX_TAGS 5 #define MAX_MENU_ID_SIZE 32 -static struct tagcache_search tcs, tcs2; static bool sort_inverse; /* @@ -642,6 +644,8 @@ static int compare(const void *p1, const void *p2) static void tagtree_buffer_event(struct mp3entry *id3) { + struct tagcache_search tcs; + /* Do not gather data unless proper setting has been enabled. */ if (!global_settings.runtimedb) return; @@ -719,6 +723,8 @@ static void tagtree_track_finish_event(struct mp3entry *id3) bool tagtree_export(void) { + struct tagcache_search tcs; + splash(0, str(LANG_CREATING)); if (!tagcache_create_changelog(&tcs)) { @@ -1040,9 +1046,9 @@ static int format_str(struct tagcache_search *tcs, struct display_format *fmt, return 0; } -static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, - int offset, bool init) +static int retrieve_entries(struct tree_context *c, int offset, bool init) { + struct tagcache_search tcs; struct tagentry *dptr = (struct tagentry *)c->dircache; struct display_format *fmt; int i; @@ -1055,15 +1061,16 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, int sort_limit; int strip; - if (init + if (init && (tagcache_is_busy() #ifdef HAVE_TC_RAMCACHE - && !tagcache_is_ramcache() + || !tagcache_is_ramcache() #endif - ) + ) ) { /* Show search progress straight away if the disk needs to spin up, otherwise show it after the normal 1/2 second delay */ show_search_progress( + !tagcache_is_busy() && #ifdef HAVE_DISK_STORAGE storage_disk_is_active() #else @@ -1080,11 +1087,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, else tag = csi->tagorder[level]; - if (!tagcache_search(tcs, tag)) + if (!tagcache_search(&tcs, tag)) return -1; /* Prevent duplicate entries in the search list. */ - tagcache_search_set_uniqbuf(tcs, uniqbuf, UNIQBUF_SIZE); + tagcache_search_set_uniqbuf(&tcs, uniqbuf, UNIQBUF_SIZE); if (level || csi->clause_count[0] || TAGCACHE_IS_NUMERIC(tag)) sort = true; @@ -1100,11 +1107,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, cc.type = clause_is; cc.numeric = true; cc.numeric_data = csi->result_seek[i]; - tagcache_search_add_clause(tcs, &cc); + tagcache_search_add_clause(&tcs, &cc); } else { - tagcache_search_add_filter(tcs, csi->tagorder[i], + tagcache_search_add_filter(&tcs, csi->tagorder[i], csi->result_seek[i]); } } @@ -1114,7 +1121,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, int j; for (j = 0; j < csi->clause_count[i]; j++) - tagcache_search_add_clause(tcs, csi->clause[i][j]); + tagcache_search_add_clause(&tcs, csi->clause[i][j]); } current_offset = offset; @@ -1164,7 +1171,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, total_count += special_entry_count; - while (tagcache_get_next(tcs)) + while (tagcache_get_next(&tcs)) { if (total_count++ < offset) continue; @@ -1173,10 +1180,10 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, if (tag == tag_title || tag == tag_filename) { dptr->newtable = PLAYTRACK; - dptr->extraseek = tcs->idx_id; + dptr->extraseek = tcs.idx_id; } else - dptr->extraseek = tcs->result_seek; + dptr->extraseek = tcs.result_seek; fmt = NULL; /* Check the format */ @@ -1185,7 +1192,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, if (formats[i]->group_id != csi->format_id[level]) continue; - if (tagcache_check_clauses(tcs, formats[i]->clause, + if (tagcache_check_clauses(&tcs, formats[i]->clause, formats[i]->clause_count)) { fmt = formats[i]; @@ -1193,15 +1200,16 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, } } - if (!tcs->ramresult || fmt) + if (!tcs.ramresult || fmt) { char buf[MAX_PATH]; if (fmt) { - if (format_str(tcs, fmt, buf, sizeof buf) < 0) + if (format_str(&tcs, fmt, buf, sizeof buf) < 0) { logf("format_str() failed"); + tagcache_search_finish(&tcs); return 0; } } @@ -1210,7 +1218,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, if (fmt) namebufused += strlen(buf)+1; else - namebufused += tcs->result_len; + namebufused += tcs.result_len; if (namebufused >= c->name_buffer_size) { @@ -1222,10 +1230,10 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, if (fmt) strcpy(dptr->name, buf); else - strcpy(dptr->name, tcs->result); + strcpy(dptr->name, tcs.result); } else - dptr->name = tcs->result; + dptr->name = tcs.result; dptr++; current_entry_count++; @@ -1238,11 +1246,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, break ; } - if (init && !tcs->ramsearch) + if (init && !tcs.ramsearch) { if (!show_search_progress(false, total_count)) { - tagcache_search_finish(tcs); + tagcache_search_finish(&tcs); return current_entry_count; } } @@ -1255,13 +1263,13 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, if (!init) { - tagcache_search_finish(tcs); + tagcache_search_finish(&tcs); return current_entry_count; } - while (tagcache_get_next(tcs)) + while (tagcache_get_next(&tcs)) { - if (!tcs->ramsearch) + if (!tcs.ramsearch) { if (!show_search_progress(false, total_count)) break; @@ -1269,7 +1277,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, total_count++; } - tagcache_search_finish(tcs); + tagcache_search_finish(&tcs); if (!sort && (sort_inverse || sort_limit)) { @@ -1363,7 +1371,7 @@ int tagtree_load(struct tree_context* c) case NAVIBROWSE: logf("navibrowse..."); cpu_boost(true); - count = retrieve_entries(c, &tcs, 0, true); + count = retrieve_entries(c, 0, true); cpu_boost(false); break; @@ -1549,6 +1557,7 @@ void tagtree_exit(struct tree_context* c) int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) { + struct tagcache_search tcs; struct tagentry *entry; entry = tagtree_get_entry(c, c->selected_item); @@ -1569,6 +1578,7 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) static bool insert_all_playlist(struct tree_context *c, int position, bool queue) { + struct tagcache_search tcs; int i; char buf[MAX_PATH]; int from, to, direction; @@ -1639,7 +1649,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue) int dirlevel = tc->dirlevel; /* We need to set the table to allsubentries. */ - show_search_progress(true, 0); + show_search_progress(!tagcache_is_busy(), 0); dptr = tagtree_get_entry(tc, tc->selected_item); @@ -1732,7 +1742,7 @@ struct tagentry* tagtree_get_entry(struct tree_context *c, int id) if (realid >= current_entry_count || realid < 0) { cpu_boost(true); - if (retrieve_entries(c, &tcs2, MAX(0, id - (current_entry_count / 2)), + if (retrieve_entries(c, MAX(0, id - (current_entry_count / 2)), false) < 0) { logf("retrieve failed");