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:
parent
a99bc99b66
commit
4c6fd0f4c0
2 changed files with 145 additions and 34 deletions
158
apps/tagcache.c
158
apps/tagcache.c
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue