diff options
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r-- | apps/tagcache.c | 460 |
1 files changed, 366 insertions, 94 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index b3bce45b9a..d2ef9845bb 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -67,7 +67,8 @@ static struct tagcache_stat stat; | |||
67 | enum tagcache_queue { | 67 | enum tagcache_queue { |
68 | Q_STOP_SCAN = 0, | 68 | Q_STOP_SCAN = 0, |
69 | Q_START_SCAN, | 69 | Q_START_SCAN, |
70 | Q_FORCE_UPDATE, | 70 | Q_UPDATE, |
71 | Q_REBUILD, | ||
71 | }; | 72 | }; |
72 | 73 | ||
73 | 74 | ||
@@ -177,7 +178,7 @@ bool tagcache_is_sorted_tag(int type) | |||
177 | return false; | 178 | return false; |
178 | } | 179 | } |
179 | 180 | ||
180 | #ifdef HAVE_TC_RAMCACHE | 181 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
181 | static struct index_entry *find_entry_ram(const char *filename, | 182 | static struct index_entry *find_entry_ram(const char *filename, |
182 | const struct dircache_entry *dc) | 183 | const struct dircache_entry *dc) |
183 | { | 184 | { |
@@ -272,7 +273,7 @@ static struct index_entry *find_entry_disk(const char *filename, bool retrieve) | |||
272 | 273 | ||
273 | if (tfe.tag_length >= (long)sizeof(buf)) | 274 | if (tfe.tag_length >= (long)sizeof(buf)) |
274 | { | 275 | { |
275 | logf("too long tag"); | 276 | logf("too long tag #1"); |
276 | close(fd); | 277 | close(fd); |
277 | last_pos = -1; | 278 | last_pos = -1; |
278 | return NULL; | 279 | return NULL; |
@@ -487,6 +488,8 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
487 | { | 488 | { |
488 | tcs->seek_list[tcs->seek_list_count] = | 489 | tcs->seek_list[tcs->seek_list_count] = |
489 | hdr->indices[i].tag_seek[tcs->type]; | 490 | hdr->indices[i].tag_seek[tcs->type]; |
491 | tcs->seek_flags[tcs->seek_list_count] = | ||
492 | hdr->indices[i].flag; | ||
490 | tcs->seek_list_count++; | 493 | tcs->seek_list_count++; |
491 | } | 494 | } |
492 | } | 495 | } |
@@ -503,6 +506,10 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
503 | while (read(tcs->masterfd, &entry, sizeof(struct index_entry)) == | 506 | while (read(tcs->masterfd, &entry, sizeof(struct index_entry)) == |
504 | sizeof(struct index_entry)) | 507 | sizeof(struct index_entry)) |
505 | { | 508 | { |
509 | /* Check if entry has been deleted. */ | ||
510 | if (entry.flag & FLAG_DELETED) | ||
511 | continue; | ||
512 | |||
506 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 513 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
507 | break ; | 514 | break ; |
508 | 515 | ||
@@ -538,6 +545,10 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
538 | } | 545 | } |
539 | 546 | ||
540 | read(fd, str, tfe.tag_length); | 547 | read(fd, str, tfe.tag_length); |
548 | |||
549 | /* Check if entry has been deleted. */ | ||
550 | if (str[0] == '\0') | ||
551 | break; | ||
541 | } | 552 | } |
542 | 553 | ||
543 | if (!check_against_clause(seek, str, tcs->clause[i])) | 554 | if (!check_against_clause(seek, str, tcs->clause[i])) |
@@ -559,6 +570,7 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
559 | { | 570 | { |
560 | tcs->seek_list[tcs->seek_list_count] = | 571 | tcs->seek_list[tcs->seek_list_count] = |
561 | entry.tag_seek[tcs->type]; | 572 | entry.tag_seek[tcs->type]; |
573 | tcs->seek_flags[tcs->seek_list_count] = entry.flag; | ||
562 | tcs->seek_list_count++; | 574 | tcs->seek_list_count++; |
563 | } | 575 | } |
564 | 576 | ||
@@ -582,7 +594,6 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
582 | return false; | 594 | return false; |
583 | 595 | ||
584 | tcs->position = sizeof(struct tagcache_header); | 596 | tcs->position = sizeof(struct tagcache_header); |
585 | tcs->fd = -1; | ||
586 | tcs->type = tag; | 597 | tcs->type = tag; |
587 | tcs->seek_pos = 0; | 598 | tcs->seek_pos = 0; |
588 | tcs->seek_list_count = 0; | 599 | tcs->seek_list_count = 0; |
@@ -608,17 +619,15 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
608 | return true; | 619 | return true; |
609 | 620 | ||
610 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tcs->type); | 621 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tcs->type); |
611 | tcs->fd = open(buf, O_RDONLY); | 622 | tcs->idxfd[tcs->type] = open(buf, O_RDONLY); |
612 | if (tcs->fd < 0) | 623 | if (tcs->idxfd[tcs->type] < 0) |
613 | { | 624 | { |
614 | logf("failed to open index"); | 625 | logf("failed to open index"); |
615 | return false; | 626 | return false; |
616 | } | 627 | } |
617 | 628 | ||
618 | tcs->idxfd[tcs->type] = tcs->fd; | ||
619 | |||
620 | /* Check the header. */ | 629 | /* Check the header. */ |
621 | if (read(tcs->fd, &h, sizeof(struct tagcache_header)) != | 630 | if (read(tcs->idxfd[tcs->type], &h, sizeof(struct tagcache_header)) != |
622 | sizeof(struct tagcache_header) || h.magic != TAGCACHE_MAGIC) | 631 | sizeof(struct tagcache_header) || h.magic != TAGCACHE_MAGIC) |
623 | { | 632 | { |
624 | logf("incorrect header"); | 633 | logf("incorrect header"); |
@@ -685,7 +694,30 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, | |||
685 | return true; | 694 | return true; |
686 | } | 695 | } |
687 | 696 | ||
688 | bool tagcache_get_next(struct tagcache_search *tcs) | 697 | static bool open_files(struct tagcache_search *tcs) |
698 | { | ||
699 | if (tcs->idxfd[tcs->type] < 0) | ||
700 | { | ||
701 | char fn[MAX_PATH]; | ||
702 | |||
703 | snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tcs->type); | ||
704 | tcs->idxfd[tcs->type] = open(fn, O_RDONLY); | ||
705 | } | ||
706 | |||
707 | if (tcs->idxfd[tcs->type] < 0) | ||
708 | { | ||
709 | logf("File not open!"); | ||
710 | return false; | ||
711 | } | ||
712 | |||
713 | return true; | ||
714 | } | ||
715 | |||
716 | #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ | ||
717 | ? (tcs->seek_flags[tcs->seek_list_count] \ | ||
718 | & FLAG_DIRCACHE) : 1) | ||
719 | |||
720 | static bool get_next(struct tagcache_search *tcs) | ||
689 | { | 721 | { |
690 | static char buf[MAX_PATH]; | 722 | static char buf[MAX_PATH]; |
691 | struct tagfile_entry entry; | 723 | struct tagfile_entry entry; |
@@ -693,7 +725,7 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
693 | if (!tcs->valid) | 725 | if (!tcs->valid) |
694 | return false; | 726 | return false; |
695 | 727 | ||
696 | if (tcs->fd < 0 && !tagcache_is_numeric_tag(tcs->type) | 728 | if (tcs->idxfd[tcs->type] < 0 && !tagcache_is_numeric_tag(tcs->type) |
697 | #ifdef HAVE_TC_RAMCACHE | 729 | #ifdef HAVE_TC_RAMCACHE |
698 | && !tcs->ramsearch | 730 | && !tcs->ramsearch |
699 | #endif | 731 | #endif |
@@ -718,15 +750,20 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
718 | tcs->seek_list_count--; | 750 | tcs->seek_list_count--; |
719 | 751 | ||
720 | /* Seek stream to the correct position and continue to direct fetch. */ | 752 | /* Seek stream to the correct position and continue to direct fetch. */ |
721 | if (!tcs->ramsearch) | 753 | if (!tcs->ramsearch || !TAG_FILENAME_RAM(tcs)) |
722 | lseek(tcs->fd, tcs->seek_list[tcs->seek_list_count], SEEK_SET); | 754 | { |
755 | if (!open_files(tcs)) | ||
756 | return false; | ||
757 | |||
758 | lseek(tcs->idxfd[tcs->type], tcs->seek_list[tcs->seek_list_count], SEEK_SET); | ||
759 | } | ||
723 | else | 760 | else |
724 | tcs->position = tcs->seek_list[tcs->seek_list_count]; | 761 | tcs->position = tcs->seek_list[tcs->seek_list_count]; |
725 | } | 762 | } |
726 | 763 | ||
727 | /* Direct fetch. */ | 764 | /* Direct fetch. */ |
728 | #ifdef HAVE_TC_RAMCACHE | 765 | #ifdef HAVE_TC_RAMCACHE |
729 | if (tcs->ramsearch) | 766 | if (tcs->ramsearch && TAG_FILENAME_RAM(tcs)) |
730 | { | 767 | { |
731 | struct tagfile_entry *ep; | 768 | struct tagfile_entry *ep; |
732 | 769 | ||
@@ -738,20 +775,22 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
738 | tcs->entry_count--; | 775 | tcs->entry_count--; |
739 | tcs->result_seek = tcs->position; | 776 | tcs->result_seek = tcs->position; |
740 | 777 | ||
778 | # ifdef HAVE_DIRCACHE | ||
741 | if (tcs->type == tag_filename) | 779 | if (tcs->type == tag_filename) |
742 | { | 780 | { |
743 | dircache_copy_path((struct dircache_entry *)tcs->position, | 781 | dircache_copy_path((struct dircache_entry *)tcs->position, |
744 | buf, sizeof buf); | 782 | buf, sizeof buf); |
745 | tcs->result = buf; | 783 | tcs->result = buf; |
746 | tcs->result_len = strlen(buf) + 1; | 784 | tcs->result_len = strlen(buf) + 1; |
747 | 785 | ||
748 | return true; | 786 | return true; |
749 | } | 787 | } |
788 | # endif | ||
750 | 789 | ||
751 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; | 790 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; |
752 | tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; | 791 | tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; |
753 | tcs->result = ep->tag_data; | 792 | tcs->result = ep->tag_data; |
754 | tcs->result_len = ep->tag_length; | 793 | tcs->result_len = strlen(tcs->result) + 1; |
755 | tcs->idx_id = ep->idx_id; | 794 | tcs->idx_id = ep->idx_id; |
756 | 795 | ||
757 | if (!tagcache_is_unique_tag(tcs->type)) | 796 | if (!tagcache_is_unique_tag(tcs->type)) |
@@ -762,8 +801,11 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
762 | else | 801 | else |
763 | #endif | 802 | #endif |
764 | { | 803 | { |
765 | tcs->result_seek = lseek(tcs->fd, 0, SEEK_CUR); | 804 | if (!open_files(tcs)) |
766 | if (read(tcs->fd, &entry, sizeof(struct tagfile_entry)) != | 805 | return false; |
806 | |||
807 | tcs->result_seek = lseek(tcs->idxfd[tcs->type], 0, SEEK_CUR); | ||
808 | if (read(tcs->idxfd[tcs->type], &entry, sizeof(struct tagfile_entry)) != | ||
767 | sizeof(struct tagfile_entry)) | 809 | sizeof(struct tagfile_entry)) |
768 | { | 810 | { |
769 | /* End of data. */ | 811 | /* End of data. */ |
@@ -775,11 +817,11 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
775 | if (entry.tag_length > (long)sizeof(buf)) | 817 | if (entry.tag_length > (long)sizeof(buf)) |
776 | { | 818 | { |
777 | tcs->valid = false; | 819 | tcs->valid = false; |
778 | logf("too long tag"); | 820 | logf("too long tag #2"); |
779 | return false; | 821 | return false; |
780 | } | 822 | } |
781 | 823 | ||
782 | if (read(tcs->fd, buf, entry.tag_length) != entry.tag_length) | 824 | if (read(tcs->idxfd[tcs->type], buf, entry.tag_length) != entry.tag_length) |
783 | { | 825 | { |
784 | tcs->valid = false; | 826 | tcs->valid = false; |
785 | logf("read error"); | 827 | logf("read error"); |
@@ -787,7 +829,7 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
787 | } | 829 | } |
788 | 830 | ||
789 | tcs->result = buf; | 831 | tcs->result = buf; |
790 | tcs->result_len = entry.tag_length; | 832 | tcs->result_len = strlen(tcs->result) + 1; |
791 | tcs->idx_id = entry.idx_id; | 833 | tcs->idx_id = entry.idx_id; |
792 | if (!tagcache_is_unique_tag(tcs->type)) | 834 | if (!tagcache_is_unique_tag(tcs->type)) |
793 | tcs->result_seek = tcs->idx_id; | 835 | tcs->result_seek = tcs->idx_id; |
@@ -795,6 +837,17 @@ bool tagcache_get_next(struct tagcache_search *tcs) | |||
795 | return true; | 837 | return true; |
796 | } | 838 | } |
797 | 839 | ||
840 | bool tagcache_get_next(struct tagcache_search *tcs) | ||
841 | { | ||
842 | while (get_next(tcs)) | ||
843 | { | ||
844 | if (tcs->result_len > 1) | ||
845 | return true; | ||
846 | } | ||
847 | |||
848 | return false; | ||
849 | } | ||
850 | |||
798 | bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | 851 | bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, |
799 | char *buf, long size) | 852 | char *buf, long size) |
800 | { | 853 | { |
@@ -809,38 +862,29 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | |||
809 | } | 862 | } |
810 | 863 | ||
811 | #ifdef HAVE_TC_RAMCACHE | 864 | #ifdef HAVE_TC_RAMCACHE |
812 | if (tcs->ramsearch) | 865 | if (tcs->ramsearch && TAG_FILENAME_RAM(tcs)) |
813 | { | 866 | { |
867 | struct tagfile_entry *ep; | ||
868 | |||
869 | # ifdef HAVE_DIRCACHE | ||
814 | if (tcs->type == tag_filename) | 870 | if (tcs->type == tag_filename) |
815 | { | 871 | { |
816 | dircache_copy_path((struct dircache_entry *)seek, | 872 | dircache_copy_path((struct dircache_entry *)seek, |
817 | buf, size); | 873 | buf, size); |
818 | } | 874 | return true; |
819 | else | ||
820 | { | ||
821 | struct tagfile_entry *ep; | ||
822 | |||
823 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][seek]; | ||
824 | strncpy(buf, ep->tag_data, size-1); | ||
825 | } | 875 | } |
876 | # endif | ||
877 | |||
878 | |||
879 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][seek]; | ||
880 | strncpy(buf, ep->tag_data, size-1); | ||
826 | 881 | ||
827 | return true; | 882 | return true; |
828 | } | 883 | } |
829 | #endif | 884 | #endif |
830 | |||
831 | if (tcs->idxfd[tcs->type] < 0) | ||
832 | { | ||
833 | char fn[MAX_PATH]; | ||
834 | |||
835 | snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tcs->type); | ||
836 | tcs->idxfd[tcs->type] = open(fn, O_RDONLY); | ||
837 | } | ||
838 | 885 | ||
839 | if (tcs->idxfd[tcs->type] < 0) | 886 | if (!open_files(tcs)) |
840 | { | ||
841 | logf("File not open!"); | ||
842 | return false; | 887 | return false; |
843 | } | ||
844 | 888 | ||
845 | lseek(tcs->idxfd[tcs->type], seek, SEEK_SET); | 889 | lseek(tcs->idxfd[tcs->type], seek, SEEK_SET); |
846 | if (read(tcs->idxfd[tcs->type], &tfe, sizeof(struct tagfile_entry)) != | 890 | if (read(tcs->idxfd[tcs->type], &tfe, sizeof(struct tagfile_entry)) != |
@@ -870,18 +914,6 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | |||
870 | 914 | ||
871 | #if 0 | 915 | #if 0 |
872 | 916 | ||
873 | static bool tagcache_delete(const char *filename) | ||
874 | { | ||
875 | struct index_entry *entry; | ||
876 | |||
877 | entry = find_entry_disk(filename, true); | ||
878 | if (entry == NULL) | ||
879 | { | ||
880 | logf("not found: %s", filename); | ||
881 | return false; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | void tagcache_modify(struct tagcache_search *tcs, int type, const char *text) | 917 | void tagcache_modify(struct tagcache_search *tcs, int type, const char *text) |
886 | { | 918 | { |
887 | struct tagentry *entry; | 919 | struct tagentry *entry; |
@@ -898,7 +930,7 @@ void tagcache_modify(struct tagcache_search *tcs, int type, const char *text) | |||
898 | tcs->seek_list[tcs->seek_list_count]; | 930 | tcs->seek_list[tcs->seek_list_count]; |
899 | } | 931 | } |
900 | 932 | ||
901 | entry = find_entry_ram( | 933 | entry = find_entry_ram(); |
902 | 934 | ||
903 | } | 935 | } |
904 | #endif | 936 | #endif |
@@ -907,13 +939,6 @@ void tagcache_search_finish(struct tagcache_search *tcs) | |||
907 | { | 939 | { |
908 | int i; | 940 | int i; |
909 | 941 | ||
910 | if (tcs->fd >= 0) | ||
911 | { | ||
912 | close(tcs->fd); | ||
913 | tcs->fd = -1; | ||
914 | tcs->idxfd[tcs->type] = -1; | ||
915 | } | ||
916 | |||
917 | if (tcs->masterfd >= 0) | 942 | if (tcs->masterfd >= 0) |
918 | { | 943 | { |
919 | close(tcs->masterfd); | 944 | close(tcs->masterfd); |
@@ -933,7 +958,7 @@ void tagcache_search_finish(struct tagcache_search *tcs) | |||
933 | tcs->valid = false; | 958 | tcs->valid = false; |
934 | } | 959 | } |
935 | 960 | ||
936 | #ifdef HAVE_TC_RAMCACHE | 961 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
937 | static struct tagfile_entry *get_tag(const struct index_entry *entry, int tag) | 962 | static struct tagfile_entry *get_tag(const struct index_entry *entry, int tag) |
938 | { | 963 | { |
939 | return (struct tagfile_entry *)&hdr->tags[tag][entry->tag_seek[tag]]; | 964 | return (struct tagfile_entry *)&hdr->tags[tag][entry->tag_seek[tag]]; |
@@ -943,7 +968,7 @@ static long get_tag_numeric(const struct index_entry *entry, int tag) | |||
943 | { | 968 | { |
944 | return entry->tag_seek[tag]; | 969 | return entry->tag_seek[tag]; |
945 | } | 970 | } |
946 | 971 | ||
947 | bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | 972 | bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) |
948 | { | 973 | { |
949 | struct index_entry *entry; | 974 | struct index_entry *entry; |
@@ -984,7 +1009,7 @@ inline void check_if_empty(char **tag) | |||
984 | 1009 | ||
985 | #define CRC_BUF_LEN 8 | 1010 | #define CRC_BUF_LEN 8 |
986 | 1011 | ||
987 | #ifdef HAVE_TC_RAMCACHE | 1012 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
988 | static void add_tagcache(const char *path, const struct dircache_entry *dc) | 1013 | static void add_tagcache(const char *path, const struct dircache_entry *dc) |
989 | #else | 1014 | #else |
990 | static void add_tagcache(const char *path) | 1015 | static void add_tagcache(const char *path) |
@@ -1006,8 +1031,8 @@ static void add_tagcache(const char *path) | |||
1006 | return ; | 1031 | return ; |
1007 | 1032 | ||
1008 | /* Check if the file is already cached. */ | 1033 | /* Check if the file is already cached. */ |
1009 | #ifdef HAVE_TC_RAMCACHE | 1034 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
1010 | if (stat.ramcache) | 1035 | if (stat.ramcache && dircache_is_enabled()) |
1011 | { | 1036 | { |
1012 | if (find_entry_ram(path, dc)) | 1037 | if (find_entry_ram(path, dc)) |
1013 | return ; | 1038 | return ; |
@@ -1477,7 +1502,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1477 | 1502 | ||
1478 | if (entry.tag_length >= (int)sizeof(buf)) | 1503 | if (entry.tag_length >= (int)sizeof(buf)) |
1479 | { | 1504 | { |
1480 | logf("too long tag"); | 1505 | logf("too long tag #3"); |
1481 | close(fd); | 1506 | close(fd); |
1482 | return -2; | 1507 | return -2; |
1483 | } | 1508 | } |
@@ -1489,6 +1514,10 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1489 | return -2; | 1514 | return -2; |
1490 | } | 1515 | } |
1491 | 1516 | ||
1517 | /* Skip deleted entries. */ | ||
1518 | if (buf[0] == '\0') | ||
1519 | continue; | ||
1520 | |||
1492 | /** | 1521 | /** |
1493 | * Save the tag and tag id in the memory buffer. Tag id | 1522 | * Save the tag and tag id in the memory buffer. Tag id |
1494 | * is saved so we can later reindex the master lookup | 1523 | * is saved so we can later reindex the master lookup |
@@ -1673,6 +1702,18 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1673 | 1702 | ||
1674 | for (j = 0; j < idxbuf_pos; j++) | 1703 | for (j = 0; j < idxbuf_pos; j++) |
1675 | { | 1704 | { |
1705 | if (idxbuf[j].flag & FLAG_DELETED) | ||
1706 | { | ||
1707 | int k; | ||
1708 | |||
1709 | idxbuf_pos--; | ||
1710 | for (k = j; k < idxbuf_pos; k++) | ||
1711 | idxbuf[k] = idxbuf[k+1]; | ||
1712 | |||
1713 | j--; | ||
1714 | continue; | ||
1715 | } | ||
1716 | |||
1676 | idxbuf[j].tag_seek[index_type] = tempbuf_find_location( | 1717 | idxbuf[j].tag_seek[index_type] = tempbuf_find_location( |
1677 | idxbuf[j].tag_seek[index_type]/TAGFILE_ENTRY_CHUNK_LENGTH | 1718 | idxbuf[j].tag_seek[index_type]/TAGFILE_ENTRY_CHUNK_LENGTH |
1678 | + TAGFILE_MAX_ENTRIES); | 1719 | + TAGFILE_MAX_ENTRIES); |
@@ -2008,6 +2049,117 @@ static void free_tempbuf(void) | |||
2008 | tempbuf_size = 0; | 2049 | tempbuf_size = 0; |
2009 | } | 2050 | } |
2010 | 2051 | ||
2052 | static bool delete_entry(long idx_id) | ||
2053 | { | ||
2054 | int fd; | ||
2055 | int tag, i; | ||
2056 | struct index_entry idx, myidx; | ||
2057 | struct tagcache_header hdr; | ||
2058 | char buf[MAX_PATH]; | ||
2059 | int in_use[TAG_COUNT]; | ||
2060 | |||
2061 | fd = open(TAGCACHE_FILE_MASTER, O_RDWR); | ||
2062 | if (fd < 0) | ||
2063 | { | ||
2064 | logf("master file open failed for R/W"); | ||
2065 | return false; | ||
2066 | } | ||
2067 | |||
2068 | /* Check the header. */ | ||
2069 | read(fd, &hdr, sizeof(struct tagcache_header)); | ||
2070 | if (hdr.magic != TAGCACHE_MAGIC) | ||
2071 | { | ||
2072 | logf("header error"); | ||
2073 | return false; | ||
2074 | } | ||
2075 | |||
2076 | lseek(fd, idx_id * sizeof(struct index_entry), SEEK_CUR); | ||
2077 | if (read(fd, &myidx, sizeof(struct index_entry)) | ||
2078 | != sizeof(struct index_entry)) | ||
2079 | { | ||
2080 | logf("read error"); | ||
2081 | return false; | ||
2082 | } | ||
2083 | |||
2084 | myidx.flag |= FLAG_DELETED; | ||
2085 | lseek(fd, -sizeof(struct index_entry), SEEK_CUR); | ||
2086 | if (write(fd, &myidx, sizeof(struct index_entry)) | ||
2087 | != sizeof(struct index_entry)) | ||
2088 | { | ||
2089 | logf("write error"); | ||
2090 | return false; | ||
2091 | } | ||
2092 | |||
2093 | /* Now check which tags are no longer in use (if any) */ | ||
2094 | for (tag = 0; tag < TAG_COUNT; tag++) | ||
2095 | in_use[tag] = 0; | ||
2096 | |||
2097 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | ||
2098 | for (i = 0; i < hdr.entry_count; i++) | ||
2099 | { | ||
2100 | if (read(fd, &idx, sizeof(struct index_entry)) | ||
2101 | != sizeof(struct index_entry)) | ||
2102 | { | ||
2103 | logf("read error"); | ||
2104 | close(fd); | ||
2105 | return false; | ||
2106 | } | ||
2107 | |||
2108 | if (idx.flag & FLAG_DELETED) | ||
2109 | continue; | ||
2110 | |||
2111 | for (tag = 0; tag < TAG_COUNT; tag++) | ||
2112 | { | ||
2113 | if (tagcache_is_numeric_tag(tag)) | ||
2114 | continue; | ||
2115 | |||
2116 | if (idx.tag_seek[tag] == myidx.tag_seek[tag]) | ||
2117 | in_use[tag]++; | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | close(fd); | ||
2122 | |||
2123 | /* Now delete all tags no longer in use. */ | ||
2124 | for (tag = 0; tag < TAG_COUNT; tag++) | ||
2125 | { | ||
2126 | if (tagcache_is_numeric_tag(tag)) | ||
2127 | continue; | ||
2128 | |||
2129 | if (in_use[tag]) | ||
2130 | { | ||
2131 | logf("in use: %d/%d", tag, in_use[tag]); | ||
2132 | continue; | ||
2133 | } | ||
2134 | |||
2135 | /* Open the index file, which contains the tag names. */ | ||
2136 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag); | ||
2137 | fd = open(buf, O_RDWR); | ||
2138 | |||
2139 | if (fd < 0) | ||
2140 | { | ||
2141 | logf("open failed"); | ||
2142 | return false; | ||
2143 | } | ||
2144 | |||
2145 | /* Skip the header block */ | ||
2146 | lseek(fd, myidx.tag_seek[tag] + sizeof(struct tagfile_entry), SEEK_SET); | ||
2147 | |||
2148 | read(fd, buf, 10); | ||
2149 | buf[10]='\0'; | ||
2150 | logf("TAG:%s", buf); | ||
2151 | lseek(fd, -10, SEEK_CUR); | ||
2152 | |||
2153 | /* Write first data byte in tag as \0 */ | ||
2154 | write(fd, "", 1); | ||
2155 | |||
2156 | /* Now tag data has been removed */ | ||
2157 | close(fd); | ||
2158 | } | ||
2159 | |||
2160 | return true; | ||
2161 | } | ||
2162 | |||
2011 | #ifdef HAVE_TC_RAMCACHE | 2163 | #ifdef HAVE_TC_RAMCACHE |
2012 | static bool allocate_tagcache(void) | 2164 | static bool allocate_tagcache(void) |
2013 | { | 2165 | { |
@@ -2063,12 +2215,13 @@ static bool load_tagcache(void) | |||
2063 | char *p; | 2215 | char *p; |
2064 | int i; | 2216 | int i; |
2065 | 2217 | ||
2066 | /* We really need the dircache for this. */ | ||
2067 | if (!dircache_is_enabled()) | ||
2068 | return false; | ||
2069 | |||
2070 | logf("loading tagcache to ram..."); | 2218 | logf("loading tagcache to ram..."); |
2071 | 2219 | ||
2220 | # ifdef HAVE_DIRCACHE | ||
2221 | while (dircache_is_initializing()) | ||
2222 | sleep(1); | ||
2223 | # endif | ||
2224 | |||
2072 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); | 2225 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); |
2073 | if (fd < 0) | 2226 | if (fd < 0) |
2074 | { | 2227 | { |
@@ -2151,8 +2304,11 @@ static bool load_tagcache(void) | |||
2151 | hdr->entry_count[i] < tch->entry_count; | 2304 | hdr->entry_count[i] < tch->entry_count; |
2152 | hdr->entry_count[i]++) | 2305 | hdr->entry_count[i]++) |
2153 | { | 2306 | { |
2307 | long pos; | ||
2308 | |||
2154 | yield(); | 2309 | yield(); |
2155 | fe = (struct tagfile_entry *)p; | 2310 | fe = (struct tagfile_entry *)p; |
2311 | pos = lseek(fd, 0, SEEK_CUR); | ||
2156 | rc = read(fd, fe, sizeof(struct tagfile_entry)); | 2312 | rc = read(fd, fe, sizeof(struct tagfile_entry)); |
2157 | if (rc != sizeof(struct tagfile_entry)) | 2313 | if (rc != sizeof(struct tagfile_entry)) |
2158 | { | 2314 | { |
@@ -2165,10 +2321,23 @@ static bool load_tagcache(void) | |||
2165 | /* We have a special handling for the filename tags. */ | 2321 | /* We have a special handling for the filename tags. */ |
2166 | if (i == tag_filename) | 2322 | if (i == tag_filename) |
2167 | { | 2323 | { |
2324 | # ifdef HAVE_DIRCACHE | ||
2168 | const struct dircache_entry *dc; | 2325 | const struct dircache_entry *dc; |
2326 | # endif | ||
2169 | 2327 | ||
2328 | // FIXME: This is wrong! | ||
2329 | // idx = &hdr->indices[hdr->entry_count[i]]; | ||
2330 | idx = &hdr->indices[fe->idx_id]; | ||
2331 | |||
2332 | /* Check if the entry has already been removed */ | ||
2333 | if (idx->flag & FLAG_DELETED) | ||
2334 | continue; | ||
2335 | |||
2170 | if (fe->tag_length >= (long)sizeof(buf)-1) | 2336 | if (fe->tag_length >= (long)sizeof(buf)-1) |
2171 | { | 2337 | { |
2338 | read(fd, buf, 10); | ||
2339 | buf[10] = '\0'; | ||
2340 | logf("TAG:%s", buf); | ||
2172 | logf("too long filename"); | 2341 | logf("too long filename"); |
2173 | close(fd); | 2342 | close(fd); |
2174 | return false; | 2343 | return false; |
@@ -2182,22 +2351,47 @@ static bool load_tagcache(void) | |||
2182 | return false; | 2351 | return false; |
2183 | } | 2352 | } |
2184 | 2353 | ||
2185 | dc = dircache_get_entry_ptr(buf); | 2354 | # ifdef HAVE_DIRCACHE |
2186 | if (dc == NULL) | 2355 | if (dircache_is_enabled()) |
2187 | { | 2356 | { |
2188 | logf("Entry no longer valid."); | 2357 | dc = dircache_get_entry_ptr(buf); |
2189 | logf("-> %s", buf); | 2358 | if (dc == NULL) |
2190 | /* FIXME: Properly delete the entry. */ | 2359 | { |
2191 | hdr->indices[hdr->entry_count[i]].flag |= FLAG_DELETED; | 2360 | logf("Entry no longer valid."); |
2192 | continue ; | 2361 | logf("-> %s", buf); |
2362 | idx->flag |= FLAG_DELETED; | ||
2363 | delete_entry(fe->idx_id); | ||
2364 | continue ; | ||
2365 | } | ||
2366 | |||
2367 | idx->flag |= FLAG_DIRCACHE; | ||
2368 | idx->tag_seek[tag_filename] = (long)dc; | ||
2369 | } | ||
2370 | else | ||
2371 | # endif | ||
2372 | { | ||
2373 | /* Check if entry has been removed. */ | ||
2374 | if (global_settings.tagcache_autoupdate) | ||
2375 | { | ||
2376 | int testfd; | ||
2377 | |||
2378 | testfd = open(buf, O_RDONLY); | ||
2379 | if (testfd < 0) | ||
2380 | { | ||
2381 | logf("Entry no longer valid."); | ||
2382 | logf("-> %s", buf); | ||
2383 | idx->flag |= FLAG_DELETED; | ||
2384 | delete_entry((long)idx - (long)hdr->indices); | ||
2385 | continue; | ||
2386 | } | ||
2387 | } | ||
2388 | |||
2389 | idx->tag_seek[i] = pos; | ||
2193 | } | 2390 | } |
2194 | |||
2195 | hdr->indices[hdr->entry_count[i]].tag_seek[tag_filename] | ||
2196 | = (long)dc; | ||
2197 | 2391 | ||
2198 | continue ; | 2392 | continue ; |
2199 | } | 2393 | } |
2200 | 2394 | ||
2201 | bytesleft -= sizeof(struct tagfile_entry) + fe->tag_length; | 2395 | bytesleft -= sizeof(struct tagfile_entry) + fe->tag_length; |
2202 | if (bytesleft < 0) | 2396 | if (bytesleft < 0) |
2203 | { | 2397 | { |
@@ -2231,7 +2425,59 @@ static bool load_tagcache(void) | |||
2231 | 2425 | ||
2232 | return true; | 2426 | return true; |
2233 | } | 2427 | } |
2234 | #endif | 2428 | #endif /* HAVE_TC_RAMCACHE */ |
2429 | |||
2430 | static bool check_deleted_files(void) | ||
2431 | { | ||
2432 | int fd, testfd; | ||
2433 | char buf[MAX_PATH]; | ||
2434 | struct tagfile_entry tfe; | ||
2435 | |||
2436 | logf("reverse scan..."); | ||
2437 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag_filename); | ||
2438 | fd = open(buf, O_RDONLY); | ||
2439 | |||
2440 | if (fd < 0) | ||
2441 | { | ||
2442 | logf("%s open fail", buf); | ||
2443 | return false; | ||
2444 | } | ||
2445 | |||
2446 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | ||
2447 | while (read(fd, &tfe, sizeof(struct tagfile_entry)) | ||
2448 | == sizeof(struct tagfile_entry) && queue_empty(&tagcache_queue)) | ||
2449 | { | ||
2450 | if (tfe.tag_length >= (long)sizeof(buf)-1) | ||
2451 | { | ||
2452 | logf("too long tag"); | ||
2453 | close(fd); | ||
2454 | return false; | ||
2455 | } | ||
2456 | |||
2457 | if (read(fd, buf, tfe.tag_length) != tfe.tag_length) | ||
2458 | { | ||
2459 | logf("read error"); | ||
2460 | close(fd); | ||
2461 | return false; | ||
2462 | } | ||
2463 | |||
2464 | /* Now check if the file exists. */ | ||
2465 | testfd = open(buf, O_RDONLY); | ||
2466 | if (testfd < 0) | ||
2467 | { | ||
2468 | logf("Entry no longer valid."); | ||
2469 | logf("-> %s", buf); | ||
2470 | delete_entry(tfe.idx_id); | ||
2471 | } | ||
2472 | close(testfd); | ||
2473 | } | ||
2474 | |||
2475 | close(fd); | ||
2476 | |||
2477 | logf("done"); | ||
2478 | |||
2479 | return true; | ||
2480 | } | ||
2235 | 2481 | ||
2236 | static bool check_dir(const char *dirname) | 2482 | static bool check_dir(const char *dirname) |
2237 | { | 2483 | { |
@@ -2273,7 +2519,7 @@ static bool check_dir(const char *dirname) | |||
2273 | if (entry->attribute & ATTR_DIRECTORY) | 2519 | if (entry->attribute & ATTR_DIRECTORY) |
2274 | check_dir(curpath); | 2520 | check_dir(curpath); |
2275 | else | 2521 | else |
2276 | #ifdef HAVE_TC_RAMCACHE | 2522 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
2277 | add_tagcache(curpath, dir->internal_entry); | 2523 | add_tagcache(curpath, dir->internal_entry); |
2278 | #else | 2524 | #else |
2279 | add_tagcache(curpath); | 2525 | add_tagcache(curpath); |
@@ -2423,25 +2669,41 @@ static void tagcache_thread(void) | |||
2423 | check_done = false; | 2669 | check_done = false; |
2424 | break ; | 2670 | break ; |
2425 | 2671 | ||
2426 | case Q_FORCE_UPDATE: | 2672 | case Q_REBUILD: |
2427 | //remove_files(); | 2673 | remove_files(); |
2674 | build_tagcache(); | ||
2675 | break; | ||
2676 | |||
2677 | case Q_UPDATE: | ||
2428 | build_tagcache(); | 2678 | build_tagcache(); |
2679 | check_deleted_files(); | ||
2429 | break ; | 2680 | break ; |
2430 | 2681 | ||
2431 | #ifdef HAVE_TC_RAMCACHE | ||
2432 | case SYS_TIMEOUT: | 2682 | case SYS_TIMEOUT: |
2433 | if (check_done || !dircache_is_enabled()) | 2683 | if (check_done) |
2434 | break ; | 2684 | break ; |
2435 | 2685 | ||
2686 | #ifdef HAVE_TC_RAMCACHE | ||
2436 | if (!stat.ramcache && global_settings.tagcache_ram) | 2687 | if (!stat.ramcache && global_settings.tagcache_ram) |
2688 | { | ||
2437 | load_ramcache(); | 2689 | load_ramcache(); |
2438 | 2690 | if (stat.ramcache) | |
2439 | if (stat.ramcache) | 2691 | build_tagcache(); |
2692 | } | ||
2693 | else | ||
2694 | #endif | ||
2695 | if (global_settings.tagcache_autoupdate) | ||
2696 | { | ||
2440 | build_tagcache(); | 2697 | build_tagcache(); |
2698 | /* Don't do auto removal without dircache (very slow). */ | ||
2699 | #ifdef HAVE_DIRCACHE | ||
2700 | if (dircache_is_enabled()) | ||
2701 | check_deleted_files(); | ||
2702 | #endif | ||
2703 | } | ||
2441 | 2704 | ||
2442 | check_done = true; | 2705 | check_done = true; |
2443 | break ; | 2706 | break ; |
2444 | #endif | ||
2445 | 2707 | ||
2446 | case Q_STOP_SCAN: | 2708 | case Q_STOP_SCAN: |
2447 | break ; | 2709 | break ; |
@@ -2470,6 +2732,8 @@ static int get_progress(void) | |||
2470 | total_count = dircache_get_entry_count(); | 2732 | total_count = dircache_get_entry_count(); |
2471 | } | 2733 | } |
2472 | else | 2734 | else |
2735 | #endif | ||
2736 | #ifdef HAVE_TC_RAMCACHE | ||
2473 | { | 2737 | { |
2474 | if (hdr && stat.ramcache) | 2738 | if (hdr && stat.ramcache) |
2475 | total_count = hdr->h.entry_count; | 2739 | total_count = hdr->h.entry_count; |
@@ -2495,9 +2759,17 @@ void tagcache_start_scan(void) | |||
2495 | queue_post(&tagcache_queue, Q_START_SCAN, 0); | 2759 | queue_post(&tagcache_queue, Q_START_SCAN, 0); |
2496 | } | 2760 | } |
2497 | 2761 | ||
2498 | bool tagcache_force_update(void) | 2762 | bool tagcache_update(void) |
2763 | { | ||
2764 | queue_post(&tagcache_queue, Q_UPDATE, 0); | ||
2765 | gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); | ||
2766 | |||
2767 | return false; | ||
2768 | } | ||
2769 | |||
2770 | bool tagcache_rebuild(void) | ||
2499 | { | 2771 | { |
2500 | queue_post(&tagcache_queue, Q_FORCE_UPDATE, 0); | 2772 | queue_post(&tagcache_queue, Q_REBUILD, 0); |
2501 | gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); | 2773 | gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); |
2502 | 2774 | ||
2503 | return false; | 2775 | return false; |