Performance optimizations for tagcache commit. Still more left to be done.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9721 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
2b18727a8a
commit
fa893c6b88
5 changed files with 282 additions and 126 deletions
301
apps/tagcache.c
301
apps/tagcache.c
|
@ -33,6 +33,7 @@
|
||||||
#include "tagcache.h"
|
#include "tagcache.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "atoi.h"
|
#include "atoi.h"
|
||||||
|
#include "crc32.h"
|
||||||
|
|
||||||
/* Tag Cache thread. */
|
/* Tag Cache thread. */
|
||||||
static struct event_queue tagcache_queue;
|
static struct event_queue tagcache_queue;
|
||||||
|
@ -66,19 +67,12 @@ static bool tagcache_init_done = false;
|
||||||
static int init_step;
|
static int init_step;
|
||||||
|
|
||||||
/* Queue commands. */
|
/* Queue commands. */
|
||||||
#define Q_STOP_SCAN 0
|
enum tagcache_queue {
|
||||||
#define Q_START_SCAN 1
|
Q_STOP_SCAN = 0,
|
||||||
#define Q_FORCE_UPDATE 2
|
Q_START_SCAN,
|
||||||
|
Q_FORCE_UPDATE,
|
||||||
|
};
|
||||||
|
|
||||||
/* Tag database files. */
|
|
||||||
#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
|
|
||||||
#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
|
|
||||||
#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
|
|
||||||
|
|
||||||
/* Tag Cache Header version 'TCHxx' */
|
|
||||||
#define TAGCACHE_MAGIC 0x54434802
|
|
||||||
|
|
||||||
#define TAGCACHE_RESERVE 32768
|
|
||||||
|
|
||||||
/* Tag database structures. */
|
/* Tag database structures. */
|
||||||
|
|
||||||
|
@ -92,6 +86,7 @@ struct tagfile_entry {
|
||||||
/* Fixed-size tag entry in master db index. */
|
/* Fixed-size tag entry in master db index. */
|
||||||
struct index_entry {
|
struct index_entry {
|
||||||
long tag_seek[TAG_COUNT];
|
long tag_seek[TAG_COUNT];
|
||||||
|
long flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Header is the same in every file. */
|
/* Header is the same in every file. */
|
||||||
|
@ -868,6 +863,19 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
|
static bool tagcache_delete(const char *filename)
|
||||||
|
{
|
||||||
|
struct index_entry *entry;
|
||||||
|
|
||||||
|
entry = find_entry_disk(filename, true);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
logf("not found: %s", filename);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void tagcache_modify(struct tagcache_search *tcs, int type, const char *text)
|
void tagcache_modify(struct tagcache_search *tcs, int type, const char *text)
|
||||||
{
|
{
|
||||||
struct tagentry *entry;
|
struct tagentry *entry;
|
||||||
|
@ -1111,7 +1119,7 @@ static bool tempbuf_insert(char *str, int id, int idx_id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
index[tempbufidx].id = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
|
index[tempbufidx].id = (struct tempbuf_id *)&tempbuf[tempbuf_pos];
|
||||||
#ifdef ROCKBOX_STRICT_ALIGN
|
#ifdef TAGCACHE_STRICT_ALIGN
|
||||||
/* Make sure the entry is long aligned. */
|
/* Make sure the entry is long aligned. */
|
||||||
if ((long)index[tempbufidx].id & 0x03)
|
if ((long)index[tempbufidx].id & 0x03)
|
||||||
{
|
{
|
||||||
|
@ -1141,41 +1149,51 @@ static bool tempbuf_unique_insert(char *str, int id)
|
||||||
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
|
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
|
||||||
struct tempbuf_id *idp;
|
struct tempbuf_id *idp;
|
||||||
int i;
|
int i;
|
||||||
|
unsigned crc32;
|
||||||
|
unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4];
|
||||||
|
|
||||||
/* Check if string already exists. */
|
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++)
|
for (i = 0; i < tempbufidx; i++)
|
||||||
{
|
{
|
||||||
if (!strcasecmp(str, index[i].str))
|
if (*(crcbuf--) == crc32)
|
||||||
{
|
{
|
||||||
tempbuf_left -= sizeof(struct tempbuf_id);
|
if (!strcasecmp(str, index[i].str))
|
||||||
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];
|
|
||||||
#ifdef ROCKBOX_STRICT_ALIGN
|
|
||||||
/* Make sure the entry is long aligned. */
|
|
||||||
if ((long)idp->next & 0x03)
|
|
||||||
{
|
{
|
||||||
int fix = 4 - ((long)idp->next & 0x03);
|
tempbuf_left -= sizeof(struct tempbuf_id);
|
||||||
tempbuf_left -= fix;
|
if (tempbuf_left - 4 < 0)
|
||||||
tempbuf_pos += fix;
|
return false;
|
||||||
idp->next = (struct tempbuf_id *)((
|
|
||||||
(long)idp->next & ~0x03) + 0x04);
|
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
|
#endif
|
||||||
idp = idp->next;
|
idp = idp->next;
|
||||||
idp->id = id;
|
idp->id = id;
|
||||||
idp->next = NULL;
|
idp->next = NULL;
|
||||||
tempbuf_pos += sizeof(struct tempbuf_id);
|
tempbuf_pos += sizeof(struct tempbuf_id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Insert and quit. */
|
||||||
|
*crcbuf = crc32;
|
||||||
|
tempbuf_left -= 4;
|
||||||
return tempbuf_insert(str, id, -1);
|
return tempbuf_insert(str, id, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1200,7 +1218,7 @@ static int tempbuf_sort(int fd)
|
||||||
struct tagfile_entry fe;
|
struct tagfile_entry fe;
|
||||||
int i;
|
int i;
|
||||||
int length;
|
int length;
|
||||||
#ifdef ROCKBOX_STRICT_ALIGN
|
#ifdef TAGCACHE_STRICT_ALIGN
|
||||||
int fix;
|
int fix;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1213,7 +1231,7 @@ static int tempbuf_sort(int fd)
|
||||||
fe.tag_length = length;
|
fe.tag_length = length;
|
||||||
fe.idx_id = index[i].idx_id;
|
fe.idx_id = index[i].idx_id;
|
||||||
|
|
||||||
#ifdef ROCKBOX_STRICT_ALIGN
|
#ifdef TAGCACHE_STRICT_ALIGN
|
||||||
/* Make sure the entry is long aligned. */
|
/* Make sure the entry is long aligned. */
|
||||||
if (index[i].seek & 0x03)
|
if (index[i].seek & 0x03)
|
||||||
{
|
{
|
||||||
|
@ -1241,7 +1259,7 @@ static int tempbuf_sort(int fd)
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ROCKBOX_STRICT_ALIGN
|
#ifdef TAGCACHE_STRICT_ALIGN
|
||||||
/* Write some padding. */
|
/* Write some padding. */
|
||||||
if (fix)
|
if (fix)
|
||||||
write(fd, "XXX", fix);
|
write(fd, "XXX", fix);
|
||||||
|
@ -1251,15 +1269,21 @@ static int tempbuf_sort(int fd)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static struct tempbuf_searchidx* tempbuf_locate(int id)
|
||||||
static struct tempbuf_searchidx* tempbuf_locate(int id)
|
|
||||||
{
|
{
|
||||||
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
|
struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf;
|
||||||
struct tempbuf_id *idp;
|
struct tempbuf_id *idp;
|
||||||
|
static int last_id = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
try_again:
|
||||||
|
|
||||||
|
if (last_id >= tempbufidx)
|
||||||
|
last_id = 0;
|
||||||
|
|
||||||
/* Check if string already exists. */
|
/* Check if string already exists. */
|
||||||
for (i = 0; i < tempbufidx; i++)
|
/* FIXME: This check is extremely slow, O(n^2) */
|
||||||
|
for (i = last_id; i < tempbufidx; i++)
|
||||||
{
|
{
|
||||||
idp = index[i].id;
|
idp = index[i].id;
|
||||||
while (idp != NULL)
|
while (idp != NULL)
|
||||||
|
@ -1270,11 +1294,14 @@ static struct tempbuf_searchidx* tempbuf_locate(int id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (last_id)
|
||||||
|
goto try_again;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int tempbuf_find_location(int id)
|
inline static int tempbuf_find_location(int id)
|
||||||
{
|
{
|
||||||
struct tempbuf_searchidx *entry;
|
struct tempbuf_searchidx *entry;
|
||||||
|
|
||||||
|
@ -1380,12 +1407,13 @@ static bool build_numeric_index(int index_type, struct tagcache_header *h, int t
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct tagcache_header tch;
|
struct tagcache_header tch;
|
||||||
struct index_entry idx;
|
struct index_entry idxbuf[IDX_BUF_DEPTH];
|
||||||
|
int idxbuf_pos;
|
||||||
char buf[MAX_PATH];
|
char buf[MAX_PATH];
|
||||||
int fd = -1, masterfd;
|
int fd = -1, masterfd;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
@ -1425,6 +1453,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
*/
|
*/
|
||||||
if (tagcache_is_sorted_tag(index_type))
|
if (tagcache_is_sorted_tag(index_type))
|
||||||
{
|
{
|
||||||
|
logf("loading tags...");
|
||||||
for (i = 0; i < tch.entry_count; i++)
|
for (i = 0; i < tch.entry_count; i++)
|
||||||
{
|
{
|
||||||
struct tagfile_entry entry;
|
struct tagfile_entry entry;
|
||||||
|
@ -1460,6 +1489,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id);
|
tempbuf_insert(buf, loc + TAGFILE_MAX_ENTRIES, entry.idx_id);
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
logf("done");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
tempbufidx = tch.entry_count;
|
tempbufidx = tch.entry_count;
|
||||||
|
@ -1555,6 +1585,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
{
|
{
|
||||||
lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
|
lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
|
||||||
/* h is the header of the temporary file containing new tags. */
|
/* h is the header of the temporary file containing new tags. */
|
||||||
|
logf("inserting new tags...");
|
||||||
for (i = 0; i < h->entry_count; i++)
|
for (i = 0; i < h->entry_count; i++)
|
||||||
{
|
{
|
||||||
struct temp_file_entry entry;
|
struct temp_file_entry entry;
|
||||||
|
@ -1600,6 +1631,7 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
entry.tag_length[index_type], SEEK_CUR);
|
entry.tag_length[index_type], SEEK_CUR);
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
logf("done");
|
||||||
|
|
||||||
/* Sort the buffer data and write it to the index file. */
|
/* Sort the buffer data and write it to the index file. */
|
||||||
lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
|
lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
|
||||||
|
@ -1611,128 +1643,146 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
/**
|
/**
|
||||||
* Now update all indexes in the master lookup file.
|
* Now update all indexes in the master lookup file.
|
||||||
*/
|
*/
|
||||||
|
logf("updating indices...");
|
||||||
lseek(masterfd, sizeof(struct tagcache_header), SEEK_SET);
|
lseek(masterfd, sizeof(struct tagcache_header), SEEK_SET);
|
||||||
for (i = 0; i < tch.entry_count; i++)
|
for (i = 0; i < tch.entry_count; i += idxbuf_pos)
|
||||||
{
|
{
|
||||||
|
int j;
|
||||||
int loc = lseek(masterfd, 0, SEEK_CUR);
|
int loc = lseek(masterfd, 0, SEEK_CUR);
|
||||||
|
|
||||||
if (read(masterfd, &idx, sizeof(struct index_entry)) !=
|
idxbuf_pos = MIN(tch.entry_count - i, IDX_BUF_DEPTH);
|
||||||
sizeof(struct index_entry))
|
|
||||||
|
if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||||
|
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||||
{
|
{
|
||||||
logf("read fail #2");
|
logf("read fail #2");
|
||||||
error = true;
|
error = true;
|
||||||
goto error_exit ;
|
goto error_exit ;
|
||||||
}
|
}
|
||||||
idx.tag_seek[index_type] = tempbuf_find_location(
|
|
||||||
idx.tag_seek[index_type]+TAGFILE_MAX_ENTRIES);
|
|
||||||
if (idx.tag_seek[index_type] < 0)
|
|
||||||
{
|
|
||||||
logf("update error: %d/%d", i, tch.entry_count);
|
|
||||||
error = true;
|
|
||||||
goto error_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write back the updated index. */
|
|
||||||
lseek(masterfd, loc, SEEK_SET);
|
lseek(masterfd, loc, SEEK_SET);
|
||||||
if (write(masterfd, &idx, sizeof(struct index_entry)) !=
|
|
||||||
sizeof(struct index_entry))
|
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);
|
||||||
|
|
||||||
|
if (idxbuf[j].tag_seek[index_type] < 0)
|
||||||
|
{
|
||||||
|
logf("update error: %d/%d", i+j, tch.entry_count);
|
||||||
|
error = true;
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write back the updated index. */
|
||||||
|
if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||||
|
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||||
{
|
{
|
||||||
logf("write fail");
|
logf("write fail");
|
||||||
error = true;
|
error = true;
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
yield();
|
|
||||||
}
|
}
|
||||||
|
logf("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Walk through the temporary file containing the new tags.
|
* Walk through the temporary file containing the new tags.
|
||||||
*/
|
*/
|
||||||
// build_normal_index(h, tmpfd, masterfd, idx);
|
// build_normal_index(h, tmpfd, masterfd, idx);
|
||||||
|
logf("updating new indices...");
|
||||||
lseek(masterfd, masterfd_pos, SEEK_SET);
|
lseek(masterfd, masterfd_pos, SEEK_SET);
|
||||||
lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
|
lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
|
||||||
lseek(fd, 0, SEEK_END);
|
lseek(fd, 0, SEEK_END);
|
||||||
for (i = 0; i < h->entry_count; i++)
|
for (i = 0; i < h->entry_count; i += idxbuf_pos)
|
||||||
{
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
idxbuf_pos = MIN(h->entry_count - i, IDX_BUF_DEPTH);
|
||||||
if (init)
|
if (init)
|
||||||
{
|
{
|
||||||
memset(&idx, 0, sizeof(struct index_entry));
|
memset(idxbuf, 0, sizeof(struct index_entry)*IDX_BUF_DEPTH);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (read(masterfd, &idx, sizeof(struct index_entry)) !=
|
int loc = lseek(masterfd, 0, SEEK_CUR);
|
||||||
sizeof(struct index_entry))
|
|
||||||
|
if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||||
|
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||||
{
|
{
|
||||||
logf("read fail #2");
|
logf("read fail #2");
|
||||||
error = true;
|
error = true;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
lseek(masterfd, -sizeof(struct index_entry), SEEK_CUR);
|
lseek(masterfd, loc, SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read entry headers. */
|
/* Read entry headers. */
|
||||||
if (!tagcache_is_sorted_tag(index_type))
|
for (j = 0; j < idxbuf_pos; j++)
|
||||||
{
|
{
|
||||||
struct temp_file_entry entry;
|
if (!tagcache_is_sorted_tag(index_type))
|
||||||
struct tagfile_entry fe;
|
|
||||||
|
|
||||||
if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
|
|
||||||
sizeof(struct temp_file_entry))
|
|
||||||
{
|
{
|
||||||
logf("read fail #1");
|
struct temp_file_entry entry;
|
||||||
error = true;
|
struct tagfile_entry fe;
|
||||||
break ;
|
|
||||||
|
if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
|
||||||
|
sizeof(struct temp_file_entry))
|
||||||
|
{
|
||||||
|
logf("read fail #1");
|
||||||
|
error = true;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read data. */
|
||||||
|
if (entry.tag_length[index_type] >= (int)sizeof(buf))
|
||||||
|
{
|
||||||
|
logf("too long entry!");
|
||||||
|
logf("length=%d", entry.tag_length[index_type]);
|
||||||
|
logf("pos=0x%02x", lseek(tmpfd, 0, SEEK_CUR));
|
||||||
|
error = true;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR);
|
||||||
|
if (read(tmpfd, buf, entry.tag_length[index_type]) !=
|
||||||
|
entry.tag_length[index_type])
|
||||||
|
{
|
||||||
|
logf("read fail #3");
|
||||||
|
logf("offset=0x%02x", entry.tag_offset[index_type]);
|
||||||
|
logf("length=0x%02x", entry.tag_length[index_type]);
|
||||||
|
error = true;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write to index file. */
|
||||||
|
idxbuf[j].tag_seek[index_type] = lseek(fd, 0, SEEK_CUR);
|
||||||
|
fe.tag_length = entry.tag_length[index_type];
|
||||||
|
fe.idx_id = tch.entry_count + i + j;
|
||||||
|
write(fd, &fe, sizeof(struct tagfile_entry));
|
||||||
|
write(fd, buf, fe.tag_length);
|
||||||
|
tempbufidx++;
|
||||||
|
|
||||||
|
/* Skip to next. */
|
||||||
|
lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
|
||||||
|
entry.tag_length[index_type], SEEK_CUR);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* Read data. */
|
|
||||||
if (entry.tag_length[index_type] >= (int)sizeof(buf))
|
|
||||||
{
|
{
|
||||||
logf("too long entry!");
|
/* Locate the correct entry from the sorted array. */
|
||||||
logf("length=%d", entry.tag_length[index_type]);
|
idxbuf[j].tag_seek[index_type] = tempbuf_find_location(i + j);
|
||||||
logf("pos=0x%02x", lseek(tmpfd, 0, SEEK_CUR));
|
if (idxbuf[j].tag_seek[index_type] < 0)
|
||||||
error = true;
|
{
|
||||||
break ;
|
logf("entry not found (%d)");
|
||||||
}
|
error = true;
|
||||||
|
break ;
|
||||||
lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR);
|
}
|
||||||
if (read(tmpfd, buf, entry.tag_length[index_type]) !=
|
|
||||||
entry.tag_length[index_type])
|
|
||||||
{
|
|
||||||
logf("read fail #3");
|
|
||||||
logf("offset=0x%02x", entry.tag_offset[index_type]);
|
|
||||||
logf("length=0x%02x", entry.tag_length[index_type]);
|
|
||||||
error = true;
|
|
||||||
break ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write to index file. */
|
|
||||||
idx.tag_seek[index_type] = lseek(fd, 0, SEEK_CUR);
|
|
||||||
fe.tag_length = entry.tag_length[index_type];
|
|
||||||
fe.idx_id = tch.entry_count + i;
|
|
||||||
write(fd, &fe, sizeof(struct tagfile_entry));
|
|
||||||
write(fd, buf, fe.tag_length);
|
|
||||||
tempbufidx++;
|
|
||||||
|
|
||||||
/* Skip to next. */
|
|
||||||
lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
|
|
||||||
entry.tag_length[index_type], SEEK_CUR);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Locate the correct entry from the sorted array. */
|
|
||||||
idx.tag_seek[index_type] = tempbuf_find_location(i);
|
|
||||||
if (idx.tag_seek[index_type] < 0)
|
|
||||||
{
|
|
||||||
logf("entry not found (%d)");
|
|
||||||
error = true;
|
|
||||||
break ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Write index. */
|
/* Write index. */
|
||||||
if (write(masterfd, &idx, sizeof(struct index_entry)) !=
|
if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||||
sizeof(struct index_entry))
|
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||||
{
|
{
|
||||||
logf("tagcache: write fail #4");
|
logf("tagcache: write fail #4");
|
||||||
error = true;
|
error = true;
|
||||||
|
@ -1741,7 +1791,8 @@ static bool build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
|
logf("done");
|
||||||
|
|
||||||
/* Finally write the uniqued tag index file. */
|
/* Finally write the uniqued tag index file. */
|
||||||
if (tagcache_is_sorted_tag(index_type))
|
if (tagcache_is_sorted_tag(index_type))
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,16 +31,38 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
|
||||||
#define HAVE_TC_RAMCACHE 1
|
#define HAVE_TC_RAMCACHE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Allow a little drift to the filename ordering. */
|
/* Allow a little drift to the filename ordering (should not be too high/low). */
|
||||||
#define POS_HISTORY_COUNT 4
|
#define POS_HISTORY_COUNT 4
|
||||||
|
|
||||||
|
/* How much to pre-load entries while committing to prevent seeking. */
|
||||||
|
#define IDX_BUF_DEPTH 64
|
||||||
|
|
||||||
|
/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
|
||||||
|
#define TAGCACHE_MAGIC 0x54434803
|
||||||
|
|
||||||
|
/* How much to allocate extra space for ramcache. */
|
||||||
|
#define TAGCACHE_RESERVE 32768
|
||||||
|
|
||||||
/* How many entries we can create in one tag file (for sorting). */
|
/* How many entries we can create in one tag file (for sorting). */
|
||||||
#define TAGFILE_MAX_ENTRIES 20000
|
#define TAGFILE_MAX_ENTRIES 20000
|
||||||
|
|
||||||
|
/* How many entries to fetch to the seek table at once while searching. */
|
||||||
#define SEEK_LIST_SIZE 50
|
#define SEEK_LIST_SIZE 50
|
||||||
|
|
||||||
|
/* Always strict align entries for best performance and binary compatability. */
|
||||||
|
#define TAGCACHE_STRICT_ALIGN 1
|
||||||
|
|
||||||
#define TAGCACHE_MAX_FILTERS 3
|
#define TAGCACHE_MAX_FILTERS 3
|
||||||
#define TAGCACHE_MAX_CLAUSES 10
|
#define TAGCACHE_MAX_CLAUSES 10
|
||||||
|
|
||||||
|
/* Tag database files. */
|
||||||
|
#define TAGCACHE_FILE_TEMP ROCKBOX_DIR "/tagcache_tmp.tcd"
|
||||||
|
#define TAGCACHE_FILE_MASTER ROCKBOX_DIR "/tagcache_idx.tcd"
|
||||||
|
#define TAGCACHE_FILE_INDEX ROCKBOX_DIR "/tagcache_%d.tcd"
|
||||||
|
|
||||||
|
/* Flags */
|
||||||
|
#define FLAG_DELETED 0x0001
|
||||||
|
|
||||||
enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
|
enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
|
||||||
clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
|
clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
|
||||||
enum modifiers { clause_mod_none, clause_mod_not };
|
enum modifiers { clause_mod_none, clause_mod_not };
|
||||||
|
|
|
@ -5,6 +5,7 @@ logf.c
|
||||||
backlight.c
|
backlight.c
|
||||||
buffer.c
|
buffer.c
|
||||||
common/atoi.c
|
common/atoi.c
|
||||||
|
common/crc32.c
|
||||||
common/ctype.c
|
common/ctype.c
|
||||||
#ifndef SIMULATOR
|
#ifndef SIMULATOR
|
||||||
common/dir.c
|
common/dir.c
|
||||||
|
|
57
firmware/common/crc32.c
Normal file
57
firmware/common/crc32.c
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Code copied from firmware_flash plugin. */
|
||||||
|
|
||||||
|
/* Tool function to calculate a CRC32 across some buffer */
|
||||||
|
/* third argument is either 0xFFFFFFFF to start or value from last piece */
|
||||||
|
unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32)
|
||||||
|
{
|
||||||
|
/* CCITT standard polynomial 0x04C11DB7 */
|
||||||
|
static const unsigned crc32_lookup[16] =
|
||||||
|
{ /* lookup table for 4 bits at a time is affordable */
|
||||||
|
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
|
||||||
|
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
|
||||||
|
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
|
||||||
|
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned char byte;
|
||||||
|
unsigned t;
|
||||||
|
|
||||||
|
while (len--)
|
||||||
|
{
|
||||||
|
byte = *buf++; /* get one byte of data */
|
||||||
|
|
||||||
|
/* upper nibble of our data */
|
||||||
|
t = crc32 >> 28; /* extract the 4 most significant bits */
|
||||||
|
t ^= byte >> 4; /* XOR in 4 bits of data into the extracted bits */
|
||||||
|
crc32 <<= 4; /* shift the CRC register left 4 bits */
|
||||||
|
crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */
|
||||||
|
|
||||||
|
/* lower nibble of our data */
|
||||||
|
t = crc32 >> 28; /* extract the 4 most significant bits */
|
||||||
|
t ^= byte & 0x0F; /* XOR in 4 bits of data into the extracted bits */
|
||||||
|
crc32 <<= 4; /* shift the CRC register left 4 bits */
|
||||||
|
crc32 ^= crc32_lookup[t]; /* do the table lookup and XOR the result */
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc32;
|
||||||
|
}
|
||||||
|
|
25
firmware/include/crc32.h
Normal file
25
firmware/include/crc32.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2003 Jörg Hohensohn [IDC]Dragon
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
#ifndef _CRC32_H
|
||||||
|
#define _CRC32_H
|
||||||
|
|
||||||
|
unsigned crc_32(unsigned char* buf, unsigned len, unsigned crc32);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue