Initial conditional filtering support for the tagcache engine and a

fix while building the lookup list. UI part not yet ready.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9465 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Miika Pekkarinen 2006-04-03 18:57:34 +00:00
parent a99bc99b66
commit 4c6fd0f4c0
2 changed files with 145 additions and 34 deletions

View file

@ -132,7 +132,7 @@ static int total_entry_count = 0;
static int data_size = 0; static int data_size = 0;
static int processed_dir_count; static int processed_dir_count;
static bool is_numeric_tag(int type) bool tagcache_is_numeric_tag(int type)
{ {
int i; int i;
@ -326,11 +326,9 @@ static struct index_entry *find_entry_disk(const char *filename, bool retrieve)
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag) long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
{ {
struct tagcache_header tch;
struct index_entry idx; struct index_entry idx;
int masterfd;
if (!is_numeric_tag(tag)) if (!tagcache_is_numeric_tag(tag))
return -1; return -1;
#ifdef HAVE_TC_RAMCACHE #ifdef HAVE_TC_RAMCACHE
@ -340,34 +338,48 @@ long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
} }
#endif #endif
masterfd = open(TAGCACHE_FILE_MASTER, O_RDONLY); lseek(tcs->masterfd, tcs->idx_id * sizeof(struct index_entry), SEEK_CUR);
if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) !=
if (masterfd < 0)
{
logf("open fail");
return -2;
}
if (read(masterfd, &tch, sizeof(struct tagcache_header)) !=
sizeof(struct tagcache_header) || tch.magic != TAGCACHE_MAGIC)
{
logf("header error");
return -3;
}
lseek(masterfd, tcs->idx_id * sizeof(struct index_entry), SEEK_CUR);
if (read(masterfd, &idx, sizeof(struct index_entry)) !=
sizeof(struct index_entry)) sizeof(struct index_entry))
{ {
logf("read error #3"); logf("read error #3");
close(masterfd);
return -4; return -4;
} }
close(masterfd);
return idx.tag_seek[tag]; return idx.tag_seek[tag];
} }
static bool check_against_clause(long numeric, const char *str,
const struct tagcache_search_clause *clause)
{
switch (clause->type)
{
case clause_is:
if (clause->numeric)
return numeric == clause->numeric_data;
else
return !strcasecmp(clause->str, str);
case clause_gt:
return numeric > clause->numeric_data;
case clause_gteq:
return numeric >= clause->numeric_data;
case clause_lt:
return numeric < clause->numeric_data;
case clause_lteq:
return numeric <= clause->numeric_data;
case clause_contains:
return (strcasestr(str, clause->str) != NULL);
case clause_begins_with:
return (strcasestr(str, clause->str) == str);
case clause_ends_with: /* Not supported yet */
return false;
}
return false;
}
static bool build_lookup_list(struct tagcache_search *tcs) static bool build_lookup_list(struct tagcache_search *tcs)
{ {
struct tagcache_header header; struct tagcache_header header;
@ -382,7 +394,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
{ {
int j; int j;
for (i = tcs->seek_pos; i < hdr->h.entry_count - tcs->seek_pos; i++) for (i = tcs->seek_pos; i < hdr->h.entry_count; i++)
{ {
if (tcs->seek_list_count == SEEK_LIST_SIZE) if (tcs->seek_list_count == SEEK_LIST_SIZE)
break ; break ;
@ -397,6 +409,25 @@ static bool build_lookup_list(struct tagcache_search *tcs)
if (j < tcs->filter_count) if (j < tcs->filter_count)
continue ; continue ;
for (j = 0; j < tcs->clause_count; j++)
{
int seek = hdr->indices[i].tag_seek[tcs->clause[j]->tag];
char *str = NULL;
struct tagfile_entry *entry;
if (!tagcache_is_numeric_tag(tcs->clause[j]->tag))
{
entry = (struct tagfile_entry *)&hdr->tags[tcs->clause[j]->tag][seek];
str = entry->tag_data;
}
if (!check_against_clause(seek, str, tcs->clause[j]))
break ;
}
if (j < tcs->clause_count)
continue ;
/* Add to the seek list if not already there. */ /* Add to the seek list if not already there. */
for (j = 0; j < tcs->seek_list_count; j++) for (j = 0; j < tcs->seek_list_count; j++)
{ {
@ -455,6 +486,26 @@ static bool build_lookup_list(struct tagcache_search *tcs)
if (i < tcs->filter_count) if (i < tcs->filter_count)
continue ; continue ;
/* Check for conditions. */
for (i = 0; i < tcs->clause_count; i++)
{
int seek = entry.tag_seek[tcs->clause[i]->tag];
char str[64];
memset(str, 0, sizeof str);
if (!tagcache_is_numeric_tag(tcs->clause[i]->tag))
{
/* FIXME: Not yet implemented. */
// str = &hdr->tags[tcs->clause[i].tag][seek];
}
if (!check_against_clause(seek, str, tcs->clause[i]))
break ;
}
if (i < tcs->clause_count)
continue ;
/* Add to the seek list if not already there. */ /* Add to the seek list if not already there. */
for (i = 0; i < tcs->seek_list_count; i++) for (i = 0; i < tcs->seek_list_count; i++)
{ {
@ -484,6 +535,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
if (tcs->valid) if (tcs->valid)
tagcache_search_finish(tcs); tagcache_search_finish(tcs);
memset(tcs, 0, sizeof(struct tagcache_search));
tcs->position = sizeof(struct tagcache_header); tcs->position = sizeof(struct tagcache_header);
tcs->fd = -1; tcs->fd = -1;
tcs->type = tag; tcs->type = tag;
@ -491,6 +543,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
tcs->seek_list_count = 0; tcs->seek_list_count = 0;
tcs->filter_count = 0; tcs->filter_count = 0;
tcs->valid = true; tcs->valid = true;
tcs->masterfd = -1;
#ifndef HAVE_TC_RAMCACHE #ifndef HAVE_TC_RAMCACHE
tcs->ramsearch = false; tcs->ramsearch = false;
@ -503,7 +556,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
else else
#endif #endif
{ {
if (is_numeric_tag(tcs->type)) if (tagcache_is_numeric_tag(tcs->type))
return true; return true;
snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tcs->type); snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tcs->type);
@ -521,6 +574,23 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
logf("incorrect header"); logf("incorrect header");
return false; return false;
} }
tcs->masterfd = open(TAGCACHE_FILE_MASTER, O_RDONLY);
if (tcs->masterfd < 0)
{
logf("open fail");
return false;
}
if (read(tcs->masterfd, &h, sizeof(struct tagcache_header)) !=
sizeof(struct tagcache_header) || h.magic != TAGCACHE_MAGIC)
{
logf("header error");
close(tcs->masterfd);
tcs->masterfd = -1;
return false;
}
} }
return true; return true;
@ -539,6 +609,21 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
return true; return true;
} }
bool tagcache_search_add_clause(struct tagcache_search *tcs,
struct tagcache_search_clause *clause)
{
if (tcs->clause_count >= TAGCACHE_MAX_CLAUSES)
{
logf("Too many clauses");
return false;
}
tcs->clause[tcs->clause_count] = clause;
tcs->clause_count++;
return true;
}
bool tagcache_get_next(struct tagcache_search *tcs) bool tagcache_get_next(struct tagcache_search *tcs)
{ {
static char buf[MAX_PATH]; static char buf[MAX_PATH];
@ -547,7 +632,7 @@ bool tagcache_get_next(struct tagcache_search *tcs)
if (!tcs->valid) if (!tcs->valid)
return false; return false;
if (tcs->fd < 0 && !is_numeric_tag(tcs->type) if (tcs->fd < 0 && !tagcache_is_numeric_tag(tcs->type)
#ifdef HAVE_TC_RAMCACHE #ifdef HAVE_TC_RAMCACHE
&& !tcs->ramsearch && !tcs->ramsearch
#endif #endif
@ -555,11 +640,11 @@ bool tagcache_get_next(struct tagcache_search *tcs)
return false; return false;
/* Searching not supported for numeric tags yet. */ /* Searching not supported for numeric tags yet. */
if (is_numeric_tag(tcs->type)) if (tagcache_is_numeric_tag(tcs->type))
return false; return false;
/* Relative fetch. */ /* Relative fetch. */
if (tcs->filter_count > 0) if (tcs->filter_count > 0 || tcs->clause_count > 0)
{ {
/* Check for end of list. */ /* Check for end of list. */
if (tcs->seek_list_count == 0) if (tcs->seek_list_count == 0)
@ -672,9 +757,16 @@ void tagcache_search_finish(struct tagcache_search *tcs)
{ {
close(tcs->fd); close(tcs->fd);
tcs->fd = -1; tcs->fd = -1;
tcs->ramsearch = false;
tcs->valid = false;
} }
if (tcs->masterfd >= 0)
{
close(tcs->masterfd);
tcs->masterfd = -1;
}
tcs->ramsearch = false;
tcs->valid = false;
} }
#ifdef HAVE_TC_RAMCACHE #ifdef HAVE_TC_RAMCACHE
@ -846,7 +938,7 @@ static void remove_files(void)
remove(TAGCACHE_FILE_MASTER); remove(TAGCACHE_FILE_MASTER);
for (i = 0; i < TAG_COUNT; i++) for (i = 0; i < TAG_COUNT; i++)
{ {
if (is_numeric_tag(i)) if (tagcache_is_numeric_tag(i))
continue; continue;
snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i); snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i);
@ -1593,7 +1685,7 @@ static bool commit(void)
/* Now create the index files. */ /* Now create the index files. */
for (i = 0; i < TAG_COUNT; i++) for (i = 0; i < TAG_COUNT; i++)
{ {
if (is_numeric_tag(i)) if (tagcache_is_numeric_tag(i))
{ {
build_numeric_index(i, &header, tmpfd); build_numeric_index(i, &header, tmpfd);
} }
@ -1760,7 +1852,7 @@ static bool load_tagcache(void)
struct tagfile_entry *fe; struct tagfile_entry *fe;
char buf[MAX_PATH]; char buf[MAX_PATH];
if (is_numeric_tag(i)) if (tagcache_is_numeric_tag(i))
continue ; continue ;
//p = ((void *)p+1); //p = ((void *)p+1);

View file

@ -39,14 +39,30 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
#define SEEK_LIST_SIZE 50 #define SEEK_LIST_SIZE 50
#define TAGCACHE_MAX_FILTERS 3 #define TAGCACHE_MAX_FILTERS 3
#define TAGCACHE_MAX_CLAUSES 10
enum clause { clause_none, clause_is, clause_gt, clause_gteq, clause_lt,
clause_lteq, clause_contains, clause_begins_with, clause_ends_with };
enum modifies { clause_mod_none, clause_mod_not };
struct tagcache_search_clause
{
int tag;
int type;
bool numeric;
long numeric_data;
char str[32];
};
struct tagcache_search { struct tagcache_search {
/* For internal use only. */ /* For internal use only. */
int fd; int fd, masterfd;
long seek_list[SEEK_LIST_SIZE]; long seek_list[SEEK_LIST_SIZE];
long filter_tag[TAGCACHE_MAX_FILTERS]; long filter_tag[TAGCACHE_MAX_FILTERS];
long filter_seek[TAGCACHE_MAX_FILTERS]; long filter_seek[TAGCACHE_MAX_FILTERS];
int filter_count; int filter_count;
struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES];
int clause_count;
int seek_list_count; int seek_list_count;
int seek_pos; int seek_pos;
int idx_id; int idx_id;
@ -62,9 +78,12 @@ struct tagcache_search {
long result_seek; long result_seek;
}; };
bool tagcache_is_numeric_tag(int type);
bool tagcache_search(struct tagcache_search *tcs, int tag); bool tagcache_search(struct tagcache_search *tcs, int tag);
bool tagcache_search_add_filter(struct tagcache_search *tcs, bool tagcache_search_add_filter(struct tagcache_search *tcs,
int tag, int seek); int tag, int seek);
bool tagcache_search_add_clause(struct tagcache_search *tcs,
struct tagcache_search_clause *clause);
bool tagcache_get_next(struct tagcache_search *tcs); bool tagcache_get_next(struct tagcache_search *tcs);
void tagcache_search_finish(struct tagcache_search *tcs); void tagcache_search_finish(struct tagcache_search *tcs);
long tagcache_get_numeric(const struct tagcache_search *tcs, int tag); long tagcache_get_numeric(const struct tagcache_search *tcs, int tag);