Much faster optimized version of tagcache commit. Added a few items to

the debug menu (still buggy) and fixed a problem with partial tagcache
updates.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9775 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-04-23 18:47:26 +00:00
parent 3f7292e13a
commit 4142710a47
3 changed files with 252 additions and 200 deletions

View file

@ -1883,6 +1883,7 @@ static bool dbg_tagcache_info(void)
bool done = false;
int line;
char buf[32];
struct tagcache_stat *stat;
lcd_setmargins(0, 0);
lcd_setfont(FONT_SYSFIXED);
@ -1892,8 +1893,21 @@ static bool dbg_tagcache_info(void)
line = 0;
lcd_clear_display();
snprintf(buf, sizeof(buf), "Current progress: %d%%",
tagcache_get_progress());
stat = tagcache_get_stat();
snprintf(buf, sizeof(buf), "Busy: %s", stat->initialized ? "No" : "Yes");
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "RAM Cache: %s", stat->ramcache ? "Yes" : "No");
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "RAM: %d/%d B",
stat->ramcache_used, stat->ramcache_allocated);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "Progress: %d%% (%d entries)",
stat->progress, stat->processed_entries);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "Commit step: %d", stat->commit_step);
lcd_puts(0, line++, buf);
snprintf(buf, sizeof(buf), "Commit delayed: %s",
stat->commit_delayed ? "Yes" : "No");
lcd_puts(0, line++, buf);
lcd_update();

View file

@ -60,11 +60,8 @@ static const int unique_tags[] = { tag_artist, tag_album, tag_genre, tag_compose
/* Numeric tags (we can use these tags with conditional clauses). */
static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate };
/* When thread initialization and memory allocation has been made. */
static bool tagcache_init_done = false;
/* Progress indicator while committing the cache. */
static int init_step;
/* Status information of the tagcache. */
static struct tagcache_stat stat;
/* Queue commands. */
enum tagcache_queue {
@ -106,8 +103,6 @@ struct ramcache_header {
};
static struct ramcache_header *hdr;
static bool ramcache = false;
static long tagcache_size = 0;
#endif
/**
@ -120,18 +115,22 @@ struct temp_file_entry {
long data_length;
};
struct tempbuf_id {
int id;
struct tempbuf_id *next;
struct tempbuf_id_list {
long id;
struct tempbuf_id_list *next;
};
struct tempbuf_searchidx {
struct tempbuf_id *id;
long idx_id;
char *str;
int seek;
struct tempbuf_id_list idlist;
};
#define LOOKUP_BUF_DEPTH (TAGFILE_MAX_ENTRIES*2 \
* (TAGFILE_ENTRY_AVG_LENGTH/TAGFILE_ENTRY_CHUNK_LENGTH))
struct tempbuf_searchidx **lookup;
/* Used when building the temporary file. */
static int cachefd = -1, filenametag_fd;
@ -187,7 +186,7 @@ static struct index_entry *find_entry_ram(const char *filename,
int i;
/* Check if we tagcache is loaded into ram. */
if (!ramcache)
if (!stat.ramcache)
return NULL;
if (dc == NULL)
@ -579,7 +578,7 @@ 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)
if (stat.commit_step > 0)
return false;
tcs->position = sizeof(struct tagcache_header);
@ -597,7 +596,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
#ifndef HAVE_TC_RAMCACHE
tcs->ramsearch = false;
#else
tcs->ramsearch = ramcache;
tcs->ramsearch = stat.ramcache;
if (tcs->ramsearch)
{
tcs->entry_count = hdr->entry_count[tcs->type];
@ -951,7 +950,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
/* Find the corresponding entry in tagcache. */
entry = find_entry_ram(filename, NULL);
if (entry == NULL || !ramcache)
if (entry == NULL || !stat.ramcache)
return false;
id3->title = get_tag(entry, tag_title)->tag_data;
@ -1008,7 +1007,7 @@ static void add_tagcache(const char *path)
/* Check if the file is already cached. */
#ifdef HAVE_TC_RAMCACHE
if (ramcache)
if (stat.ramcache)
{
if (find_entry_ram(path, dc))
return ;
@ -1115,33 +1114,58 @@ static void remove_files(void)
}
}
static bool tempbuf_insert(char *str, int id, int idx_id)
static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
{
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
int len = strlen(str)+1;
int i;
unsigned crc32;
unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4];
char buf[MAX_PATH];
for (i = 0; str[i] != '\0' && i < (int)sizeof(buf)-1; i++)
buf[i] = tolower(str[i]);
buf[i] = '\0';
crc32 = crc_32(buf, i, 0xffffffff);
if (unique)
{
/* Check if the crc does not exist -> entry does not exist for sure. */
for (i = 0; i < tempbufidx; i++)
{
if (crcbuf[-i] != crc32)
continue;
if (!strcasecmp(str, index[i].str))
{
if (id >= 0 && id < LOOKUP_BUF_DEPTH)
lookup[id] = &index[i];
return true;
}
}
}
/* Insert to CRC buffer. */
crcbuf[-tempbufidx] = crc32;
tempbuf_left -= 4;
/* Insert it to the buffer. */
tempbuf_left -= len + sizeof(struct tempbuf_id);
tempbuf_left -= len;
if (tempbuf_left - 4 < 0 || tempbufidx >= TAGFILE_MAX_ENTRIES-1)
return false;
index[tempbufidx].id = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
#ifdef TAGCACHE_STRICT_ALIGN
/* Make sure the entry is long aligned. */
if ((long)index[tempbufidx].id & 0x03)
if (id >= 0 && id < LOOKUP_BUF_DEPTH)
{
int fix = 4 - ((long)index[tempbufidx].id & 0x03);
tempbuf_left -= fix;
tempbuf_pos += fix;
index[tempbufidx].id = (struct tempbuf_id *)((
(long)index[tempbufidx].id & ~0x03) + 0x04);
lookup[id] = &index[tempbufidx];
index[tempbufidx].idlist.id = id;
}
#endif
index[tempbufidx].id->id = id;
index[tempbufidx].id->next = NULL;
index[tempbufidx].idx_id = idx_id;
tempbuf_pos += sizeof(struct tempbuf_id);
else
index[tempbufidx].idlist.id = -1;
index[tempbufidx].idlist.next = NULL;
index[tempbufidx].idx_id = idx_id;
index[tempbufidx].seek = -1;
index[tempbufidx].str = &tempbuf[tempbuf_pos];
memcpy(index[tempbufidx].str, str, len);
@ -1151,59 +1175,6 @@ static bool tempbuf_insert(char *str, int id, int idx_id)
return true;
}
static bool tempbuf_unique_insert(char *str, int id)
{
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
struct tempbuf_id *idp;
int i;
unsigned crc32;
unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4];
crc32 = crc_32(str, strlen(str), 0xffffffff);
/* Check if the crc does not exist -> entry does not exist for sure. */
for (i = 0; i < tempbufidx; i++)
{
if (*(crcbuf--) == crc32)
{
if (!strcasecmp(str, index[i].str))
{
tempbuf_left -= sizeof(struct tempbuf_id);
if (tempbuf_left - 4 < 0)
return false;
idp = index[i].id;
while (idp->next != NULL)
idp = idp->next;
idp->next = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
#if TAGCACHE_STRICT_ALIGN
/* Make sure the entry is long aligned. */
if ((long)idp->next & 0x03)
{
int fix = 4 - ((long)idp->next & 0x03);
tempbuf_left -= fix;
tempbuf_pos += fix;
idp->next = (struct tempbuf_id *)
(((long)idp->next & ~0x03) + 0x04);
}
#endif
idp = idp->next;
idp->id = id;
idp->next = NULL;
tempbuf_pos += sizeof(struct tempbuf_id);
return true;
}
}
}
/* Insert and quit. */
*crcbuf = crc32;
tempbuf_left -= 4;
return tempbuf_insert(str, id, -1);
}
static int compare(const void *p1, const void *p2)
{
struct tempbuf_searchidx *e1 = (struct tempbuf_searchidx *)p1;
@ -1225,19 +1196,69 @@ static int tempbuf_sort(int fd)
struct tagfile_entry fe;
int i;
int length;
#ifdef TAGCACHE_STRICT_ALIGN
int fix;
#endif
/* Generate reverse lookup entries. */
for (i = 0; i < LOOKUP_BUF_DEPTH; i++)
{
struct tempbuf_id_list *idlist;
if (!lookup[i])
continue;
if (lookup[i]->idlist.id == i)
continue;
idlist = &lookup[i]->idlist;
while (idlist->next != NULL)
idlist = idlist->next;
tempbuf_left -= sizeof(struct tempbuf_id_list);
if (tempbuf_left - 4 < 0)
return -1;
idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos];
if (tempbuf_pos & 0x03)
{
tempbuf_pos = (tempbuf_pos & ~0x03) + 0x04;
tempbuf_left -= 3;
idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos];
}
tempbuf_pos += sizeof(struct tempbuf_id_list);
idlist = idlist->next;
idlist->id = i;
idlist->next = NULL;
}
qsort(index, tempbufidx, sizeof(struct tempbuf_searchidx), compare);
memset(lookup, 0, LOOKUP_BUF_DEPTH * sizeof(struct tempbuf_searchidx **));
for (i = 0; i < tempbufidx; i++)
{
struct tempbuf_id_list *idlist = &index[i].idlist;
/* Fix the lookup list. */
while (idlist != NULL)
{
if (idlist->id >= 0)
lookup[idlist->id] = &index[i];
idlist = idlist->next;
}
index[i].seek = lseek(fd, 0, SEEK_CUR);
length = strlen(index[i].str) + 1;
fe.tag_length = length;
fe.idx_id = index[i].idx_id;
/* Check the chunk alignment. */
if ((fe.tag_length + sizeof(struct tagfile_entry))
% TAGFILE_ENTRY_CHUNK_LENGTH)
{
fe.tag_length += TAGFILE_ENTRY_CHUNK_LENGTH -
((fe.tag_length + sizeof(struct tagfile_entry))
% TAGFILE_ENTRY_CHUNK_LENGTH);
}
#ifdef TAGCACHE_STRICT_ALIGN
/* Make sure the entry is long aligned. */
if (index[i].seek & 0x03)
@ -1245,12 +1266,6 @@ static int tempbuf_sort(int fd)
logf("tempbuf_sort: alignment error!");
return -3;
}
fix = (sizeof(struct tagfile_entry) + length) & 0x03;
if (fix)
fix = 4-fix;
fe.tag_length += fix;
#endif
if (write(fd, &fe, sizeof(struct tagfile_entry)) !=
@ -1266,11 +1281,9 @@ static int tempbuf_sort(int fd)
return -2;
}
#ifdef TAGCACHE_STRICT_ALIGN
/* Write some padding. */
if (fix)
write(fd, "XXX", fix);
#endif
if (fe.tag_length - length > 0)
write(fd, "XXXXXXXX", fe.tag_length - length);
}
return i;
@ -1278,33 +1291,10 @@ static int tempbuf_sort(int fd)
inline static struct tempbuf_searchidx* tempbuf_locate(int id)
{
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
struct tempbuf_id *idp;
static int last_id = 0;
int i;
try_again:
if (last_id >= tempbufidx)
last_id = 0;
/* Check if string already exists. */
/* FIXME: This check is extremely slow, O(n^2) */
for (i = last_id; i < tempbufidx; i++)
{
idp = index[i].id;
while (idp != NULL)
{
if (idp->id == id)
return &index[i];
idp = idp->next;
}
}
if (last_id)
goto try_again;
if (id < 0 || id >= LOOKUP_BUF_DEPTH)
return NULL;
return lookup[id];
}
@ -1415,7 +1405,13 @@ static bool build_numeric_index(int index_type, struct tagcache_header *h, int t
return true;
}
static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
/**
* Return values:
* > 0 success
* == 0 temporary failure
* < 0 fatal error
*/
static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
{
int i;
struct tagcache_header tch;
@ -1431,13 +1427,18 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
tempbufidx = 0;
tempbuf_pos = TAGFILE_MAX_ENTRIES * sizeof(struct tempbuf_searchidx);
tempbuf_left = tempbuf_size - tempbuf_pos;
if (tempbuf_left < 0)
memset(tempbuf+tempbuf_pos, 0, LOOKUP_BUF_DEPTH * sizeof(void **));
tempbuf_pos += LOOKUP_BUF_DEPTH * sizeof(void **);
tempbuf_left = tempbuf_size - tempbuf_pos - 8;
if (tempbuf_left - TAGFILE_ENTRY_AVG_LENGTH * TAGFILE_MAX_ENTRIES < 0)
{
logf("Buffer way too small!");
return false;
return 0;
}
lookup = (struct tempbuf_searchidx **)
(tempbuf + sizeof(struct tempbuf_searchidx)*TAGFILE_MAX_ENTRIES);
/* Open the index file, which contains the tag names. */
snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, index_type);
fd = open(buf, O_RDWR);
@ -1450,7 +1451,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
{
logf("header error");
close(fd);
return false;
return -2;
}
/**
@ -1471,21 +1472,21 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
{
logf("read error");
close(fd);
return false;
return -2;
}
if (entry.tag_length >= (int)sizeof(buf))
{
logf("too long tag");
close(fd);
return false;
return -2;
}
if (read(fd, buf, entry.tag_length) != entry.tag_length)
{
logf("read error #2");
close(fd);
return false;
return -2;
}
/**
@ -1493,7 +1494,8 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
* is saved so we can later reindex the master lookup
* table when the index gets resorted.
*/
tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id);
tempbuf_insert(buf, loc/TAGFILE_ENTRY_CHUNK_LENGTH
+ TAGFILE_MAX_ENTRIES, entry.idx_id, false);
yield();
}
logf("done");
@ -1511,7 +1513,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
if (fd < 0)
{
logf("%s open fail", buf);
return false;
return -2;
}
tch.magic = TAGCACHE_MAGIC;
@ -1523,7 +1525,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
{
logf("header write failed");
close(fd);
return false;
return -2;
}
}
@ -1540,7 +1542,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
{
logf("Failure to create index file");
close(fd);
return false;
return -2;
}
/* Write the header (write real values later). */
@ -1565,7 +1567,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
logf("header error");
close(fd);
close(masterfd);
return false;
return -2;
}
/**
@ -1623,9 +1625,9 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
}
if (tagcache_is_unique_tag(index_type))
error = !tempbuf_unique_insert(buf, i);
error = !tempbuf_insert(buf, i, -1, true);
else
error = !tempbuf_insert(buf, i, tch.entry_count + i);
error = !tempbuf_insert(buf, i, tch.entry_count + i, false);
if (error)
{
@ -1671,7 +1673,8 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
for (j = 0; j < idxbuf_pos; j++)
{
idxbuf[j].tag_seek[index_type] = tempbuf_find_location(
idxbuf[j].tag_seek[index_type]+TAGFILE_MAX_ENTRIES);
idxbuf[j].tag_seek[index_type]/TAGFILE_ENTRY_CHUNK_LENGTH
+ TAGFILE_MAX_ENTRIES);
if (idxbuf[j].tag_seek[index_type] < 0)
{
@ -1679,6 +1682,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
error = true;
goto error_exit;
}
yield();
}
@ -1800,30 +1804,24 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
}
logf("done");
/* Finally write the uniqued tag index file. */
if (tagcache_is_sorted_tag(index_type))
{
/* Finally write the header. */
tch.magic = TAGCACHE_MAGIC;
tch.entry_count = tempbufidx;
tch.datasize = lseek(fd, 0, SEEK_END) - sizeof(struct tagcache_header);
lseek(fd, 0, SEEK_SET);
write(fd, &tch, sizeof(struct tagcache_header));
}
else
{
tch.magic = TAGCACHE_MAGIC;
tch.entry_count = tempbufidx;
tch.datasize = lseek(fd, 0, SEEK_CUR) - sizeof(struct tagcache_header);
lseek(fd, 0, SEEK_SET);
write(fd, &tch, sizeof(struct tagcache_header));
}
if (index_type != tag_filename)
h->datasize += tch.datasize;
error_exit:
close(fd);
close(masterfd);
return !error;
if (error)
return -2;
return 1;
}
static bool commit(void)
@ -1865,11 +1863,11 @@ static bool commit(void)
/* Try to steal every buffer we can :) */
#ifdef HAVE_TC_RAMCACHE
if (tempbuf_size == 0 && tagcache_size > 0)
if (tempbuf_size == 0 && stat.ramcache_allocated > 0)
{
ramcache = false;
stat.ramcache = false;
tempbuf = (char *)(hdr + 1);
tempbuf_size = tagcache_size - sizeof(struct ramcache_header);
tempbuf_size = stat.ramcache_allocated - sizeof(struct ramcache_header);
}
#endif
@ -1885,6 +1883,7 @@ static bool commit(void)
if (tempbuf_size == 0)
{
logf("delaying commit until next boot");
stat.commit_delayed = true;
close(tmpfd);
return false;
}
@ -1892,26 +1891,36 @@ static bool commit(void)
logf("commit %d entries...", header.entry_count);
/* Now create the index files. */
init_step = 0;
stat.commit_step = 0;
header.datasize = 0;
stat.commit_delayed = false;
for (i = 0; i < TAG_COUNT; i++)
{
init_step++;
int ret;
stat.commit_step++;
if (tagcache_is_numeric_tag(i))
{
build_numeric_index(i, &header, tmpfd);
continue;
}
else if (!build_index(i, &header, tmpfd))
ret = build_index(i, &header, tmpfd);
if (ret <= 0)
{
logf("tagcache failed init");
if (ret < 0)
remove_files();
init_step = 0;
else
stat.commit_delayed = true;
stat.commit_step = 0;
return false;
}
}
close(tmpfd);
init_step = 0;
stat.commit_step = 0;
/* Update the master index headers. */
masterfd = open(TAGCACHE_FILE_MASTER, O_RDWR);
@ -1932,7 +1941,8 @@ static bool commit(void)
}
header.entry_count += header_old.entry_count;
header.datasize += header_old.datasize;
/* Datasize has been recalculated. */
// header.datasize += header_old.datasize;
lseek(masterfd, 0, SEEK_SET);
write(masterfd, &header, sizeof(struct tagcache_header));
@ -1948,7 +1958,7 @@ static bool commit(void)
#ifdef HAVE_TC_RAMCACHE
/* Reload tagcache. */
if (tagcache_size > 0 && !ramcache)
if (stat.ramcache_allocated > 0 && !stat.ramcache)
tagcache_start_scan();
#endif
@ -2009,12 +2019,12 @@ 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_RESERVE +
stat.ramcache_allocated = 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);
logf("tagcache: %d bytes allocated.", stat.ramcache_allocated);
logf("at: 0x%04x", audiobuf);
audiobuf += (long)((tagcache_size & ~0x03) + 0x04);
audiobuf += (long)((stat.ramcache_allocated & ~0x03) + 0x04);
return true;
}
@ -2022,7 +2032,7 @@ static bool allocate_tagcache(void)
static bool load_tagcache(void)
{
struct tagcache_header *tch;
long bytesleft = tagcache_size;
long bytesleft = stat.ramcache_allocated;
struct index_entry *idx;
int rc, fd;
char *p;
@ -2065,7 +2075,7 @@ static bool load_tagcache(void)
}
bytesleft -= sizeof(struct index_entry);
if (bytesleft < 0 || ((long)idx - (long)hdr->indices) >= tagcache_size)
if (bytesleft < 0 || ((long)idx - (long)hdr->indices) >= stat.ramcache_allocated)
{
logf("too big tagcache.");
close(fd);
@ -2189,6 +2199,7 @@ static bool load_tagcache(void)
close(fd);
}
stat.ramcache_used = stat.ramcache_allocated - bytesleft;
logf("tagcache loaded into ram!");
return true;
@ -2341,9 +2352,9 @@ static void load_ramcache(void)
cpu_boost(true);
/* At first we should load the cache (if exists). */
ramcache = load_tagcache();
stat.ramcache = load_tagcache();
if (!ramcache)
if (!stat.ramcache)
{
hdr = NULL;
remove_files();
@ -2364,9 +2375,16 @@ static void tagcache_thread(void)
allocate_tempbuf();
commit();
free_tempbuf();
#ifdef HAVE_TC_RAMCACHE
/* Allocate space for the tagcache if found on disk. */
if (global_settings.tagcache_ram)
allocate_tagcache();
#endif
cpu_boost(false);
tagcache_init_done = true;
stat.initialized = true;
while (1)
{
@ -2388,10 +2406,10 @@ static void tagcache_thread(void)
if (check_done || !dircache_is_enabled())
break ;
if (!ramcache && global_settings.tagcache_ram)
if (!stat.ramcache && global_settings.tagcache_ram)
load_ramcache();
if (ramcache)
if (stat.ramcache)
build_tagcache();
check_done = true;
@ -2415,7 +2433,7 @@ static void tagcache_thread(void)
}
}
int tagcache_get_progress(void)
static int get_progress(void)
{
int total_count = -1;
@ -2426,7 +2444,7 @@ int tagcache_get_progress(void)
}
else
{
if (hdr && ramcache)
if (hdr && stat.ramcache)
total_count = hdr->h.entry_count;
}
#endif
@ -2437,9 +2455,12 @@ int tagcache_get_progress(void)
return processed_dir_count * 100 / total_count;
}
int tagcache_get_processes_entrycount(void)
struct tagcache_stat* tagcache_get_stat(void)
{
return processed_dir_count;
stat.progress = get_progress();
stat.processed_entries = processed_dir_count;
return &stat;
}
void tagcache_start_scan(void)
@ -2463,19 +2484,15 @@ void tagcache_stop_scan(void)
#ifdef HAVE_TC_RAMCACHE
bool tagcache_is_ramcache(void)
{
return ramcache;
return stat.ramcache;
}
#endif
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
stat.initialized = false;
stat.commit_step = 0;
queue_init(&tagcache_queue);
create_thread(tagcache_thread, tagcache_stack,
@ -2484,11 +2501,11 @@ void tagcache_init(void)
bool tagcache_is_initialized(void)
{
return tagcache_init_done;
return stat.initialized;
}
int tagcache_get_commit_step(void)
{
return init_step;
return stat.commit_step;
}

View file

@ -38,13 +38,22 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
#define IDX_BUF_DEPTH 64
/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
#define TAGCACHE_MAGIC 0x54434803
#define TAGCACHE_MAGIC 0x54434804
/* How much to allocate extra space for ramcache. */
#define TAGCACHE_RESERVE 32768
/* How many entries we can create in one tag file (for sorting). */
#define TAGFILE_MAX_ENTRIES 20000
#define TAGFILE_MAX_ENTRIES 10000
/**
* Define how long one entry must be at least (longer -> less memory at commit).
* Must be at least 4 bytes in length for correct alignment.
*/
#define TAGFILE_ENTRY_CHUNK_LENGTH 8
/* Used to guess the necessary buffer size at commit. */
#define TAGFILE_ENTRY_AVG_LENGTH 16
/* How many entries to fetch to the seek table at once while searching. */
#define SEEK_LIST_SIZE 50
@ -67,6 +76,17 @@ enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
enum modifiers { clause_mod_none, clause_mod_not };
struct tagcache_stat {
bool initialized; /* Is tagcache currently busy? */
bool ramcache; /* Is tagcache loaded in ram? */
bool commit_delayed; /* Has commit been delayed until next reboot? */
int commit_step; /* Commit progress */
int ramcache_allocated; /* Has ram been allocated for ramcache? */
int ramcache_used; /* How much ram has been really used */
int progress; /* Current progress of disk scan */
int processed_entries; /* Scanned disk entries so far */
};
struct tagcache_search_clause
{
int tag;
@ -116,14 +136,15 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
void tagcache_search_finish(struct tagcache_search *tcs);
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);
int tagcache_get_progress(void);
struct tagcache_stat* tagcache_get_stat(void);
int tagcache_get_commit_step(void);
#ifdef HAVE_TC_RAMCACHE
bool tagcache_is_ramcache(void);
bool tagcache_fill_tags(struct mp3entry *id3, const char *filename);
#endif
void tagcache_init(void);
bool tagcache_is_initialized(void);
int tagcache_get_commit_step(void);
void tagcache_start_scan(void);
void tagcache_stop_scan(void);
bool tagcache_force_update(void);