diff options
-rw-r--r-- | apps/tagcache.c | 103 | ||||
-rw-r--r-- | apps/tagcache.h | 2 | ||||
-rw-r--r-- | apps/tagtree.c | 24 |
3 files changed, 78 insertions, 51 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index 75191d678e..7555781cbe 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -984,74 +984,86 @@ static bool check_against_clause(long numeric, const char *str, | |||
984 | 984 | ||
985 | static bool check_clauses(struct tagcache_search *tcs, | 985 | static bool check_clauses(struct tagcache_search *tcs, |
986 | struct index_entry *idx, | 986 | struct index_entry *idx, |
987 | struct tagcache_search_clause **clause, int count) | 987 | struct tagcache_search_clause **clauses, int count) |
988 | { | 988 | { |
989 | int i; | 989 | int i; |
990 | 990 | ||
991 | #ifdef HAVE_TC_RAMCACHE | 991 | /* Go through all conditional clauses. */ |
992 | if (tcs->ramsearch) | 992 | for (i = 0; i < count; i++) |
993 | { | 993 | { |
994 | /* Go through all conditional clauses. */ | 994 | int seek; |
995 | for (i = 0; i < count; i++) | 995 | char buf[256]; |
996 | char *str; | ||
997 | struct tagcache_search_clause *clause = clauses[i]; | ||
998 | |||
999 | if (clause->type == clause_logical_or) | ||
1000 | break; /* all conditions before logical-or satisfied -- | ||
1001 | stop processing clauses */ | ||
1002 | |||
1003 | #ifdef HAVE_TC_RAMCACHE | ||
1004 | str = NULL; | ||
1005 | |||
1006 | if (tcs->ramsearch) | ||
996 | { | 1007 | { |
997 | struct tagfile_entry *tfe; | 1008 | struct tagfile_entry *tfe; |
998 | int seek; | ||
999 | char buf[256]; | ||
1000 | char *str = NULL; | ||
1001 | 1009 | ||
1002 | seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx); | 1010 | seek = check_virtual_tags(clause->tag, tcs->idx_id, idx); |
1003 | 1011 | ||
1004 | if (!TAGCACHE_IS_NUMERIC(clause[i]->tag)) | 1012 | if (!TAGCACHE_IS_NUMERIC(clause->tag)) |
1005 | { | 1013 | { |
1006 | if (clause[i]->tag == tag_filename) | 1014 | if (clause->tag == tag_filename) |
1007 | { | 1015 | { |
1008 | retrieve(tcs, idx, tag_filename, buf, sizeof buf); | 1016 | retrieve(tcs, idx, tag_filename, buf, sizeof buf); |
1009 | str = buf; | 1017 | str = buf; |
1010 | } | 1018 | } |
1011 | else | 1019 | else |
1012 | { | 1020 | { |
1013 | tfe = (struct tagfile_entry *)&hdr->tags[clause[i]->tag][seek]; | 1021 | tfe = (struct tagfile_entry *)&hdr->tags[clause->tag][seek]; |
1014 | str = tfe->tag_data; | 1022 | str = tfe->tag_data; |
1015 | } | 1023 | } |
1016 | } | 1024 | } |
1017 | |||
1018 | if (!check_against_clause(seek, str, clause[i])) | ||
1019 | return false; | ||
1020 | } | 1025 | } |
1021 | } | 1026 | else |
1022 | else | ||
1023 | #endif | 1027 | #endif |
1024 | { | ||
1025 | /* Check for conditions. */ | ||
1026 | for (i = 0; i < count; i++) | ||
1027 | { | 1028 | { |
1028 | struct tagfile_entry tfe; | 1029 | struct tagfile_entry tfe; |
1029 | int seek; | 1030 | str = buf; |
1030 | char str[256]; | ||
1031 | 1031 | ||
1032 | seek = check_virtual_tags(clause[i]->tag, tcs->idx_id, idx); | 1032 | seek = check_virtual_tags(clause->tag, tcs->idx_id, idx); |
1033 | 1033 | ||
1034 | memset(str, 0, sizeof str); | 1034 | memset(buf, 0, sizeof buf); |
1035 | if (!TAGCACHE_IS_NUMERIC(clause[i]->tag)) | 1035 | if (!TAGCACHE_IS_NUMERIC(clause->tag)) |
1036 | { | 1036 | { |
1037 | int fd = tcs->idxfd[clause[i]->tag]; | 1037 | int fd = tcs->idxfd[clause->tag]; |
1038 | lseek(fd, seek, SEEK_SET); | 1038 | lseek(fd, seek, SEEK_SET); |
1039 | ecread_tagfile_entry(fd, &tfe); | 1039 | ecread_tagfile_entry(fd, &tfe); |
1040 | if (tfe.tag_length >= (int)sizeof(str)) | 1040 | if (tfe.tag_length >= (int)sizeof(buf)) |
1041 | { | 1041 | { |
1042 | logf("Too long tag read!"); | 1042 | logf("Too long tag read!"); |
1043 | break ; | 1043 | return false; |
1044 | } | 1044 | } |
1045 | 1045 | ||
1046 | read(fd, str, tfe.tag_length); | 1046 | read(fd, str, tfe.tag_length); |
1047 | 1047 | ||
1048 | /* Check if entry has been deleted. */ | 1048 | /* Check if entry has been deleted. */ |
1049 | if (str[0] == '\0') | 1049 | if (str[0] == '\0') |
1050 | return false; | ||
1051 | } | ||
1052 | } | ||
1053 | |||
1054 | if (!check_against_clause(seek, str, clause)) | ||
1055 | { | ||
1056 | /* Clause failed -- try finding a logical-or clause */ | ||
1057 | while (++i < count) | ||
1058 | { | ||
1059 | if (clauses[i]->type == clause_logical_or) | ||
1050 | break; | 1060 | break; |
1051 | } | 1061 | } |
1052 | 1062 | ||
1053 | if (!check_against_clause(seek, str, clause[i])) | 1063 | if (i < count) /* Found logical-or? */ |
1054 | return false; | 1064 | continue; /* Check clauses after logical-or */ |
1065 | |||
1066 | return false; | ||
1055 | } | 1067 | } |
1056 | } | 1068 | } |
1057 | 1069 | ||
@@ -1369,21 +1381,24 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, | |||
1369 | return false; | 1381 | return false; |
1370 | } | 1382 | } |
1371 | 1383 | ||
1372 | /* Check if there is already a similar filter in present (filters are | 1384 | if (clause->type != clause_logical_or) |
1373 | * much faster than clauses). | ||
1374 | */ | ||
1375 | for (i = 0; i < tcs->filter_count; i++) | ||
1376 | { | ||
1377 | if (tcs->filter_tag[i] == clause->tag) | ||
1378 | return true; | ||
1379 | } | ||
1380 | |||
1381 | if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0) | ||
1382 | { | 1385 | { |
1383 | char buf[MAX_PATH]; | 1386 | /* Check if there is already a similar filter in present (filters are |
1384 | 1387 | * much faster than clauses). | |
1385 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); | 1388 | */ |
1386 | tcs->idxfd[clause->tag] = open(buf, O_RDONLY); | 1389 | for (i = 0; i < tcs->filter_count; i++) |
1390 | { | ||
1391 | if (tcs->filter_tag[i] == clause->tag) | ||
1392 | return true; | ||
1393 | } | ||
1394 | |||
1395 | if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0) | ||
1396 | { | ||
1397 | char buf[MAX_PATH]; | ||
1398 | |||
1399 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); | ||
1400 | tcs->idxfd[clause->tag] = open(buf, O_RDONLY); | ||
1401 | } | ||
1387 | } | 1402 | } |
1388 | 1403 | ||
1389 | tcs->clause[tcs->clause_count] = clause; | 1404 | tcs->clause[tcs->clause_count] = clause; |
diff --git a/apps/tagcache.h b/apps/tagcache.h index 59f8b8bc9a..7351998c0a 100644 --- a/apps/tagcache.h +++ b/apps/tagcache.h | |||
@@ -120,7 +120,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title, | |||
120 | enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, | 120 | enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, |
121 | clause_lt, clause_lteq, clause_contains, clause_not_contains, | 121 | clause_lt, clause_lteq, clause_contains, clause_not_contains, |
122 | clause_begins_with, clause_not_begins_with, clause_ends_with, | 122 | clause_begins_with, clause_not_begins_with, clause_ends_with, |
123 | clause_not_ends_with, clause_oneof }; | 123 | clause_not_ends_with, clause_oneof, clause_logical_or }; |
124 | 124 | ||
125 | struct tagcache_stat { | 125 | struct tagcache_stat { |
126 | bool initialized; /* Is tagcache currently busy? */ | 126 | bool initialized; /* Is tagcache currently busy? */ |
diff --git a/apps/tagtree.c b/apps/tagtree.c index 2a2e2b805b..e7f703154c 100644 --- a/apps/tagtree.c +++ b/apps/tagtree.c | |||
@@ -461,16 +461,18 @@ static int add_format(const char *buf) | |||
461 | 461 | ||
462 | while (1) | 462 | while (1) |
463 | { | 463 | { |
464 | struct tagcache_search_clause *newclause; | ||
465 | |||
464 | if (clause_count >= TAGCACHE_MAX_CLAUSES) | 466 | if (clause_count >= TAGCACHE_MAX_CLAUSES) |
465 | { | 467 | { |
466 | logf("too many clauses"); | 468 | logf("too many clauses"); |
467 | break; | 469 | break; |
468 | } | 470 | } |
469 | 471 | ||
470 | formats[format_count]->clause[clause_count] = | 472 | newclause = buffer_alloc(sizeof(struct tagcache_search_clause)); |
471 | buffer_alloc(sizeof(struct tagcache_search_clause)); | ||
472 | 473 | ||
473 | if (!read_clause(formats[format_count]->clause[clause_count])) | 474 | formats[format_count]->clause[clause_count] = newclause; |
475 | if (!read_clause(newclause)) | ||
474 | break; | 476 | break; |
475 | 477 | ||
476 | clause_count++; | 478 | clause_count++; |
@@ -486,6 +488,7 @@ static int add_format(const char *buf) | |||
486 | 488 | ||
487 | static int get_condition(struct search_instruction *inst) | 489 | static int get_condition(struct search_instruction *inst) |
488 | { | 490 | { |
491 | struct tagcache_search_clause *new_clause; | ||
489 | int clause_count; | 492 | int clause_count; |
490 | char buf[128]; | 493 | char buf[128]; |
491 | 494 | ||
@@ -530,10 +533,15 @@ static int get_condition(struct search_instruction *inst) | |||
530 | return false; | 533 | return false; |
531 | } | 534 | } |
532 | 535 | ||
533 | inst->clause[inst->tagorder_count][clause_count] = | 536 | new_clause = buffer_alloc(sizeof(struct tagcache_search_clause)); |
534 | buffer_alloc(sizeof(struct tagcache_search_clause)); | 537 | inst->clause[inst->tagorder_count][clause_count] = new_clause; |
535 | 538 | ||
536 | if (!read_clause(inst->clause[inst->tagorder_count][clause_count])) | 539 | if (*strp == '|') |
540 | { | ||
541 | strp++; | ||
542 | new_clause->type = clause_logical_or; | ||
543 | } | ||
544 | else if (!read_clause(new_clause)) | ||
537 | return -1; | 545 | return -1; |
538 | 546 | ||
539 | inst->clause_count[inst->tagorder_count]++; | 547 | inst->clause_count[inst->tagorder_count]++; |
@@ -1502,6 +1510,10 @@ int tagtree_enter(struct tree_context* c) | |||
1502 | for (j = 0; j < csi->clause_count[i]; j++) | 1510 | for (j = 0; j < csi->clause_count[i]; j++) |
1503 | { | 1511 | { |
1504 | char* searchstring; | 1512 | char* searchstring; |
1513 | |||
1514 | if (csi->clause[i][j]->type == clause_logical_or) | ||
1515 | continue; | ||
1516 | |||
1505 | source = csi->clause[i][j]->source; | 1517 | source = csi->clause[i][j]->source; |
1506 | 1518 | ||
1507 | if (source == source_constant) | 1519 | if (source == source_constant) |