Tagcache: Fixed runtime stats not being gathered when tagcache is kept

on disk. Initial attempt to make tagcache thread safe. Replaced a few
direct buffer allocations with buffer_alloc from tagcache and dircache
where possible.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10415 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-08-02 17:39:34 +00:00
parent d68ae6a7a6
commit d8ac607418
5 changed files with 74 additions and 22 deletions

View file

@ -850,7 +850,7 @@ int onplay(char* file, int attr, int from)
if (context == CONTEXT_WPS ||
context == CONTEXT_TREE ||
(context == CONTEXT_ID3DB))
context == CONTEXT_ID3DB)
{
items[i].desc = ID2P(LANG_PLAYLIST);
items[i].function = playlist_options;

View file

@ -43,9 +43,9 @@
* | | | | +--x--------x---------+ |
* | | | | | Temporary Commit DB | |
* | | | | +---------------------+ |
* +-x----x---x---x--+ |
* +-x----x-------x--+ |
* | TagCache RAM DB x==\(W) +-----------------+ |
* +-x----x---x---x--+ \===x | |
* +-----------------+ \===x | |
* | | | | (R) | Ram DB Loader x============x DirCache
* +-x----x---x---x---+ /==x | | (optional)
* | Tagcache Disk DB x==/ +-----------------+ |
@ -191,6 +191,10 @@ static int total_entry_count = 0;
static int data_size = 0;
static int processed_dir_count;
/* Thread safe locking */
static volatile int write_lock;
static volatile int read_lock;
int tagcache_str_to_tag(const char *str)
{
int i;
@ -516,6 +520,7 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
sizeof(struct index_entry))
{
logf("write error #3");
logf("idxid: %d", idxid);
return false;
}
@ -818,9 +823,12 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
struct master_header master_hdr;
int i;
if (tcs->valid)
if (tcs->initialized)
tagcache_search_finish(tcs);
while (read_lock)
sleep(1);
memset(tcs, 0, sizeof(struct tagcache_search));
if (stat.commit_step > 0 || !stat.ready)
return false;
@ -830,7 +838,6 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
tcs->seek_pos = 0;
tcs->seek_list_count = 0;
tcs->filter_count = 0;
tcs->valid = true;
tcs->masterfd = -1;
for (i = 0; i < TAG_COUNT; i++)
@ -848,18 +855,28 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
#endif
{
if (tagcache_is_numeric_tag(tcs->type))
{
tcs->valid = true;
tcs->initialized = true;
return true;
}
tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false);
if (tcs->idxfd[tcs->type] < 0)
return false;
tcs->masterfd = open_master_fd(&master_hdr, false);
/* 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;
tcs->initialized = true;
write_lock++;
return true;
}
@ -1153,6 +1170,9 @@ void tagcache_search_finish(struct tagcache_search *tcs)
{
int i;
if (!tcs->initialized)
return;
if (tcs->masterfd >= 0)
{
close(tcs->masterfd);
@ -1170,6 +1190,9 @@ void tagcache_search_finish(struct tagcache_search *tcs)
tcs->ramsearch = false;
tcs->valid = false;
tcs->initialized = 0;
if (write_lock > 0)
write_lock--;
}
#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
@ -2076,6 +2099,9 @@ static bool commit(void)
logf("committing tagcache");
while (write_lock)
sleep(1);
tmpfd = open(TAGCACHE_FILE_TEMP, O_RDONLY);
if (tmpfd < 0)
{
@ -2103,6 +2129,8 @@ static bool commit(void)
return true;
}
read_lock++;
/* Try to steal every buffer we can :) */
if (tempbuf_size == 0)
local_allocation = true;
@ -2138,6 +2166,7 @@ static bool commit(void)
logf("delaying commit until next boot");
stat.commit_delayed = true;
close(tmpfd);
read_lock--;
return false;
}
@ -2169,6 +2198,7 @@ static bool commit(void)
else
stat.commit_delayed = true;
stat.commit_step = 0;
read_lock--;
return false;
}
}
@ -2178,8 +2208,11 @@ static bool commit(void)
/* Update the master index headers. */
if ( (masterfd = open_master_fd(&tcmh, true)) < 0)
{
read_lock--;
return false;
}
tcmh.tch.entry_count += tch.entry_count;
tcmh.tch.datasize = sizeof(struct master_header)
+ sizeof(struct index_entry) * tcmh.tch.entry_count
@ -2212,6 +2245,7 @@ static bool commit(void)
#endif
queue_post(&tagcache_queue, Q_IMPORT_CHANGELOG, 0);
read_lock--;
return true;
}
@ -2263,6 +2297,9 @@ long tagcache_increase_serial(void)
if (!stat.ready)
return -2;
while (read_lock)
sleep(1);
if (!update_current_serial(current_serial + 1))
return -1;
@ -2478,6 +2515,9 @@ bool tagcache_import_changelog(void)
if (!stat.ready)
return false;
while (read_lock)
sleep(1);
clfd = open(TAGCACHE_FILE_CHANGELOG, O_RDONLY);
if (clfd < 0)
{
@ -2491,6 +2531,8 @@ bool tagcache_import_changelog(void)
return false;
}
write_lock++;
/* Fast readline */
while ( 1 )
{
@ -2530,6 +2572,8 @@ bool tagcache_import_changelog(void)
close(clfd);
close(masterfd);
write_lock--;
update_current_serial(current_serial);
return true;
@ -2724,12 +2768,11 @@ static bool delete_entry(long idx_id)
#ifdef HAVE_TC_RAMCACHE
static bool allocate_tagcache(void)
{
struct master_header tcmh;
int fd;
/* Load the header. */
hdr = (struct ramcache_header *)(((long)audiobuf & ~0x03) + 0x04);
memset(hdr, 0, sizeof(struct ramcache_header));
if ( (fd = open_master_fd(&hdr->h, false)) < 0)
if ( (fd = open_master_fd(&tcmh, false)) < 0)
{
hdr = NULL;
return false;
@ -2737,17 +2780,17 @@ static bool allocate_tagcache(void)
close(fd);
hdr->indices = (struct index_entry *)(hdr + 1);
/**
* Now calculate the required cache size plus
* some extra space for alignment fixes.
*/
stat.ramcache_allocated = hdr->h.tch.datasize + 128 + TAGCACHE_RESERVE +
stat.ramcache_allocated = tcmh.tch.datasize + 128 + TAGCACHE_RESERVE +
sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *);
hdr = buffer_alloc(stat.ramcache_allocated + 128);
memset(hdr, 0, sizeof(struct ramcache_header));
memcpy(&hdr->h, &tcmh, sizeof(struct master_header));
hdr->indices = (struct index_entry *)(hdr + 1);
logf("tagcache: %d bytes allocated.", stat.ramcache_allocated);
logf("at: 0x%04x", audiobuf);
audiobuf += (long)((stat.ramcache_allocated & ~0x03) + 128);
return true;
}
@ -3361,6 +3404,7 @@ void tagcache_init(void)
memset(&stat, 0, sizeof(struct tagcache_stat));
filenametag_fd = -1;
current_serial = 0;
write_lock = read_lock = 0;
queue_init(&tagcache_queue);
create_thread(tagcache_thread, tagcache_stack,

View file

@ -113,6 +113,7 @@ struct tagcache_search {
long position;
int entry_count;
bool valid;
bool initialized;
/* Exported variables. */
bool ramsearch;

View file

@ -379,11 +379,17 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track)
/* Do not gather data unless proper setting has been enabled. */
if (!global_settings.runtimedb)
{
logf("runtimedb gathering not enabled");
return;
}
/* Don't process unplayed tracks. */
if (id3->elapsed == 0)
{
logf("not logging unplayed track");
return;
}
if (!tagcache_find_index(&tcs, id3->path))
{
@ -399,7 +405,11 @@ static void tagtree_unbuffer_event(struct mp3entry *id3, bool last_track)
lastplayed = tagcache_increase_serial();
if (lastplayed < 0)
{
logf("incorrect tc serial:%d", lastplayed);
tagcache_search_finish(&tcs);
return;
}
/* Ignore the last 15s (crossfade etc.) */
playtime += MIN(id3->length, id3->elapsed + 15 * 1000);

View file

@ -623,14 +623,10 @@ int dircache_build(int last_size)
return 2;
}
dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04);
if (last_size > DIRCACHE_RESERVE && last_size < DIRCACHE_LIMIT )
{
allocated_size = last_size + DIRCACHE_RESERVE;
/* We have to long align the audiobuf to keep the buffer access fast. */
audiobuf += (long)((allocated_size & ~0x03) + 0x04);
dircache_root = (struct dircache_entry *)buffer_alloc(allocated_size);
thread_enabled = true;
/* Start a transparent rebuild. */
@ -638,6 +634,8 @@ int dircache_build(int last_size)
return 3;
}
dircache_root = (struct dircache_entry *)(((long)audiobuf & ~0x03) + 0x04);
/* Start a non-transparent rebuild. */
return dircache_do_rebuild();
}
@ -672,8 +670,7 @@ void dircache_init(void)
memset(opendirs, 0, sizeof(opendirs));
for (i = 0; i < MAX_OPEN_DIRS; i++)
{
opendirs[i].secondary_entry.d_name = audiobuf;
audiobuf += MAX_PATH;
opendirs[i].secondary_entry.d_name = buffer_alloc(MAX_PATH);
}
queue_init(&dircache_queue);