diff options
-rw-r--r-- | apps/lang/english.lang | 13 | ||||
-rw-r--r-- | apps/misc.c | 8 | ||||
-rw-r--r-- | apps/tagcache.c | 72 | ||||
-rw-r--r-- | apps/tagtree.c | 78 | ||||
-rw-r--r-- | firmware/common/dircache.c | 33 | ||||
-rw-r--r-- | firmware/export/powermgmt.h | 1 | ||||
-rw-r--r-- | firmware/include/dircache.h | 1 | ||||
-rw-r--r-- | firmware/powermgmt.c | 6 |
8 files changed, 165 insertions, 47 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index a388884d69..f56c6aae90 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -8474,3 +8474,16 @@ *: "" </voice> </phrase> +<phrase> + id: LANG_TAGCACHE_BUSY + desc: when trying to shutdown and tagcache is committing + <source> + *: "Tagcache is not ready" + </source> + <dest> + *: "Tagcache is not ready" + </dest> + <voice> + *: "Tagcache is not ready" + </voice> +</phrase> diff --git a/apps/misc.c b/apps/misc.c index 6493e7b46f..ba360e5a91 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -44,6 +44,7 @@ #include "version.h" #include "font.h" #include "splash.h" +#include "tagcache.h" #ifdef HAVE_MMC #include "ata_mmc.h" #endif @@ -487,6 +488,13 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter) (void)parameter; exit(0); #else + if (tagcache_get_commit_step() > 0) + { + cancel_shutdown(); + gui_syncsplash(HZ, true, str(LANG_TAGCACHE_BUSY)); + return false; + } + #if defined(HAVE_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING) if(!charger_inserted()) #endif diff --git a/apps/tagcache.c b/apps/tagcache.c index b992a0d586..1c4ab6f3af 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c @@ -78,6 +78,8 @@ static int init_step; /* Tag Cache Header version 'TCHxx' */ #define TAGCACHE_MAGIC 0x54434802 +#define TAGCACHE_RESERVE 32768 + /* Tag database structures. */ /* Variable-length tag entry in tag files. */ @@ -575,6 +577,9 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) tagcache_search_finish(tcs); memset(tcs, 0, sizeof(struct tagcache_search)); + if (tagcache_get_commit_step() > 0) + return false; + tcs->position = sizeof(struct tagcache_header); tcs->fd = -1; tcs->type = tag; @@ -1453,6 +1458,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd) * table when the index gets resorted. */ tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id); + yield(); } } else @@ -1592,6 +1598,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd) /* Skip to next. */ lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] - entry.tag_length[index_type], SEEK_CUR); + yield(); } /* Sort the buffer data and write it to the index file. */ @@ -1634,6 +1641,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd) error = true; goto error_exit; } + yield(); } } @@ -1730,7 +1738,8 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd) error = true; break ; } - + + yield(); } /* Finally write the uniqued tag index file. */ @@ -1796,6 +1805,25 @@ static bool commit(void) return true; } + /* Try to steal every buffer we can :) */ +#ifdef HAVE_TC_RAMCACHE + if (tempbuf_size == 0 && tagcache_size > 0) + { + ramcache = false; + tempbuf = (char *)(hdr + 1); + tempbuf_size = tagcache_size - sizeof(struct ramcache_header); + } +#endif + +#ifdef HAVE_DIRCACHE + if (tempbuf_size == 0) + { + /* Try to steal the dircache buffer. */ + tempbuf = dircache_steal_buffer(&tempbuf_size); + } +#endif + + /* And finally fail if there are no buffers available. */ if (tempbuf_size == 0) { logf("delaying commit until next boot"); @@ -1855,6 +1883,17 @@ static bool commit(void) logf("tagcache committed"); remove(TAGCACHE_FILE_TEMP); +#ifdef HAVE_DIRCACHE + /* Rebuild the dircache, if we stole the buffer. */ + dircache_build(0); +#endif + +#ifdef HAVE_TC_RAMCACHE + /* Reload tagcache. */ + if (tagcache_size > 0 && !ramcache) + tagcache_start_scan(); +#endif + return true; } @@ -1912,7 +1951,7 @@ static bool allocate_tagcache(void) * Now calculate the required cache size plus * some extra space for alignment fixes. */ - tagcache_size = hdr->h.datasize + 128 + + tagcache_size = hdr->h.datasize + 128 + TAGCACHE_RESERVE + sizeof(struct index_entry) * hdr->h.entry_count + sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); logf("tagcache: %d bytes allocated.", tagcache_size); @@ -1932,8 +1971,8 @@ static bool load_tagcache(void) int i; /* We really need the dircache for this. */ - while (!dircache_is_enabled()) - sleep(HZ); + if (!dircache_is_enabled()) + return false; logf("loading tagcache to ram..."); @@ -1943,6 +1982,14 @@ static bool load_tagcache(void) logf("tagcache open failed"); return false; } + + if (read(fd, &hdr->h, sizeof(struct tagcache_header)) + != sizeof(struct tagcache_header) + || hdr->h.magic != TAGCACHE_MAGIC) + { + logf("incorrect header"); + return false; + } lseek(fd, sizeof(struct tagcache_header), SEEK_SET); @@ -2252,17 +2299,13 @@ static void tagcache_thread(void) bool check_done = false; /* If the previous cache build/update was interrupted, commit - * the changes first. */ + * the changes first in foreground. */ cpu_boost(true); allocate_tempbuf(); commit(); free_tempbuf(); cpu_boost(false); -#ifdef HAVE_TC_RAMCACHE - /* Allocate space for the tagcache if found on disk. */ - allocate_tagcache(); -#endif tagcache_init_done = true; while (1) @@ -2288,7 +2331,7 @@ static void tagcache_thread(void) if (!ramcache && global_settings.tagcache_ram) load_ramcache(); - if (global_settings.tagcache_ram) + if (ramcache) build_tagcache(); check_done = true; @@ -2303,6 +2346,7 @@ static void tagcache_thread(void) #ifndef SIMULATOR case SYS_USB_CONNECTED: + logf("USB: TagCache"); usb_acknowledge(SYS_USB_CONNECTED_ACK); usb_wait_for_disconnect(&tagcache_queue); break ; @@ -2322,7 +2366,7 @@ int tagcache_get_progress(void) } else { - if (hdr) + if (hdr && ramcache) total_count = hdr->h.entry_count; } #endif @@ -2362,6 +2406,12 @@ void tagcache_init(void) { tagcache_init_done = false; init_step = 0; + +#ifdef HAVE_TC_RAMCACHE + /* Allocate space for the tagcache if found on disk. */ + allocate_tagcache(); +#endif + queue_init(&tagcache_queue); create_thread(tagcache_thread, tagcache_stack, sizeof(tagcache_stack), tagcache_thread_name); diff --git a/apps/tagtree.c b/apps/tagtree.c index ccf926163a..875065a4ea 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c @@ -399,7 +399,9 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, 0, csi->name); } - tagcache_search(tcs, csi->tagorder[extra]); + if (!tagcache_search(tcs, csi->tagorder[extra])) + return -1; + for (i = 0; i < extra; i++) { tagcache_search_add_filter(tcs, csi->tagorder[i], csi->result_seek[i]); @@ -502,10 +504,29 @@ int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, return total_count; } -int tagtree_load(struct tree_context* c) +static int load_root(struct tree_context *c) { - int i; struct tagentry *dptr = (struct tagentry *)c->dircache; + int i; + + c->currtable = root; + for (i = 0; i < si_count; i++) + { + dptr->name = (si+i)->name; + dptr->newtable = navibrowse; + dptr->extraseek = i; + dptr++; + } + + current_offset = 0; + current_entry_count = i; + + return i; +} + +int tagtree_load(struct tree_context* c) +{ + int count; int table = c->currtable; c->dentry_size = sizeof(struct tagentry); @@ -517,25 +538,15 @@ int tagtree_load(struct tree_context* c) c->currtable = table; } - switch (table) { - case root: { - for (i = 0; i < si_count; i++) - { - dptr->name = (si+i)->name; - dptr->newtable = navibrowse; - dptr->extraseek = i; - dptr++; - } - c->dirlength = c->filesindir = i; - current_offset = 0; - current_entry_count = i; - - return c->dirlength; - } + switch (table) + { + case root: + count = load_root(c); + break; case navibrowse: logf("navibrowse..."); - i = retrieve_entries(c, &tcs, 0, true); + count = retrieve_entries(c, &tcs, 0, true); break; default: @@ -543,11 +554,17 @@ int tagtree_load(struct tree_context* c) return -1; } + if (count < 0) + { + c->dirlevel = 0; + count = load_root(c); + gui_syncsplash(HZ, true, str(LANG_TAGCACHE_BUSY)); + } /* The _total_ numer of entries available. */ - c->dirlength = c->filesindir = i; + c->dirlength = c->filesindir = count; - return i; + return count; } int tagtree_enter(struct tree_context* c) @@ -654,13 +671,15 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) entry = tagtree_get_entry(c, c->selected_item); - tagcache_search(&tcs, tag_filename); + if (!tagcache_search(&tcs, tag_filename)) + return -1; + tagcache_search_add_filter(&tcs, tag_title, entry->newtable); if (!tagcache_get_next(&tcs)) { tagcache_search_finish(&tcs); - return -1; + return -2; } strncpy(buf, tcs.result, buflen-1); @@ -681,7 +700,12 @@ static int tagtree_play_folder(struct tree_context* c) } cpu_boost(true); - tagcache_search(&tcs, tag_filename); + if (!tagcache_search(&tcs, tag_filename)) + { + gui_syncsplash(HZ, true, str(LANG_TAGCACHE_BUSY)); + return -1; + } + for (i=0; i < c->filesindir; i++) { if (!show_search_progress(false, i)) @@ -717,7 +741,11 @@ struct tagentry* tagtree_get_entry(struct tree_context *c, int id) /* Load the next chunk if necessary. */ if (realid >= current_entry_count || realid < 0) { - retrieve_entries(c, &tcs, MAX(0, id - (current_entry_count / 2)), false); + if (retrieve_entries(c, &tcs, MAX(0, id - (current_entry_count / 2)), + false) < 0) + { + return NULL; + } realid = id - current_offset; } diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 9a0bcb631f..e5ee77c311 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c @@ -567,6 +567,7 @@ static int dircache_do_rebuild(void) audiobuf += (long)((dircache_size & ~0x03) + 0x04); audiobuf += DIRCACHE_RESERVE; allocated_size = dircache_size + DIRCACHE_RESERVE; + reserve_used = 0; } return 1; @@ -612,27 +613,20 @@ static void dircache_thread(void) */ int dircache_build(int last_size) { - if (dircache_initialized) + if (dircache_initialized || thread_enabled) return -3; - while (thread_enabled) - sleep(1); - logf("Building directory cache"); if (dircache_size > 0) { - allocated_size = dircache_size + (DIRCACHE_RESERVE-reserve_used); thread_enabled = true; queue_post(&dircache_queue, DIRCACHE_BUILD, 0); return 2; } - else - { - dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04); - dircache_size = 0; - } + + dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04); - if (last_size > DIRCACHE_RESERVE && last_size < DIRCACHE_LIMIT) + if (last_size > DIRCACHE_RESERVE && last_size < DIRCACHE_LIMIT ) { allocated_size = last_size + DIRCACHE_RESERVE; @@ -650,6 +644,23 @@ int dircache_build(int last_size) } /** + * Steal the allocated dircache buffer and disable dircache. + */ +void* dircache_steal_buffer(long *size) +{ + dircache_disable(); + if (dircache_size == 0) + { + *size = 0; + return NULL; + } + + *size = dircache_size + (DIRCACHE_RESERVE-reserve_used); + + return dircache_root; +} + +/** * Main initialization function that must be called before any other * operations within the dircache. */ diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h index da78857072..6c31aeec52 100644 --- a/firmware/export/powermgmt.h +++ b/firmware/export/powermgmt.h @@ -139,6 +139,7 @@ void set_sleep_timer(int seconds); int get_sleep_timer(void); void set_car_adapter_mode(bool setting); void reset_poweroff_timer(void); +void cancel_shutdown(void); void shutdown_hw(void); void sys_poweroff(void); diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index bd7308da68..6c214a9073 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h @@ -83,6 +83,7 @@ void dircache_init(void); int dircache_load(const char *path); int dircache_save(const char *path); int dircache_build(int last_size); +void* dircache_steal_buffer(long *size); bool dircache_is_enabled(void); int dircache_get_entry_count(void); int dircache_get_cache_size(void); diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 4c6db6d44c..15977caed6 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -1019,6 +1019,12 @@ void sys_poweroff(void) queue_post(&button_queue, SYS_POWEROFF, NULL); } +void cancel_shutdown(void) +{ + logf("sys_cancel_shutdown()"); + shutdown_timeout = 0; +} + /* Various hardware housekeeping tasks relating to shutting down the jukebox */ void shutdown_hw(void) { |