summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/tagcache.c1074
1 files changed, 537 insertions, 537 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index e6a4e8e3c4..4c09336641 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -21,12 +21,12 @@
21 21
22/* 22/*
23 * TagCache API 23 * TagCache API
24 * 24 *
25 * ----------x---------x------------------x----- 25 * ----------x---------x------------------x-----
26 * | | | External 26 * | | | External
27 * +---------------x-------+ | TagCache | Libraries 27 * +---------------x-------+ | TagCache | Libraries
28 * | Modification routines | | Core | 28 * | Modification routines | | Core |
29 * +-x---------x-----------+ | | 29 * +-x---------x-----------+ | |
30 * | (R/W) | | | | 30 * | (R/W) | | | |
31 * | +------x-------------x-+ +-------------x-----+ | 31 * | +------x-------------x-+ +-------------x-----+ |
32 * | | x==x Filters & clauses | | 32 * | | x==x Filters & clauses | |
@@ -50,9 +50,9 @@
50 * +-----------------+ \===x | | 50 * +-----------------+ \===x | |
51 * | | | | (R) | Ram DB Loader x============x DirCache 51 * | | | | (R) | Ram DB Loader x============x DirCache
52 * +-x----x---x---x---+ /==x | | (optional) 52 * +-x----x---x---x---+ /==x | | (optional)
53 * | Tagcache Disk DB x==/ +-----------------+ | 53 * | Tagcache Disk DB x==/ +-----------------+ |
54 * +------------------+ | 54 * +------------------+ |
55 * 55 *
56 */ 56 */
57 57
58/*#define LOGF_ENABLE*/ 58/*#define LOGF_ENABLE*/
@@ -131,9 +131,9 @@ static int tempbuf_handle;
131 (1LU << tag_albumartist) | (1LU << tag_grouping)) 131 (1LU << tag_albumartist) | (1LU << tag_grouping))
132 132
133/* String presentation of the tags defined in tagcache.h. Must be in correct order! */ 133/* String presentation of the tags defined in tagcache.h. Must be in correct order! */
134static const char *tags_str[] = { "artist", "album", "genre", "title", 134static const char *tags_str[] = { "artist", "album", "genre", "title",
135 "filename", "composer", "comment", "albumartist", "grouping", "year", 135 "filename", "composer", "comment", "albumartist", "grouping", "year",
136 "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating", 136 "discnumber", "tracknumber", "bitrate", "length", "playcount", "rating",
137 "playtime", "lastplayed", "commitid", "mtime", "lastelapsed", "lastoffset" }; 137 "playtime", "lastplayed", "commitid", "mtime", "lastelapsed", "lastoffset" };
138 138
139/* Status information of the tagcache. */ 139/* Status information of the tagcache. */
@@ -146,7 +146,7 @@ enum tagcache_queue {
146 Q_IMPORT_CHANGELOG, 146 Q_IMPORT_CHANGELOG,
147 Q_UPDATE, 147 Q_UPDATE,
148 Q_REBUILD, 148 Q_REBUILD,
149 149
150 /* Internal tagcache command queue. */ 150 /* Internal tagcache command queue. */
151 CMD_UPDATE_MASTER_HEADER, 151 CMD_UPDATE_MASTER_HEADER,
152 CMD_UPDATE_NUMERIC, 152 CMD_UPDATE_NUMERIC,
@@ -263,14 +263,14 @@ static inline void tcrc_buffer_unlock(void)
263 263
264#endif /* HAVE_TC_RAMCACHE */ 264#endif /* HAVE_TC_RAMCACHE */
265 265
266/** 266/**
267 * Full tag entries stored in a temporary file waiting 267 * Full tag entries stored in a temporary file waiting
268 * for commit to the cache. */ 268 * for commit to the cache. */
269struct temp_file_entry { 269struct temp_file_entry {
270 long tag_offset[TAG_COUNT]; 270 long tag_offset[TAG_COUNT];
271 short tag_length[TAG_COUNT]; 271 short tag_length[TAG_COUNT];
272 long flag; 272 long flag;
273 273
274 long data_length; 274 long data_length;
275}; 275};
276 276
@@ -364,12 +364,12 @@ static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
364 int fd; 364 int fd;
365 char buf[MAX_PATH]; 365 char buf[MAX_PATH];
366 int rc; 366 int rc;
367 367
368 if (TAGCACHE_IS_NUMERIC(tag) || tag < 0 || tag >= TAG_COUNT) 368 if (TAGCACHE_IS_NUMERIC(tag) || tag < 0 || tag >= TAG_COUNT)
369 return -1; 369 return -1;
370 370
371 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag); 371 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag);
372 372
373 fd = open(buf, write ? O_RDWR : O_RDONLY); 373 fd = open(buf, write ? O_RDWR : O_RDONLY);
374 if (fd < 0) 374 if (fd < 0)
375 { 375 {
@@ -377,7 +377,7 @@ static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
377 tc_stat.ready = false; 377 tc_stat.ready = false;
378 return fd; 378 return fd;
379 } 379 }
380 380
381 /* Check the header. */ 381 /* Check the header. */
382 rc = ecread(fd, hdr, 1, tagcache_header_ec, tc_stat.econ); 382 rc = ecread(fd, hdr, 1, tagcache_header_ec, tc_stat.econ);
383 if (hdr->magic != TAGCACHE_MAGIC || rc != sizeof(struct tagcache_header)) 383 if (hdr->magic != TAGCACHE_MAGIC || rc != sizeof(struct tagcache_header))
@@ -395,7 +395,7 @@ static int open_master_fd(struct master_header *hdr, bool write)
395{ 395{
396 int fd; 396 int fd;
397 int rc; 397 int rc;
398 398
399 fd = open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY); 399 fd = open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY);
400 if (fd < 0) 400 if (fd < 0)
401 { 401 {
@@ -403,9 +403,9 @@ static int open_master_fd(struct master_header *hdr, bool write)
403 tc_stat.ready = false; 403 tc_stat.ready = false;
404 return fd; 404 return fd;
405 } 405 }
406 406
407 tc_stat.econ = false; 407 tc_stat.econ = false;
408 408
409 /* Check the header. */ 409 /* Check the header. */
410 rc = read(fd, hdr, sizeof(struct master_header)); 410 rc = read(fd, hdr, sizeof(struct master_header));
411 if (hdr->tch.magic == TAGCACHE_MAGIC && rc == sizeof(struct master_header)) 411 if (hdr->tch.magic == TAGCACHE_MAGIC && rc == sizeof(struct master_header))
@@ -413,10 +413,10 @@ static int open_master_fd(struct master_header *hdr, bool write)
413 /* Success. */ 413 /* Success. */
414 return fd; 414 return fd;
415 } 415 }
416 416
417 /* Trying to read again, this time with endianess correction enabled. */ 417 /* Trying to read again, this time with endianess correction enabled. */
418 lseek(fd, 0, SEEK_SET); 418 lseek(fd, 0, SEEK_SET);
419 419
420 rc = ecread(fd, hdr, 1, master_header_ec, true); 420 rc = ecread(fd, hdr, 1, master_header_ec, true);
421 if (hdr->tch.magic != TAGCACHE_MAGIC || rc != sizeof(struct master_header)) 421 if (hdr->tch.magic != TAGCACHE_MAGIC || rc != sizeof(struct master_header))
422 { 422 {
@@ -427,7 +427,7 @@ static int open_master_fd(struct master_header *hdr, bool write)
427 } 427 }
428 428
429 tc_stat.econ = true; 429 tc_stat.econ = true;
430 430
431 return fd; 431 return fd;
432} 432}
433 433
@@ -453,7 +453,7 @@ static long find_entry_ram(const char *filename)
453{ 453{
454 static long last_pos = 0; 454 static long last_pos = 0;
455 struct dircache_fileref dcfref; 455 struct dircache_fileref dcfref;
456 456
457 /* Check if tagcache is loaded into ram. */ 457 /* Check if tagcache is loaded into ram. */
458 if (!tc_stat.ramcache) 458 if (!tc_stat.ramcache)
459 return -1; 459 return -1;
@@ -520,7 +520,7 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
520 520
521 if (!tc_stat.ready) 521 if (!tc_stat.ready)
522 return -2; 522 return -2;
523 523
524 fd = filenametag_fd; 524 fd = filenametag_fd;
525 if (fd < 0 || localfd) 525 if (fd < 0 || localfd)
526 { 526 {
@@ -528,9 +528,9 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
528 if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0) 528 if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0)
529 return -1; 529 return -1;
530 } 530 }
531 531
532 check_again: 532 check_again:
533 533
534 if (last_pos > 0) 534 if (last_pos > 0)
535 lseek(fd, last_pos, SEEK_SET); 535 lseek(fd, last_pos, SEEK_SET);
536 else 536 else
@@ -543,12 +543,12 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
543 pos_history[i+1] = pos_history[i]; 543 pos_history[i+1] = pos_history[i];
544 pos_history[0] = pos; 544 pos_history[0] = pos;
545 545
546 if (ecread_tagfile_entry(fd, &tfe) 546 if (ecread_tagfile_entry(fd, &tfe)
547 != sizeof(struct tagfile_entry)) 547 != sizeof(struct tagfile_entry))
548 { 548 {
549 break ; 549 break ;
550 } 550 }
551 551
552 if (tfe.tag_length >= (long)sizeof(buf)) 552 if (tfe.tag_length >= (long)sizeof(buf))
553 { 553 {
554 logf("too long tag #1"); 554 logf("too long tag #1");
@@ -558,7 +558,7 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
558 last_pos = -1; 558 last_pos = -1;
559 return -2; 559 return -2;
560 } 560 }
561 561
562 if (read(fd, buf, tfe.tag_length) != tfe.tag_length) 562 if (read(fd, buf, tfe.tag_length) != tfe.tag_length)
563 { 563 {
564 logf("read error #2"); 564 logf("read error #2");
@@ -568,18 +568,18 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
568 last_pos = -1; 568 last_pos = -1;
569 return -3; 569 return -3;
570 } 570 }
571 571
572 if (!strcmp(filename, buf)) 572 if (!strcmp(filename, buf))
573 { 573 {
574 last_pos = pos_history[pos_history_idx]; 574 last_pos = pos_history[pos_history_idx];
575 found = true; 575 found = true;
576 break ; 576 break ;
577 } 577 }
578 578
579 if (pos_history_idx < POS_HISTORY_COUNT - 1) 579 if (pos_history_idx < POS_HISTORY_COUNT - 1)
580 pos_history_idx++; 580 pos_history_idx++;
581 } 581 }
582 582
583 /* Not found? */ 583 /* Not found? */
584 if (!found) 584 if (!found)
585 { 585 {
@@ -589,63 +589,63 @@ static long find_entry_disk(const char *filename_raw, bool localfd)
589 logf("seek again"); 589 logf("seek again");
590 goto check_again; 590 goto check_again;
591 } 591 }
592 592
593 if (fd != filenametag_fd || localfd) 593 if (fd != filenametag_fd || localfd)
594 close(fd); 594 close(fd);
595 return -4; 595 return -4;
596 } 596 }
597 597
598 if (fd != filenametag_fd || localfd) 598 if (fd != filenametag_fd || localfd)
599 close(fd); 599 close(fd);
600 600
601 return tfe.idx_id; 601 return tfe.idx_id;
602} 602}
603 603
604static int find_index(const char *filename) 604static int find_index(const char *filename)
605{ 605{
606 long idx_id = -1; 606 long idx_id = -1;
607 607
608#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 608#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
609 idx_id = find_entry_ram(filename); 609 idx_id = find_entry_ram(filename);
610#endif 610#endif
611 611
612 if (idx_id < 0) 612 if (idx_id < 0)
613 idx_id = find_entry_disk(filename, true); 613 idx_id = find_entry_disk(filename, true);
614 614
615 return idx_id; 615 return idx_id;
616} 616}
617 617
618bool tagcache_find_index(struct tagcache_search *tcs, const char *filename) 618bool tagcache_find_index(struct tagcache_search *tcs, const char *filename)
619{ 619{
620 int idx_id; 620 int idx_id;
621 621
622 if (!tc_stat.ready) 622 if (!tc_stat.ready)
623 return false; 623 return false;
624 624
625 idx_id = find_index(filename); 625 idx_id = find_index(filename);
626 if (idx_id < 0) 626 if (idx_id < 0)
627 return false; 627 return false;
628 628
629 if (!tagcache_search(tcs, tag_filename)) 629 if (!tagcache_search(tcs, tag_filename))
630 return false; 630 return false;
631 631
632 tcs->entry_count = 0; 632 tcs->entry_count = 0;
633 tcs->idx_id = idx_id; 633 tcs->idx_id = idx_id;
634 634
635 return true; 635 return true;
636} 636}
637 637
638static bool get_index(int masterfd, int idxid, 638static bool get_index(int masterfd, int idxid,
639 struct index_entry *idx, bool use_ram) 639 struct index_entry *idx, bool use_ram)
640{ 640{
641 bool localfd = false; 641 bool localfd = false;
642 642
643 if (idxid < 0) 643 if (idxid < 0)
644 { 644 {
645 logf("Incorrect idxid: %d", idxid); 645 logf("Incorrect idxid: %d", idxid);
646 return false; 646 return false;
647 } 647 }
648 648
649#ifdef HAVE_TC_RAMCACHE 649#ifdef HAVE_TC_RAMCACHE
650 if (tc_stat.ramcache && use_ram) 650 if (tc_stat.ramcache && use_ram)
651 { 651 {
@@ -656,35 +656,35 @@ static bool get_index(int masterfd, int idxid,
656 return true; 656 return true;
657 } 657 }
658#endif /* HAVE_TC_RAMCACHE */ 658#endif /* HAVE_TC_RAMCACHE */
659 659
660 if (masterfd < 0) 660 if (masterfd < 0)
661 { 661 {
662 struct master_header tcmh; 662 struct master_header tcmh;
663 663
664 localfd = true; 664 localfd = true;
665 masterfd = open_master_fd(&tcmh, false); 665 masterfd = open_master_fd(&tcmh, false);
666 if (masterfd < 0) 666 if (masterfd < 0)
667 return false; 667 return false;
668 } 668 }
669 669
670 lseek(masterfd, idxid * sizeof(struct index_entry) 670 lseek(masterfd, idxid * sizeof(struct index_entry)
671 + sizeof(struct master_header), SEEK_SET); 671 + sizeof(struct master_header), SEEK_SET);
672 if (ecread_index_entry(masterfd, idx) 672 if (ecread_index_entry(masterfd, idx)
673 != sizeof(struct index_entry)) 673 != sizeof(struct index_entry))
674 { 674 {
675 logf("read error #3"); 675 logf("read error #3");
676 if (localfd) 676 if (localfd)
677 close(masterfd); 677 close(masterfd);
678 678
679 return false; 679 return false;
680 } 680 }
681 681
682 if (localfd) 682 if (localfd)
683 close(masterfd); 683 close(masterfd);
684 684
685 if (idx->flag & FLAG_DELETED) 685 if (idx->flag & FLAG_DELETED)
686 return false; 686 return false;
687 687
688 return true; 688 return true;
689 689
690 (void)use_ram; 690 (void)use_ram;
@@ -700,7 +700,7 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
700 logf("memory only flags!"); 700 logf("memory only flags!");
701 return false; 701 return false;
702 } 702 }
703 703
704#ifdef HAVE_TC_RAMCACHE 704#ifdef HAVE_TC_RAMCACHE
705 /* Only update numeric data. Writing the whole index to RAM by memcpy 705 /* Only update numeric data. Writing the whole index to RAM by memcpy
706 * destroys dircache pointers! 706 * destroys dircache pointers!
@@ -708,7 +708,7 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
708 if (tc_stat.ramcache) 708 if (tc_stat.ramcache)
709 { 709 {
710 struct index_entry *idx_ram = &tcramcache.hdr->indices[idxid]; 710 struct index_entry *idx_ram = &tcramcache.hdr->indices[idxid];
711 711
712 for (int tag = 0; tag < TAG_COUNT; tag++) 712 for (int tag = 0; tag < TAG_COUNT; tag++)
713 { 713 {
714 if (TAGCACHE_IS_NUMERIC(tag)) 714 if (TAGCACHE_IS_NUMERIC(tag))
@@ -716,14 +716,14 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
716 idx_ram->tag_seek[tag] = idx->tag_seek[tag]; 716 idx_ram->tag_seek[tag] = idx->tag_seek[tag];
717 } 717 }
718 } 718 }
719 719
720 /* Don't touch the dircache flag or attributes. */ 720 /* Don't touch the dircache flag or attributes. */
721 idx_ram->flag = (idx->flag & 0x0000ffff) 721 idx_ram->flag = (idx->flag & 0x0000ffff)
722 | (idx_ram->flag & (0xffff0000 | FLAG_DIRCACHE)); 722 | (idx_ram->flag & (0xffff0000 | FLAG_DIRCACHE));
723 } 723 }
724#endif /* HAVE_TC_RAMCACHE */ 724#endif /* HAVE_TC_RAMCACHE */
725 725
726 lseek(masterfd, idxid * sizeof(struct index_entry) 726 lseek(masterfd, idxid * sizeof(struct index_entry)
727 + sizeof(struct master_header), SEEK_SET); 727 + sizeof(struct master_header), SEEK_SET);
728 if (ecwrite_index_entry(masterfd, idx) != sizeof(struct index_entry)) 728 if (ecwrite_index_entry(masterfd, idx) != sizeof(struct index_entry))
729 { 729 {
@@ -731,7 +731,7 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
731 logf("idxid: %d", idxid); 731 logf("idxid: %d", idxid);
732 return false; 732 return false;
733 } 733 }
734 734
735 return true; 735 return true;
736} 736}
737 737
@@ -746,13 +746,13 @@ static bool open_files(struct tagcache_search *tcs, int tag)
746 snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag); 746 snprintf(fn, sizeof fn, TAGCACHE_FILE_INDEX, tag);
747 tcs->idxfd[tag] = open(fn, O_RDONLY); 747 tcs->idxfd[tag] = open(fn, O_RDONLY);
748 } 748 }
749 749
750 if (tcs->idxfd[tag] < 0) 750 if (tcs->idxfd[tag] < 0)
751 { 751 {
752 logf("File not open!"); 752 logf("File not open!");
753 return false; 753 return false;
754 } 754 }
755 755
756 return true; 756 return true;
757} 757}
758 758
@@ -761,19 +761,19 @@ static bool retrieve(struct tagcache_search *tcs, IF_DIRCACHE(int idx_id,)
761{ 761{
762 struct tagfile_entry tfe; 762 struct tagfile_entry tfe;
763 long seek; 763 long seek;
764 764
765 *buf = '\0'; 765 *buf = '\0';
766 766
767 if (TAGCACHE_IS_NUMERIC(tag)) 767 if (TAGCACHE_IS_NUMERIC(tag))
768 return false; 768 return false;
769 769
770 seek = idx->tag_seek[tag]; 770 seek = idx->tag_seek[tag];
771 if (seek < 0) 771 if (seek < 0)
772 { 772 {
773 logf("Retrieve failed"); 773 logf("Retrieve failed");
774 return false; 774 return false;
775 } 775 }
776 776
777#ifdef HAVE_TC_RAMCACHE 777#ifdef HAVE_TC_RAMCACHE
778 if (tcs->ramsearch) 778 if (tcs->ramsearch)
779 { 779 {
@@ -790,36 +790,36 @@ static bool retrieve(struct tagcache_search *tcs, IF_DIRCACHE(int idx_id,)
790 struct tagfile_entry *ep = 790 struct tagfile_entry *ep =
791 (struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek]; 791 (struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek];
792 strlcpy(buf, ep->tag_data, size); 792 strlcpy(buf, ep->tag_data, size);
793 793
794 return true; 794 return true;
795 } 795 }
796 } 796 }
797#endif /* HAVE_TC_RAMCACHE */ 797#endif /* HAVE_TC_RAMCACHE */
798 798
799 if (!open_files(tcs, tag)) 799 if (!open_files(tcs, tag))
800 return false; 800 return false;
801 801
802 lseek(tcs->idxfd[tag], seek, SEEK_SET); 802 lseek(tcs->idxfd[tag], seek, SEEK_SET);
803 if (ecread_tagfile_entry(tcs->idxfd[tag], &tfe) 803 if (ecread_tagfile_entry(tcs->idxfd[tag], &tfe)
804 != sizeof(struct tagfile_entry)) 804 != sizeof(struct tagfile_entry))
805 { 805 {
806 logf("read error #5"); 806 logf("read error #5");
807 return false; 807 return false;
808 } 808 }
809 809
810 if (tfe.tag_length >= size) 810 if (tfe.tag_length >= size)
811 { 811 {
812 logf("too small buffer"); 812 logf("too small buffer");
813 return false; 813 return false;
814 } 814 }
815 815
816 if (read(tcs->idxfd[tag], buf, tfe.tag_length) != 816 if (read(tcs->idxfd[tag], buf, tfe.tag_length) !=
817 tfe.tag_length) 817 tfe.tag_length)
818 { 818 {
819 logf("read error #6"); 819 logf("read error #6");
820 return false; 820 return false;
821 } 821 }
822 822
823 buf[tfe.tag_length] = '\0'; 823 buf[tfe.tag_length] = '\0';
824 824
825 return true; 825 return true;
@@ -844,7 +844,7 @@ static long find_tag(int tag, int idx_id, const struct index_entry *idx)
844 { 844 {
845 if (--ridx < 0) 845 if (--ridx < 0)
846 ridx = TAGCACHE_COMMAND_QUEUE_LENGTH - 1; 846 ridx = TAGCACHE_COMMAND_QUEUE_LENGTH - 1;
847 847
848 if (command_queue[ridx].command == CMD_UPDATE_NUMERIC 848 if (command_queue[ridx].command == CMD_UPDATE_NUMERIC
849 && command_queue[ridx].idx_id == idx_id 849 && command_queue[ridx].idx_id == idx_id
850 && command_queue[ridx].tag == tag) 850 && command_queue[ridx].tag == tag)
@@ -872,31 +872,31 @@ static long find_tag(int tag, int idx_id, const struct index_entry *idx)
872} 872}
873 873
874 874
875static long check_virtual_tags(int tag, int idx_id, 875static long check_virtual_tags(int tag, int idx_id,
876 const struct index_entry *idx) 876 const struct index_entry *idx)
877{ 877{
878 long data = 0; 878 long data = 0;
879 879
880 switch (tag) 880 switch (tag)
881 { 881 {
882 case tag_virt_length_sec: 882 case tag_virt_length_sec:
883 data = (find_tag(tag_length, idx_id, idx)/1000) % 60; 883 data = (find_tag(tag_length, idx_id, idx)/1000) % 60;
884 break; 884 break;
885 885
886 case tag_virt_length_min: 886 case tag_virt_length_min:
887 data = (find_tag(tag_length, idx_id, idx)/1000) / 60; 887 data = (find_tag(tag_length, idx_id, idx)/1000) / 60;
888 break; 888 break;
889 889
890 case tag_virt_playtime_sec: 890 case tag_virt_playtime_sec:
891 data = (find_tag(tag_playtime, idx_id, idx)/1000) % 60; 891 data = (find_tag(tag_playtime, idx_id, idx)/1000) % 60;
892 break; 892 break;
893 893
894 case tag_virt_playtime_min: 894 case tag_virt_playtime_min:
895 data = (find_tag(tag_playtime, idx_id, idx)/1000) / 60; 895 data = (find_tag(tag_playtime, idx_id, idx)/1000) / 60;
896 break; 896 break;
897 897
898 case tag_virt_autoscore: 898 case tag_virt_autoscore:
899 if (find_tag(tag_length, idx_id, idx) == 0 899 if (find_tag(tag_length, idx_id, idx) == 0
900 || find_tag(tag_playcount, idx_id, idx) == 0) 900 || find_tag(tag_playcount, idx_id, idx) == 0)
901 { 901 {
902 data = 0; 902 data = 0;
@@ -913,21 +913,21 @@ static long check_virtual_tags(int tag, int idx_id,
913 autoscore = 100 * (alpha / playcout + beta / length / playcount) 913 autoscore = 100 * (alpha / playcout + beta / length / playcount)
914 Both terms should be small enough to avoid any overflow 914 Both terms should be small enough to avoid any overflow
915 */ 915 */
916 data = 100 * (find_tag(tag_playtime, idx_id, idx) 916 data = 100 * (find_tag(tag_playtime, idx_id, idx)
917 / find_tag(tag_length, idx_id, idx)) 917 / find_tag(tag_length, idx_id, idx))
918 + (100 * (find_tag(tag_playtime, idx_id, idx) 918 + (100 * (find_tag(tag_playtime, idx_id, idx)
919 % find_tag(tag_length, idx_id, idx))) 919 % find_tag(tag_length, idx_id, idx)))
920 / find_tag(tag_length, idx_id, idx); 920 / find_tag(tag_length, idx_id, idx);
921 data /= find_tag(tag_playcount, idx_id, idx); 921 data /= find_tag(tag_playcount, idx_id, idx);
922 } 922 }
923 break; 923 break;
924 924
925 /* How many commits before the file has been added to the DB. */ 925 /* How many commits before the file has been added to the DB. */
926 case tag_virt_entryage: 926 case tag_virt_entryage:
927 data = current_tcmh.commitid 927 data = current_tcmh.commitid
928 - find_tag(tag_commitid, idx_id, idx) - 1; 928 - find_tag(tag_commitid, idx_id, idx) - 1;
929 break; 929 break;
930 930
931 case tag_virt_basename: 931 case tag_virt_basename:
932 tag = tag_filename; /* return filename; caller handles basename */ 932 tag = tag_filename; /* return filename; caller handles basename */
933 /* FALLTHRU */ 933 /* FALLTHRU */
@@ -935,23 +935,23 @@ static long check_virtual_tags(int tag, int idx_id,
935 default: 935 default:
936 data = find_tag(tag, idx_id, idx); 936 data = find_tag(tag, idx_id, idx);
937 } 937 }
938 938
939 return data; 939 return data;
940} 940}
941 941
942long tagcache_get_numeric(const struct tagcache_search *tcs, int tag) 942long tagcache_get_numeric(const struct tagcache_search *tcs, int tag)
943{ 943{
944 struct index_entry idx; 944 struct index_entry idx;
945 945
946 if (!tc_stat.ready) 946 if (!tc_stat.ready)
947 return false; 947 return false;
948 948
949 if (!TAGCACHE_IS_NUMERIC(tag)) 949 if (!TAGCACHE_IS_NUMERIC(tag))
950 return -1; 950 return -1;
951 951
952 if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true)) 952 if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true))
953 return -2; 953 return -2;
954 954
955 return check_virtual_tags(tag, tcs->idx_id, &idx); 955 return check_virtual_tags(tag, tcs->idx_id, &idx);
956} 956}
957 957
@@ -959,10 +959,10 @@ inline static bool str_ends_with(const char *str1, const char *str2)
959{ 959{
960 int str_len = strlen(str1); 960 int str_len = strlen(str1);
961 int clause_len = strlen(str2); 961 int clause_len = strlen(str2);
962 962
963 if (clause_len > str_len) 963 if (clause_len > str_len)
964 return false; 964 return false;
965 965
966 return !strcasecmp(&str1[str_len - clause_len], str2); 966 return !strcasecmp(&str1[str_len - clause_len], str2);
967} 967}
968 968
@@ -970,7 +970,7 @@ inline static bool str_oneof(const char *str, const char *list)
970{ 970{
971 const char *sep; 971 const char *sep;
972 int l, len = strlen(str); 972 int l, len = strlen(str);
973 973
974 while (*list) 974 while (*list)
975 { 975 {
976 sep = strchr(list, '|'); 976 sep = strchr(list, '|');
@@ -1001,7 +1001,7 @@ static bool check_against_clause(long numeric, const char *str,
1001 case clause_lt: 1001 case clause_lt:
1002 return numeric < clause->numeric_data; 1002 return numeric < clause->numeric_data;
1003 case clause_lteq: 1003 case clause_lteq:
1004 return numeric <= clause->numeric_data; 1004 return numeric <= clause->numeric_data;
1005 default: 1005 default:
1006 logf("Incorrect numeric tag: %d", clause->type); 1006 logf("Incorrect numeric tag: %d", clause->type);
1007 } 1007 }
@@ -1036,7 +1036,7 @@ static bool check_against_clause(long numeric, const char *str,
1036 return !str_ends_with(str, clause->str); 1036 return !str_ends_with(str, clause->str);
1037 case clause_oneof: 1037 case clause_oneof:
1038 return str_oneof(str, clause->str); 1038 return str_oneof(str, clause->str);
1039 1039
1040 default: 1040 default:
1041 logf("Incorrect tag: %d", clause->type); 1041 logf("Incorrect tag: %d", clause->type);
1042 } 1042 }
@@ -1050,7 +1050,7 @@ static bool check_clauses(struct tagcache_search *tcs,
1050 struct tagcache_search_clause **clauses, int count) 1050 struct tagcache_search_clause **clauses, int count)
1051{ 1051{
1052 int i; 1052 int i;
1053 1053
1054 /* Go through all conditional clauses. */ 1054 /* Go through all conditional clauses. */
1055 for (i = 0; i < count; i++) 1055 for (i = 0; i < count; i++)
1056 { 1056 {
@@ -1058,7 +1058,7 @@ static bool check_clauses(struct tagcache_search *tcs,
1058 char buf[256]; 1058 char buf[256];
1059 char *str = buf; 1059 char *str = buf;
1060 struct tagcache_search_clause *clause = clauses[i]; 1060 struct tagcache_search_clause *clause = clauses[i];
1061 1061
1062 if (clause->type == clause_logical_or) 1062 if (clause->type == clause_logical_or)
1063 break; /* all conditions before logical-or satisfied -- 1063 break; /* all conditions before logical-or satisfied --
1064 stop processing clauses */ 1064 stop processing clauses */
@@ -1069,7 +1069,7 @@ static bool check_clauses(struct tagcache_search *tcs,
1069 if (tcs->ramsearch) 1069 if (tcs->ramsearch)
1070 { 1070 {
1071 struct tagfile_entry *tfe; 1071 struct tagfile_entry *tfe;
1072 1072
1073 if (!TAGCACHE_IS_NUMERIC(clause->tag)) 1073 if (!TAGCACHE_IS_NUMERIC(clause->tag))
1074 { 1074 {
1075 if (clause->tag == tag_filename 1075 if (clause->tag == tag_filename
@@ -1092,7 +1092,7 @@ static bool check_clauses(struct tagcache_search *tcs,
1092#endif /* HAVE_TC_RAMCACHE */ 1092#endif /* HAVE_TC_RAMCACHE */
1093 { 1093 {
1094 struct tagfile_entry tfe; 1094 struct tagfile_entry tfe;
1095 1095
1096 if (!TAGCACHE_IS_NUMERIC(clause->tag)) 1096 if (!TAGCACHE_IS_NUMERIC(clause->tag))
1097 { 1097 {
1098 int tag = clause->tag; 1098 int tag = clause->tag;
@@ -1110,7 +1110,7 @@ static bool check_clauses(struct tagcache_search *tcs,
1110 1110
1111 read(fd, str, tfe.tag_length); 1111 read(fd, str, tfe.tag_length);
1112 str[tfe.tag_length] = '\0'; 1112 str[tfe.tag_length] = '\0';
1113 1113
1114 /* Check if entry has been deleted. */ 1114 /* Check if entry has been deleted. */
1115 if (str[0] == '\0') 1115 if (str[0] == '\0')
1116 return false; 1116 return false;
@@ -1132,14 +1132,14 @@ static bool check_clauses(struct tagcache_search *tcs,
1132 if (clauses[i]->type == clause_logical_or) 1132 if (clauses[i]->type == clause_logical_or)
1133 break; 1133 break;
1134 } 1134 }
1135 1135
1136 if (i < count) /* Found logical-or? */ 1136 if (i < count) /* Found logical-or? */
1137 continue; /* Check clauses after logical-or */ 1137 continue; /* Check clauses after logical-or */
1138 1138
1139 return false; 1139 return false;
1140 } 1140 }
1141 } 1141 }
1142 1142
1143 return true; 1143 return true;
1144} 1144}
1145 1145
@@ -1147,40 +1147,40 @@ bool tagcache_check_clauses(struct tagcache_search *tcs,
1147 struct tagcache_search_clause **clause, int count) 1147 struct tagcache_search_clause **clause, int count)
1148{ 1148{
1149 struct index_entry idx; 1149 struct index_entry idx;
1150 1150
1151 if (count == 0) 1151 if (count == 0)
1152 return true; 1152 return true;
1153 1153
1154 if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true)) 1154 if (!get_index(tcs->masterfd, tcs->idx_id, &idx, true))
1155 return false; 1155 return false;
1156 1156
1157 return check_clauses(tcs, &idx, clause, count); 1157 return check_clauses(tcs, &idx, clause, count);
1158} 1158}
1159 1159
1160static bool add_uniqbuf(struct tagcache_search *tcs, unsigned long id) 1160static bool add_uniqbuf(struct tagcache_search *tcs, unsigned long id)
1161{ 1161{
1162 int i; 1162 int i;
1163 1163
1164 /* If uniq buffer is not defined we must return true for search to work. */ 1164 /* If uniq buffer is not defined we must return true for search to work. */
1165 if (tcs->unique_list == NULL || (!TAGCACHE_IS_UNIQUE(tcs->type) 1165 if (tcs->unique_list == NULL || (!TAGCACHE_IS_UNIQUE(tcs->type)
1166 && !TAGCACHE_IS_NUMERIC(tcs->type))) 1166 && !TAGCACHE_IS_NUMERIC(tcs->type)))
1167 { 1167 {
1168 return true; 1168 return true;
1169 } 1169 }
1170 1170
1171 for (i = 0; i < tcs->unique_list_count; i++) 1171 for (i = 0; i < tcs->unique_list_count; i++)
1172 { 1172 {
1173 /* Return false if entry is found. */ 1173 /* Return false if entry is found. */
1174 if (tcs->unique_list[i] == id) 1174 if (tcs->unique_list[i] == id)
1175 return false; 1175 return false;
1176 } 1176 }
1177 1177
1178 if (tcs->unique_list_count < tcs->unique_list_capacity) 1178 if (tcs->unique_list_count < tcs->unique_list_capacity)
1179 { 1179 {
1180 tcs->unique_list[i] = id; 1180 tcs->unique_list[i] = id;
1181 tcs->unique_list_count++; 1181 tcs->unique_list_count++;
1182 } 1182 }
1183 1183
1184 return true; 1184 return true;
1185} 1185}
1186 1186
@@ -1188,9 +1188,9 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1188{ 1188{
1189 struct index_entry entry; 1189 struct index_entry entry;
1190 int i, j; 1190 int i, j;
1191 1191
1192 tcs->seek_list_count = 0; 1192 tcs->seek_list_count = 0;
1193 1193
1194#ifdef HAVE_TC_RAMCACHE 1194#ifdef HAVE_TC_RAMCACHE
1195 if (tcs->ramsearch) 1195 if (tcs->ramsearch)
1196 { 1196 {
@@ -1203,11 +1203,11 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1203 struct index_entry *idx = &tcramcache.hdr->indices[i]; 1203 struct index_entry *idx = &tcramcache.hdr->indices[i];
1204 if (tcs->seek_list_count == SEEK_LIST_SIZE) 1204 if (tcs->seek_list_count == SEEK_LIST_SIZE)
1205 break ; 1205 break ;
1206 1206
1207 /* Skip deleted files. */ 1207 /* Skip deleted files. */
1208 if (idx->flag & FLAG_DELETED) 1208 if (idx->flag & FLAG_DELETED)
1209 continue; 1209 continue;
1210 1210
1211 /* Go through all filters.. */ 1211 /* Go through all filters.. */
1212 for (j = 0; j < tcs->filter_count; j++) 1212 for (j = 0; j < tcs->filter_count; j++)
1213 { 1213 {
@@ -1216,7 +1216,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1216 break ; 1216 break ;
1217 } 1217 }
1218 } 1218 }
1219 1219
1220 if (j < tcs->filter_count) 1220 if (j < tcs->filter_count)
1221 continue ; 1221 continue ;
1222 1222
@@ -1226,7 +1226,7 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1226 /* Add to the seek list if not already in uniq buffer (doesn't yield)*/ 1226 /* Add to the seek list if not already in uniq buffer (doesn't yield)*/
1227 if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type])) 1227 if (!add_uniqbuf(tcs, idx->tag_seek[tcs->type]))
1228 continue; 1228 continue;
1229 1229
1230 /* Lets add it. */ 1230 /* Lets add it. */
1231 seeklist = &tcs->seeklist[tcs->seek_list_count]; 1231 seeklist = &tcs->seeklist[tcs->seek_list_count];
1232 seeklist->seek = idx->tag_seek[tcs->type]; 1232 seeklist->seek = idx->tag_seek[tcs->type];
@@ -1238,72 +1238,72 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1238 tcrc_buffer_unlock(); 1238 tcrc_buffer_unlock();
1239 1239
1240 tcs->seek_pos = i; 1240 tcs->seek_pos = i;
1241 1241
1242 return tcs->seek_list_count > 0; 1242 return tcs->seek_list_count > 0;
1243 } 1243 }
1244#endif /* HAVE_TC_RAMCACHE */ 1244#endif /* HAVE_TC_RAMCACHE */
1245 1245
1246 if (tcs->masterfd < 0) 1246 if (tcs->masterfd < 0)
1247 { 1247 {
1248 struct master_header tcmh; 1248 struct master_header tcmh;
1249 tcs->masterfd = open_master_fd(&tcmh, false); 1249 tcs->masterfd = open_master_fd(&tcmh, false);
1250 } 1250 }
1251 1251
1252 lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + 1252 lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) +
1253 sizeof(struct master_header), SEEK_SET); 1253 sizeof(struct master_header), SEEK_SET);
1254 1254
1255 while (ecread_index_entry(tcs->masterfd, &entry) 1255 while (ecread_index_entry(tcs->masterfd, &entry)
1256 == sizeof(struct index_entry)) 1256 == sizeof(struct index_entry))
1257 { 1257 {
1258 struct tagcache_seeklist_entry *seeklist; 1258 struct tagcache_seeklist_entry *seeklist;
1259 1259
1260 if (tcs->seek_list_count == SEEK_LIST_SIZE) 1260 if (tcs->seek_list_count == SEEK_LIST_SIZE)
1261 break ; 1261 break ;
1262 1262
1263 i = tcs->seek_pos; 1263 i = tcs->seek_pos;
1264 tcs->seek_pos++; 1264 tcs->seek_pos++;
1265 1265
1266 /* Check if entry has been deleted. */ 1266 /* Check if entry has been deleted. */
1267 if (entry.flag & FLAG_DELETED) 1267 if (entry.flag & FLAG_DELETED)
1268 continue; 1268 continue;
1269 1269
1270 /* Go through all filters.. */ 1270 /* Go through all filters.. */
1271 for (j = 0; j < tcs->filter_count; j++) 1271 for (j = 0; j < tcs->filter_count; j++)
1272 { 1272 {
1273 if (entry.tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j]) 1273 if (entry.tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j])
1274 break ; 1274 break ;
1275 } 1275 }
1276 1276
1277 if (j < tcs->filter_count) 1277 if (j < tcs->filter_count)
1278 continue ; 1278 continue ;
1279 1279
1280 /* Check for conditions. */ 1280 /* Check for conditions. */
1281 if (!check_clauses(tcs, &entry, tcs->clause, tcs->clause_count)) 1281 if (!check_clauses(tcs, &entry, tcs->clause, tcs->clause_count))
1282 continue; 1282 continue;
1283 1283
1284 /* Add to the seek list if not already in uniq buffer. */ 1284 /* Add to the seek list if not already in uniq buffer. */
1285 if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type])) 1285 if (!add_uniqbuf(tcs, entry.tag_seek[tcs->type]))
1286 continue; 1286 continue;
1287 1287
1288 /* Lets add it. */ 1288 /* Lets add it. */
1289 seeklist = &tcs->seeklist[tcs->seek_list_count]; 1289 seeklist = &tcs->seeklist[tcs->seek_list_count];
1290 seeklist->seek = entry.tag_seek[tcs->type]; 1290 seeklist->seek = entry.tag_seek[tcs->type];
1291 seeklist->flag = entry.flag; 1291 seeklist->flag = entry.flag;
1292 seeklist->idx_id = i; 1292 seeklist->idx_id = i;
1293 tcs->seek_list_count++; 1293 tcs->seek_list_count++;
1294 1294
1295 yield(); 1295 yield();
1296 } 1296 }
1297 1297
1298 return tcs->seek_list_count > 0; 1298 return tcs->seek_list_count > 0;
1299} 1299}
1300 1300
1301 1301
1302static void remove_files(void) 1302static void remove_files(void)
1303{ 1303{
1304 int i; 1304 int i;
1305 char buf[MAX_PATH]; 1305 char buf[MAX_PATH];
1306 1306
1307 tc_stat.ready = false; 1307 tc_stat.ready = false;
1308 tc_stat.ramcache = false; 1308 tc_stat.ramcache = false;
1309 tc_stat.econ = false; 1309 tc_stat.econ = false;
@@ -1312,7 +1312,7 @@ static void remove_files(void)
1312 { 1312 {
1313 if (TAGCACHE_IS_NUMERIC(i)) 1313 if (TAGCACHE_IS_NUMERIC(i))
1314 continue; 1314 continue;
1315 1315
1316 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i); 1316 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i);
1317 remove(buf); 1317 remove(buf);
1318 } 1318 }
@@ -1325,30 +1325,30 @@ static bool check_all_headers(void)
1325 struct tagcache_header tch; 1325 struct tagcache_header tch;
1326 int tag; 1326 int tag;
1327 int fd; 1327 int fd;
1328 1328
1329 if ( (fd = open_master_fd(&myhdr, false)) < 0) 1329 if ( (fd = open_master_fd(&myhdr, false)) < 0)
1330 return false; 1330 return false;
1331 1331
1332 close(fd); 1332 close(fd);
1333 if (myhdr.dirty) 1333 if (myhdr.dirty)
1334 { 1334 {
1335 logf("tagcache is dirty!"); 1335 logf("tagcache is dirty!");
1336 return false; 1336 return false;
1337 } 1337 }
1338 1338
1339 memcpy(&current_tcmh, &myhdr, sizeof(struct master_header)); 1339 memcpy(&current_tcmh, &myhdr, sizeof(struct master_header));
1340 1340
1341 for (tag = 0; tag < TAG_COUNT; tag++) 1341 for (tag = 0; tag < TAG_COUNT; tag++)
1342 { 1342 {
1343 if (TAGCACHE_IS_NUMERIC(tag)) 1343 if (TAGCACHE_IS_NUMERIC(tag))
1344 continue; 1344 continue;
1345 1345
1346 if ( (fd = open_tag_fd(&tch, tag, false)) < 0) 1346 if ( (fd = open_tag_fd(&tch, tag, false)) < 0)
1347 return false; 1347 return false;
1348 1348
1349 close(fd); 1349 close(fd);
1350 } 1350 }
1351 1351
1352 return true; 1352 return true;
1353} 1353}
1354 1354
@@ -1360,11 +1360,11 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
1360 1360
1361 while (read_lock) 1361 while (read_lock)
1362 sleep(1); 1362 sleep(1);
1363 1363
1364 memset(tcs, 0, sizeof(struct tagcache_search)); 1364 memset(tcs, 0, sizeof(struct tagcache_search));
1365 if (tc_stat.commit_step > 0 || !tc_stat.ready) 1365 if (tc_stat.commit_step > 0 || !tc_stat.ready)
1366 return false; 1366 return false;
1367 1367
1368 tcs->position = sizeof(struct tagcache_header); 1368 tcs->position = sizeof(struct tagcache_header);
1369 tcs->type = tag; 1369 tcs->type = tag;
1370 tcs->seek_pos = 0; 1370 tcs->seek_pos = 0;
@@ -1392,13 +1392,13 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
1392 tcs->masterfd = open_master_fd(&master_hdr, true); 1392 tcs->masterfd = open_master_fd(&master_hdr, true);
1393 if (tcs->masterfd < 0) 1393 if (tcs->masterfd < 0)
1394 return false; 1394 return false;
1395 1395
1396 if (!TAGCACHE_IS_NUMERIC(tcs->type)) 1396 if (!TAGCACHE_IS_NUMERIC(tcs->type))
1397 { 1397 {
1398 tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false); 1398 tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false);
1399 if (tcs->idxfd[tcs->type] < 0) 1399 if (tcs->idxfd[tcs->type] < 0)
1400 return false; 1400 return false;
1401 1401
1402 tcs->entry_count = tag_hdr.entry_count; 1402 tcs->entry_count = tag_hdr.entry_count;
1403 } 1403 }
1404 else 1404 else
@@ -1410,7 +1410,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
1410 tcs->valid = true; 1410 tcs->valid = true;
1411 tcs->initialized = true; 1411 tcs->initialized = true;
1412 write_lock++; 1412 write_lock++;
1413 1413
1414 return true; 1414 return true;
1415} 1415}
1416 1416
@@ -1430,7 +1430,7 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
1430 1430
1431 if (TAGCACHE_IS_NUMERIC_OR_NONUNIQUE(tag)) 1431 if (TAGCACHE_IS_NUMERIC_OR_NONUNIQUE(tag))
1432 return false; 1432 return false;
1433 1433
1434 tcs->filter_tag[tcs->filter_count] = tag; 1434 tcs->filter_tag[tcs->filter_count] = tag;
1435 tcs->filter_seek[tcs->filter_count] = seek; 1435 tcs->filter_seek[tcs->filter_count] = seek;
1436 tcs->filter_count++; 1436 tcs->filter_count++;
@@ -1442,7 +1442,7 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
1442 struct tagcache_search_clause *clause) 1442 struct tagcache_search_clause *clause)
1443{ 1443{
1444 int i; 1444 int i;
1445 1445
1446 if (tcs->clause_count >= TAGCACHE_MAX_CLAUSES) 1446 if (tcs->clause_count >= TAGCACHE_MAX_CLAUSES)
1447 { 1447 {
1448 logf("Too many clauses"); 1448 logf("Too many clauses");
@@ -1452,26 +1452,26 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
1452 if (clause->type != clause_logical_or) 1452 if (clause->type != clause_logical_or)
1453 { 1453 {
1454 /* Check if there is already a similar filter in present (filters are 1454 /* Check if there is already a similar filter in present (filters are
1455 * much faster than clauses). 1455 * much faster than clauses).
1456 */ 1456 */
1457 for (i = 0; i < tcs->filter_count; i++) 1457 for (i = 0; i < tcs->filter_count; i++)
1458 { 1458 {
1459 if (tcs->filter_tag[i] == clause->tag) 1459 if (tcs->filter_tag[i] == clause->tag)
1460 return true; 1460 return true;
1461 } 1461 }
1462 1462
1463 if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0) 1463 if (!TAGCACHE_IS_NUMERIC(clause->tag) && tcs->idxfd[clause->tag] < 0)
1464 { 1464 {
1465 char buf[MAX_PATH]; 1465 char buf[MAX_PATH];
1466 1466
1467 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag); 1467 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, clause->tag);
1468 tcs->idxfd[clause->tag] = open(buf, O_RDONLY); 1468 tcs->idxfd[clause->tag] = open(buf, O_RDONLY);
1469 } 1469 }
1470 } 1470 }
1471 1471
1472 tcs->clause[tcs->clause_count] = clause; 1472 tcs->clause[tcs->clause_count] = clause;
1473 tcs->clause_count++; 1473 tcs->clause_count++;
1474 1474
1475 return true; 1475 return true;
1476} 1476}
1477 1477
@@ -1485,14 +1485,14 @@ static bool get_next(struct tagcache_search *tcs)
1485 1485
1486 if (!tcs->valid || !tc_stat.ready) 1486 if (!tcs->valid || !tc_stat.ready)
1487 return false; 1487 return false;
1488 1488
1489 if (tcs->idxfd[tcs->type] < 0 && !TAGCACHE_IS_NUMERIC(tcs->type) 1489 if (tcs->idxfd[tcs->type] < 0 && !TAGCACHE_IS_NUMERIC(tcs->type)
1490#ifdef HAVE_TC_RAMCACHE 1490#ifdef HAVE_TC_RAMCACHE
1491 && !tcs->ramsearch 1491 && !tcs->ramsearch
1492#endif 1492#endif
1493 ) 1493 )
1494 return false; 1494 return false;
1495 1495
1496 /* Relative fetch. */ 1496 /* Relative fetch. */
1497 if (tcs->filter_count > 0 || tcs->clause_count > 0 1497 if (tcs->filter_count > 0 || tcs->clause_count > 0
1498 || TAGCACHE_IS_NUMERIC(tcs->type) 1498 || TAGCACHE_IS_NUMERIC(tcs->type)
@@ -1503,12 +1503,12 @@ static bool get_next(struct tagcache_search *tcs)
1503 ) 1503 )
1504 { 1504 {
1505 struct tagcache_seeklist_entry *seeklist; 1505 struct tagcache_seeklist_entry *seeklist;
1506 1506
1507 /* Check for end of list. */ 1507 /* Check for end of list. */
1508 if (tcs->list_position == tcs->seek_list_count) 1508 if (tcs->list_position == tcs->seek_list_count)
1509 { 1509 {
1510 tcs->list_position = 0; 1510 tcs->list_position = 0;
1511 1511
1512 /* Try to fetch more. */ 1512 /* Try to fetch more. */
1513 if (!build_lookup_list(tcs)) 1513 if (!build_lookup_list(tcs))
1514 { 1514 {
@@ -1516,7 +1516,7 @@ static bool get_next(struct tagcache_search *tcs)
1516 return false; 1516 return false;
1517 } 1517 }
1518 } 1518 }
1519 1519
1520 seeklist = &tcs->seeklist[tcs->list_position]; 1520 seeklist = &tcs->seeklist[tcs->list_position];
1521#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 1521#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1522 flag = seeklist->flag; 1522 flag = seeklist->flag;
@@ -1532,12 +1532,12 @@ static bool get_next(struct tagcache_search *tcs)
1532 tcs->valid = false; 1532 tcs->valid = false;
1533 return false; 1533 return false;
1534 } 1534 }
1535 1535
1536 tcs->entry_count--; 1536 tcs->entry_count--;
1537 } 1537 }
1538 1538
1539 tcs->result_seek = tcs->position; 1539 tcs->result_seek = tcs->position;
1540 1540
1541 if (TAGCACHE_IS_NUMERIC(tcs->type)) 1541 if (TAGCACHE_IS_NUMERIC(tcs->type))
1542 { 1542 {
1543 snprintf(buf, sizeof(buf), "%ld", tcs->position); 1543 snprintf(buf, sizeof(buf), "%ld", tcs->position);
@@ -1545,7 +1545,7 @@ static bool get_next(struct tagcache_search *tcs)
1545 tcs->result_len = strlen(buf) + 1; 1545 tcs->result_len = strlen(buf) + 1;
1546 return true; 1546 return true;
1547 } 1547 }
1548 1548
1549 /* Direct fetch. */ 1549 /* Direct fetch. */
1550#ifdef HAVE_TC_RAMCACHE 1550#ifdef HAVE_TC_RAMCACHE
1551 if (tcs->ramsearch) 1551 if (tcs->ramsearch)
@@ -1569,38 +1569,38 @@ static bool get_next(struct tagcache_search *tcs)
1569 if (tcs->type != tag_filename) 1569 if (tcs->type != tag_filename)
1570 { 1570 {
1571 struct tagfile_entry *ep; 1571 struct tagfile_entry *ep;
1572 1572
1573 ep = (struct tagfile_entry *)&tcramcache.hdr->tags[tcs->type][tcs->position]; 1573 ep = (struct tagfile_entry *)&tcramcache.hdr->tags[tcs->type][tcs->position];
1574 /* don't return ep->tag_data directly as it may move */ 1574 /* don't return ep->tag_data directly as it may move */
1575 tcs->result_len = strlcpy(buf, ep->tag_data, sizeof(buf)) + 1; 1575 tcs->result_len = strlcpy(buf, ep->tag_data, sizeof(buf)) + 1;
1576 tcs->result = buf; 1576 tcs->result = buf;
1577 tcs->idx_id = ep->idx_id; 1577 tcs->idx_id = ep->idx_id;
1578 tcs->ramresult = false; /* was true before we copied to buf too */ 1578 tcs->ramresult = false; /* was true before we copied to buf too */
1579 1579
1580 /* Increase position for the next run. This may get overwritten. */ 1580 /* Increase position for the next run. This may get overwritten. */
1581 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; 1581 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length;
1582 1582
1583 return true; 1583 return true;
1584 } 1584 }
1585 } 1585 }
1586#endif /* HAVE_TC_RAMCACHE */ 1586#endif /* HAVE_TC_RAMCACHE */
1587 1587
1588 if (!open_files(tcs, tcs->type)) 1588 if (!open_files(tcs, tcs->type))
1589 { 1589 {
1590 tcs->valid = false; 1590 tcs->valid = false;
1591 return false; 1591 return false;
1592 } 1592 }
1593 1593
1594 /* Seek stream to the correct position and continue to direct fetch. */ 1594 /* Seek stream to the correct position and continue to direct fetch. */
1595 lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET); 1595 lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET);
1596 1596
1597 if (ecread_tagfile_entry(tcs->idxfd[tcs->type], &entry) != sizeof(struct tagfile_entry)) 1597 if (ecread_tagfile_entry(tcs->idxfd[tcs->type], &entry) != sizeof(struct tagfile_entry))
1598 { 1598 {
1599 logf("read error #5"); 1599 logf("read error #5");
1600 tcs->valid = false; 1600 tcs->valid = false;
1601 return false; 1601 return false;
1602 } 1602 }
1603 1603
1604 if (entry.tag_length > (long)sizeof(buf)) 1604 if (entry.tag_length > (long)sizeof(buf))
1605 { 1605 {
1606 tcs->valid = false; 1606 tcs->valid = false;
@@ -1608,14 +1608,14 @@ static bool get_next(struct tagcache_search *tcs)
1608 logf("P:%lX/%lX", tcs->position, entry.tag_length); 1608 logf("P:%lX/%lX", tcs->position, entry.tag_length);
1609 return false; 1609 return false;
1610 } 1610 }
1611 1611
1612 if (read(tcs->idxfd[tcs->type], buf, entry.tag_length) != entry.tag_length) 1612 if (read(tcs->idxfd[tcs->type], buf, entry.tag_length) != entry.tag_length)
1613 { 1613 {
1614 tcs->valid = false; 1614 tcs->valid = false;
1615 logf("read error #4"); 1615 logf("read error #4");
1616 return false; 1616 return false;
1617 } 1617 }
1618 1618
1619 /** 1619 /**
1620 Update the position for the next read (this may be overridden 1620 Update the position for the next read (this may be overridden
1621 if filters or clauses are being used). 1621 if filters or clauses are being used).
@@ -1636,19 +1636,19 @@ bool tagcache_get_next(struct tagcache_search *tcs)
1636 if (tcs->result_len > 1) 1636 if (tcs->result_len > 1)
1637 return true; 1637 return true;
1638 } 1638 }
1639 1639
1640 return false; 1640 return false;
1641} 1641}
1642 1642
1643bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, 1643bool tagcache_retrieve(struct tagcache_search *tcs, int idxid,
1644 int tag, char *buf, long size) 1644 int tag, char *buf, long size)
1645{ 1645{
1646 struct index_entry idx; 1646 struct index_entry idx;
1647 1647
1648 *buf = '\0'; 1648 *buf = '\0';
1649 if (!get_index(tcs->masterfd, idxid, &idx, true)) 1649 if (!get_index(tcs->masterfd, idxid, &idx, true))
1650 return false; 1650 return false;
1651 1651
1652 return retrieve(tcs, IF_DIRCACHE(idxid,) &idx, tag, buf, size); 1652 return retrieve(tcs, IF_DIRCACHE(idxid,) &idx, tag, buf, size);
1653} 1653}
1654 1654
@@ -1656,32 +1656,32 @@ static bool update_master_header(void)
1656{ 1656{
1657 struct master_header myhdr; 1657 struct master_header myhdr;
1658 int fd; 1658 int fd;
1659 1659
1660 if (!tc_stat.ready) 1660 if (!tc_stat.ready)
1661 return false; 1661 return false;
1662 1662
1663 if ( (fd = open_master_fd(&myhdr, true)) < 0) 1663 if ( (fd = open_master_fd(&myhdr, true)) < 0)
1664 return false; 1664 return false;
1665 1665
1666 myhdr.serial = current_tcmh.serial; 1666 myhdr.serial = current_tcmh.serial;
1667 myhdr.commitid = current_tcmh.commitid; 1667 myhdr.commitid = current_tcmh.commitid;
1668 myhdr.dirty = current_tcmh.dirty; 1668 myhdr.dirty = current_tcmh.dirty;
1669 1669
1670 /* Write it back */ 1670 /* Write it back */
1671 lseek(fd, 0, SEEK_SET); 1671 lseek(fd, 0, SEEK_SET);
1672 ecwrite(fd, &myhdr, 1, master_header_ec, tc_stat.econ); 1672 ecwrite(fd, &myhdr, 1, master_header_ec, tc_stat.econ);
1673 close(fd); 1673 close(fd);
1674 1674
1675 return true; 1675 return true;
1676} 1676}
1677 1677
1678void tagcache_search_finish(struct tagcache_search *tcs) 1678void tagcache_search_finish(struct tagcache_search *tcs)
1679{ 1679{
1680 int i; 1680 int i;
1681 1681
1682 if (!tcs->initialized) 1682 if (!tcs->initialized)
1683 return; 1683 return;
1684 1684
1685 if (tcs->masterfd >= 0) 1685 if (tcs->masterfd >= 0)
1686 { 1686 {
1687 close(tcs->masterfd); 1687 close(tcs->masterfd);
@@ -1696,7 +1696,7 @@ void tagcache_search_finish(struct tagcache_search *tcs)
1696 tcs->idxfd[i] = -1; 1696 tcs->idxfd[i] = -1;
1697 } 1697 }
1698 } 1698 }
1699 1699
1700 tcs->ramsearch = false; 1700 tcs->ramsearch = false;
1701 tcs->valid = false; 1701 tcs->valid = false;
1702 tcs->initialized = 0; 1702 tcs->initialized = 0;
@@ -1725,17 +1725,17 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1725{ 1725{
1726 struct index_entry *entry; 1726 struct index_entry *entry;
1727 int idx_id; 1727 int idx_id;
1728 1728
1729 if (!tc_stat.ready || !tc_stat.ramcache) 1729 if (!tc_stat.ready || !tc_stat.ramcache)
1730 return false; 1730 return false;
1731 1731
1732 /* Find the corresponding entry in tagcache. */ 1732 /* Find the corresponding entry in tagcache. */
1733 idx_id = find_entry_ram(filename); 1733 idx_id = find_entry_ram(filename);
1734 if (idx_id < 0) 1734 if (idx_id < 0)
1735 return false; 1735 return false;
1736 1736
1737 entry = &tcramcache.hdr->indices[idx_id]; 1737 entry = &tcramcache.hdr->indices[idx_id];
1738 1738
1739 memset(id3, 0, sizeof(struct mp3entry)); 1739 memset(id3, 0, sizeof(struct mp3entry));
1740 char* buf = id3->id3v2buf; 1740 char* buf = id3->id3v2buf;
1741 ssize_t remaining = sizeof(id3->id3v2buf); 1741 ssize_t remaining = sizeof(id3->id3v2buf);
@@ -1755,8 +1755,8 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1755 } \ 1755 } \
1756 } \ 1756 } \
1757 } while(0) 1757 } while(0)
1758 1758
1759 1759
1760 SET(id3->title, tag_title); 1760 SET(id3->title, tag_title);
1761 SET(id3->artist, tag_artist); 1761 SET(id3->artist, tag_artist);
1762 SET(id3->album, tag_album); 1762 SET(id3->album, tag_album);
@@ -1786,7 +1786,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1786 id3->title, id3->elapsed); 1786 id3->title, id3->elapsed);
1787 1787
1788 id3->offset = get_tag_numeric(entry, tag_lastoffset, idx_id); 1788 id3->offset = get_tag_numeric(entry, tag_lastoffset, idx_id);
1789 logf("tagcache_fill_tags: Set offset for %s to %lX\n", 1789 logf("tagcache_fill_tags: Set offset for %s to %lX\n",
1790 id3->title, id3->offset); 1790 id3->title, id3->offset);
1791 } 1791 }
1792 1792
@@ -1868,11 +1868,11 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1868 logf("Too long path: %s", path); 1868 logf("Too long path: %s", path);
1869 return ; 1869 return ;
1870 } 1870 }
1871 1871
1872 /* Check if the file is supported. */ 1872 /* Check if the file is supported. */
1873 if (probe_file_format(path) == AFMT_UNKNOWN) 1873 if (probe_file_format(path) == AFMT_UNKNOWN)
1874 return ; 1874 return ;
1875 1875
1876 /* Check if the file is already cached. */ 1876 /* Check if the file is already cached. */
1877#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 1877#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1878 idx_id = find_entry_ram(path); 1878 idx_id = find_entry_ram(path);
@@ -1881,27 +1881,27 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1881 /* Be sure the entry doesn't exist. */ 1881 /* Be sure the entry doesn't exist. */
1882 if (filenametag_fd >= 0 && idx_id < 0) 1882 if (filenametag_fd >= 0 && idx_id < 0)
1883 idx_id = find_entry_disk(path, false); 1883 idx_id = find_entry_disk(path, false);
1884 1884
1885 /* Check if file has been modified. */ 1885 /* Check if file has been modified. */
1886 if (idx_id >= 0) 1886 if (idx_id >= 0)
1887 { 1887 {
1888 struct index_entry idx; 1888 struct index_entry idx;
1889 1889
1890 /* TODO: Mark that the index exists (for fast reverse scan) */ 1890 /* TODO: Mark that the index exists (for fast reverse scan) */
1891 //found_idx[idx_id/8] |= idx_id%8; 1891 //found_idx[idx_id/8] |= idx_id%8;
1892 1892
1893 if (!get_index(-1, idx_id, &idx, true)) 1893 if (!get_index(-1, idx_id, &idx, true))
1894 { 1894 {
1895 logf("failed to retrieve index entry"); 1895 logf("failed to retrieve index entry");
1896 return ; 1896 return ;
1897 } 1897 }
1898 1898
1899 if ((unsigned long)idx.tag_seek[tag_mtime] == mtime) 1899 if ((unsigned long)idx.tag_seek[tag_mtime] == mtime)
1900 { 1900 {
1901 /* No changes to file. */ 1901 /* No changes to file. */
1902 return ; 1902 return ;
1903 } 1903 }
1904 1904
1905 /* Metadata might have been changed. Delete the entry. */ 1905 /* Metadata might have been changed. Delete the entry. */
1906 logf("Re-adding: %s", path); 1906 logf("Re-adding: %s", path);
1907 if (!delete_entry(idx_id)) 1907 if (!delete_entry(idx_id))
@@ -1910,7 +1910,7 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1910 return ; 1910 return ;
1911 } 1911 }
1912 } 1912 }
1913 1913
1914 fd = open(path, O_RDONLY); 1914 fd = open(path, O_RDONLY);
1915 if (fd < 0) 1915 if (fd < 0)
1916 { 1916 {
@@ -1928,12 +1928,12 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1928 return ; 1928 return ;
1929 1929
1930 logf("-> %s", path); 1930 logf("-> %s", path);
1931 1931
1932 if (id3.tracknum <= 0) /* Track number missing? */ 1932 if (id3.tracknum <= 0) /* Track number missing? */
1933 { 1933 {
1934 id3.tracknum = -1; 1934 id3.tracknum = -1;
1935 } 1935 }
1936 1936
1937 /* Numeric tags */ 1937 /* Numeric tags */
1938 entry.tag_offset[tag_year] = id3.year; 1938 entry.tag_offset[tag_year] = id3.year;
1939 entry.tag_offset[tag_discnumber] = id3.discnum; 1939 entry.tag_offset[tag_discnumber] = id3.discnum;
@@ -1941,7 +1941,7 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1941 entry.tag_offset[tag_length] = id3.length; 1941 entry.tag_offset[tag_length] = id3.length;
1942 entry.tag_offset[tag_bitrate] = id3.bitrate; 1942 entry.tag_offset[tag_bitrate] = id3.bitrate;
1943 entry.tag_offset[tag_mtime] = mtime; 1943 entry.tag_offset[tag_mtime] = mtime;
1944 1944
1945 /* String tags. */ 1945 /* String tags. */
1946 has_albumartist = id3.albumartist != NULL 1946 has_albumartist = id3.albumartist != NULL
1947 && strlen(id3.albumartist) > 0; 1947 && strlen(id3.albumartist) > 0;
@@ -1972,10 +1972,10 @@ static void NO_INLINE add_tagcache(char *path, unsigned long mtime)
1972 ADD_TAG(entry, tag_grouping, &id3.title); 1972 ADD_TAG(entry, tag_grouping, &id3.title);
1973 } 1973 }
1974 entry.data_length = offset; 1974 entry.data_length = offset;
1975 1975
1976 /* Write the header */ 1976 /* Write the header */
1977 write(cachefd, &entry, sizeof(struct temp_file_entry)); 1977 write(cachefd, &entry, sizeof(struct temp_file_entry));
1978 1978
1979 /* And tags also... Correct order is critical */ 1979 /* And tags also... Correct order is critical */
1980 write_item(path); 1980 write_item(path);
1981 write_item(id3.title); 1981 write_item(id3.title);
@@ -2014,13 +2014,13 @@ static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
2014 unsigned crc32; 2014 unsigned crc32;
2015 unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4]; 2015 unsigned *crcbuf = (unsigned *)&tempbuf[tempbuf_size-4];
2016 char buf[TAG_MAXLEN+32]; 2016 char buf[TAG_MAXLEN+32];
2017 2017
2018 for (i = 0; str[i] != '\0' && i < (int)sizeof(buf)-1; i++) 2018 for (i = 0; str[i] != '\0' && i < (int)sizeof(buf)-1; i++)
2019 buf[i] = tolower(str[i]); 2019 buf[i] = tolower(str[i]);
2020 buf[i] = '\0'; 2020 buf[i] = '\0';
2021 2021
2022 crc32 = crc_32(buf, i, 0xffffffff); 2022 crc32 = crc_32(buf, i, 0xffffffff);
2023 2023
2024 if (unique) 2024 if (unique)
2025 { 2025 {
2026 /* Check if the crc does not exist -> entry does not exist for sure. */ 2026 /* Check if the crc does not exist -> entry does not exist for sure. */
@@ -2028,7 +2028,7 @@ static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
2028 { 2028 {
2029 if (crcbuf[-i] != crc32) 2029 if (crcbuf[-i] != crc32)
2030 continue; 2030 continue;
2031 2031
2032 if (!strcasecmp(str, index[i].str)) 2032 if (!strcasecmp(str, index[i].str))
2033 { 2033 {
2034 if (id < 0 || id >= lookup_buffer_depth) 2034 if (id < 0 || id >= lookup_buffer_depth)
@@ -2036,22 +2036,22 @@ static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
2036 logf("lookup buf overf.: %d", id); 2036 logf("lookup buf overf.: %d", id);
2037 return false; 2037 return false;
2038 } 2038 }
2039 2039
2040 lookup[id] = &index[i]; 2040 lookup[id] = &index[i];
2041 return true; 2041 return true;
2042 } 2042 }
2043 } 2043 }
2044 } 2044 }
2045 2045
2046 /* Insert to CRC buffer. */ 2046 /* Insert to CRC buffer. */
2047 crcbuf[-tempbufidx] = crc32; 2047 crcbuf[-tempbufidx] = crc32;
2048 tempbuf_left -= 4; 2048 tempbuf_left -= 4;
2049 2049
2050 /* Insert it to the buffer. */ 2050 /* Insert it to the buffer. */
2051 tempbuf_left -= len; 2051 tempbuf_left -= len;
2052 if (tempbuf_left - 4 < 0 || tempbufidx >= commit_entry_count-1) 2052 if (tempbuf_left - 4 < 0 || tempbufidx >= commit_entry_count-1)
2053 return false; 2053 return false;
2054 2054
2055 if (id >= lookup_buffer_depth) 2055 if (id >= lookup_buffer_depth)
2056 { 2056 {
2057 logf("lookup buf overf. #2: %d", id); 2057 logf("lookup buf overf. #2: %d", id);
@@ -2065,7 +2065,7 @@ static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
2065 } 2065 }
2066 else 2066 else
2067 index[tempbufidx].idlist.id = -1; 2067 index[tempbufidx].idlist.id = -1;
2068 2068
2069 index[tempbufidx].idlist.next = NULL; 2069 index[tempbufidx].idlist.next = NULL;
2070 index[tempbufidx].idx_id = idx_id; 2070 index[tempbufidx].idx_id = idx_id;
2071 index[tempbufidx].seek = -1; 2071 index[tempbufidx].seek = -1;
@@ -2073,7 +2073,7 @@ static bool tempbuf_insert(char *str, int id, int idx_id, bool unique)
2073 memcpy(index[tempbufidx].str, str, len); 2073 memcpy(index[tempbufidx].str, str, len);
2074 tempbuf_pos += len; 2074 tempbuf_pos += len;
2075 tempbufidx++; 2075 tempbufidx++;
2076 2076
2077 return true; 2077 return true;
2078} 2078}
2079 2079
@@ -2083,7 +2083,7 @@ static int compare(const void *p1, const void *p2)
2083 2083
2084 struct tempbuf_searchidx *e1 = (struct tempbuf_searchidx *)p1; 2084 struct tempbuf_searchidx *e1 = (struct tempbuf_searchidx *)p1;
2085 struct tempbuf_searchidx *e2 = (struct tempbuf_searchidx *)p2; 2085 struct tempbuf_searchidx *e2 = (struct tempbuf_searchidx *)p2;
2086 2086
2087 if (strcmp(e1->str, UNTAGGED) == 0) 2087 if (strcmp(e1->str, UNTAGGED) == 0)
2088 { 2088 {
2089 if (strcmp(e2->str, UNTAGGED) == 0) 2089 if (strcmp(e2->str, UNTAGGED) == 0)
@@ -2092,7 +2092,7 @@ static int compare(const void *p1, const void *p2)
2092 } 2092 }
2093 else if (strcmp(e2->str, UNTAGGED) == 0) 2093 else if (strcmp(e2->str, UNTAGGED) == 0)
2094 return 1; 2094 return 1;
2095 2095
2096 return strncasecmp(e1->str, e2->str, TAG_MAXLEN); 2096 return strncasecmp(e1->str, e2->str, TAG_MAXLEN);
2097} 2097}
2098 2098
@@ -2102,26 +2102,26 @@ static int tempbuf_sort(int fd)
2102 struct tagfile_entry fe; 2102 struct tagfile_entry fe;
2103 int i; 2103 int i;
2104 int length; 2104 int length;
2105 2105
2106 /* Generate reverse lookup entries. */ 2106 /* Generate reverse lookup entries. */
2107 for (i = 0; i < lookup_buffer_depth; i++) 2107 for (i = 0; i < lookup_buffer_depth; i++)
2108 { 2108 {
2109 struct tempbuf_id_list *idlist; 2109 struct tempbuf_id_list *idlist;
2110 2110
2111 if (!lookup[i]) 2111 if (!lookup[i])
2112 continue; 2112 continue;
2113 2113
2114 if (lookup[i]->idlist.id == i) 2114 if (lookup[i]->idlist.id == i)
2115 continue; 2115 continue;
2116 2116
2117 idlist = &lookup[i]->idlist; 2117 idlist = &lookup[i]->idlist;
2118 while (idlist->next != NULL) 2118 while (idlist->next != NULL)
2119 idlist = idlist->next; 2119 idlist = idlist->next;
2120 2120
2121 tempbuf_left -= sizeof(struct tempbuf_id_list); 2121 tempbuf_left -= sizeof(struct tempbuf_id_list);
2122 if (tempbuf_left - 4 < 0) 2122 if (tempbuf_left - 4 < 0)
2123 return -1; 2123 return -1;
2124 2124
2125 idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos]; 2125 idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos];
2126 if (tempbuf_pos & 0x03) 2126 if (tempbuf_pos & 0x03)
2127 { 2127 {
@@ -2130,21 +2130,21 @@ static int tempbuf_sort(int fd)
2130 idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos]; 2130 idlist->next = (struct tempbuf_id_list *)&tempbuf[tempbuf_pos];
2131 } 2131 }
2132 tempbuf_pos += sizeof(struct tempbuf_id_list); 2132 tempbuf_pos += sizeof(struct tempbuf_id_list);
2133 2133
2134 idlist = idlist->next; 2134 idlist = idlist->next;
2135 idlist->id = i; 2135 idlist->id = i;
2136 idlist->next = NULL; 2136 idlist->next = NULL;
2137 2137
2138 do_timed_yield(); 2138 do_timed_yield();
2139 } 2139 }
2140 2140
2141 qsort(index, tempbufidx, sizeof(struct tempbuf_searchidx), compare); 2141 qsort(index, tempbufidx, sizeof(struct tempbuf_searchidx), compare);
2142 memset(lookup, 0, lookup_buffer_depth * sizeof(struct tempbuf_searchidx **)); 2142 memset(lookup, 0, lookup_buffer_depth * sizeof(struct tempbuf_searchidx **));
2143 2143
2144 for (i = 0; i < tempbufidx; i++) 2144 for (i = 0; i < tempbufidx; i++)
2145 { 2145 {
2146 struct tempbuf_id_list *idlist = &index[i].idlist; 2146 struct tempbuf_id_list *idlist = &index[i].idlist;
2147 2147
2148 /* Fix the lookup list. */ 2148 /* Fix the lookup list. */
2149 while (idlist != NULL) 2149 while (idlist != NULL)
2150 { 2150 {
@@ -2152,21 +2152,21 @@ static int tempbuf_sort(int fd)
2152 lookup[idlist->id] = &index[i]; 2152 lookup[idlist->id] = &index[i];
2153 idlist = idlist->next; 2153 idlist = idlist->next;
2154 } 2154 }
2155 2155
2156 index[i].seek = lseek(fd, 0, SEEK_CUR); 2156 index[i].seek = lseek(fd, 0, SEEK_CUR);
2157 length = strlen(index[i].str) + 1; 2157 length = strlen(index[i].str) + 1;
2158 fe.tag_length = length; 2158 fe.tag_length = length;
2159 fe.idx_id = index[i].idx_id; 2159 fe.idx_id = index[i].idx_id;
2160 2160
2161 /* Check the chunk alignment. */ 2161 /* Check the chunk alignment. */
2162 if ((fe.tag_length + sizeof(struct tagfile_entry)) 2162 if ((fe.tag_length + sizeof(struct tagfile_entry))
2163 % TAGFILE_ENTRY_CHUNK_LENGTH) 2163 % TAGFILE_ENTRY_CHUNK_LENGTH)
2164 { 2164 {
2165 fe.tag_length += TAGFILE_ENTRY_CHUNK_LENGTH - 2165 fe.tag_length += TAGFILE_ENTRY_CHUNK_LENGTH -
2166 ((fe.tag_length + sizeof(struct tagfile_entry)) 2166 ((fe.tag_length + sizeof(struct tagfile_entry))
2167 % TAGFILE_ENTRY_CHUNK_LENGTH); 2167 % TAGFILE_ENTRY_CHUNK_LENGTH);
2168 } 2168 }
2169 2169
2170#ifdef TAGCACHE_STRICT_ALIGN 2170#ifdef TAGCACHE_STRICT_ALIGN
2171 /* Make sure the entry is long aligned. */ 2171 /* Make sure the entry is long aligned. */
2172 if (index[i].seek & 0x03) 2172 if (index[i].seek & 0x03)
@@ -2175,20 +2175,20 @@ static int tempbuf_sort(int fd)
2175 return -3; 2175 return -3;
2176 } 2176 }
2177#endif 2177#endif
2178 2178
2179 if (ecwrite(fd, &fe, 1, tagfile_entry_ec, tc_stat.econ) != 2179 if (ecwrite(fd, &fe, 1, tagfile_entry_ec, tc_stat.econ) !=
2180 sizeof(struct tagfile_entry)) 2180 sizeof(struct tagfile_entry))
2181 { 2181 {
2182 logf("tempbuf_sort: write error #1"); 2182 logf("tempbuf_sort: write error #1");
2183 return -1; 2183 return -1;
2184 } 2184 }
2185 2185
2186 if (write(fd, index[i].str, length) != length) 2186 if (write(fd, index[i].str, length) != length)
2187 { 2187 {
2188 logf("tempbuf_sort: write error #2"); 2188 logf("tempbuf_sort: write error #2");
2189 return -2; 2189 return -2;
2190 } 2190 }
2191 2191
2192 /* Write some padding. */ 2192 /* Write some padding. */
2193 if (fe.tag_length - length > 0) 2193 if (fe.tag_length - length > 0)
2194 write(fd, "XXXXXXXX", fe.tag_length - length); 2194 write(fd, "XXXXXXXX", fe.tag_length - length);
@@ -2196,12 +2196,12 @@ static int tempbuf_sort(int fd)
2196 2196
2197 return i; 2197 return i;
2198} 2198}
2199 2199
2200inline static struct tempbuf_searchidx* tempbuf_locate(int id) 2200inline static struct tempbuf_searchidx* tempbuf_locate(int id)
2201{ 2201{
2202 if (id < 0 || id >= lookup_buffer_depth) 2202 if (id < 0 || id >= lookup_buffer_depth)
2203 return NULL; 2203 return NULL;
2204 2204
2205 return lookup[id]; 2205 return lookup[id];
2206} 2206}
2207 2207
@@ -2228,15 +2228,15 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2228 int entries_processed = 0; 2228 int entries_processed = 0;
2229 int i, j; 2229 int i, j;
2230 char buf[TAG_MAXLEN]; 2230 char buf[TAG_MAXLEN];
2231 2231
2232 max_entries = tempbuf_size / sizeof(struct temp_file_entry) - 1; 2232 max_entries = tempbuf_size / sizeof(struct temp_file_entry) - 1;
2233 2233
2234 logf("Building numeric indices..."); 2234 logf("Building numeric indices...");
2235 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET); 2235 lseek(tmpfd, sizeof(struct tagcache_header), SEEK_SET);
2236 2236
2237 if ( (masterfd = open_master_fd(&tcmh, true)) < 0) 2237 if ( (masterfd = open_master_fd(&tcmh, true)) < 0)
2238 return false; 2238 return false;
2239 2239
2240 masterfd_pos = lseek(masterfd, tcmh.tch.entry_count * sizeof(struct index_entry), 2240 masterfd_pos = lseek(masterfd, tcmh.tch.entry_count * sizeof(struct index_entry),
2241 SEEK_CUR); 2241 SEEK_CUR);
2242 if (masterfd_pos < 0) 2242 if (masterfd_pos < 0)
@@ -2249,13 +2249,13 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2249 while (entries_processed < h->entry_count) 2249 while (entries_processed < h->entry_count)
2250 { 2250 {
2251 int count = MIN(h->entry_count - entries_processed, max_entries); 2251 int count = MIN(h->entry_count - entries_processed, max_entries);
2252 2252
2253 /* Read in as many entries as possible. */ 2253 /* Read in as many entries as possible. */
2254 for (i = 0; i < count; i++) 2254 for (i = 0; i < count; i++)
2255 { 2255 {
2256 struct temp_file_entry *tfe = &entrybuf[i]; 2256 struct temp_file_entry *tfe = &entrybuf[i];
2257 int datastart; 2257 int datastart;
2258 2258
2259 /* Read in numeric data. */ 2259 /* Read in numeric data. */
2260 if (read(tmpfd, tfe, sizeof(struct temp_file_entry)) != 2260 if (read(tmpfd, tfe, sizeof(struct temp_file_entry)) !=
2261 sizeof(struct temp_file_entry)) 2261 sizeof(struct temp_file_entry))
@@ -2266,14 +2266,14 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2266 } 2266 }
2267 2267
2268 datastart = lseek(tmpfd, 0, SEEK_CUR); 2268 datastart = lseek(tmpfd, 0, SEEK_CUR);
2269 2269
2270 /** 2270 /**
2271 * Read string data from the following tags: 2271 * Read string data from the following tags:
2272 * - tag_filename 2272 * - tag_filename
2273 * - tag_artist 2273 * - tag_artist
2274 * - tag_album 2274 * - tag_album
2275 * - tag_title 2275 * - tag_title
2276 * 2276 *
2277 * A crc32 hash is calculated from the read data 2277 * A crc32 hash is calculated from the read data
2278 * and stored back to the data offset field kept in memory. 2278 * and stored back to the data offset field kept in memory.
2279 */ 2279 */
@@ -2296,85 +2296,85 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2296 \ 2296 \
2297 tfe->tag_offset[tag] = crc_32(buf, strlen(buf), 0xffffffff); \ 2297 tfe->tag_offset[tag] = crc_32(buf, strlen(buf), 0xffffffff); \
2298 lseek(tmpfd, datastart, SEEK_SET) 2298 lseek(tmpfd, datastart, SEEK_SET)
2299 2299
2300 tmpdb_read_string_tag(tag_filename); 2300 tmpdb_read_string_tag(tag_filename);
2301 tmpdb_read_string_tag(tag_artist); 2301 tmpdb_read_string_tag(tag_artist);
2302 tmpdb_read_string_tag(tag_album); 2302 tmpdb_read_string_tag(tag_album);
2303 tmpdb_read_string_tag(tag_title); 2303 tmpdb_read_string_tag(tag_title);
2304 2304
2305 /* Seek to the end of the string data. */ 2305 /* Seek to the end of the string data. */
2306 lseek(tmpfd, tfe->data_length, SEEK_CUR); 2306 lseek(tmpfd, tfe->data_length, SEEK_CUR);
2307 } 2307 }
2308 2308
2309 /* Backup the master index position. */ 2309 /* Backup the master index position. */
2310 masterfd_pos = lseek(masterfd, 0, SEEK_CUR); 2310 masterfd_pos = lseek(masterfd, 0, SEEK_CUR);
2311 lseek(masterfd, sizeof(struct master_header), SEEK_SET); 2311 lseek(masterfd, sizeof(struct master_header), SEEK_SET);
2312 2312
2313 /* Check if we can resurrect some deleted runtime statistics data. */ 2313 /* Check if we can resurrect some deleted runtime statistics data. */
2314 for (i = 0; i < tcmh.tch.entry_count; i++) 2314 for (i = 0; i < tcmh.tch.entry_count; i++)
2315 { 2315 {
2316 /* Read the index entry. */ 2316 /* Read the index entry. */
2317 if (ecread_index_entry(masterfd, &idx) 2317 if (ecread_index_entry(masterfd, &idx)
2318 != sizeof(struct index_entry)) 2318 != sizeof(struct index_entry))
2319 { 2319 {
2320 logf("read fail #3"); 2320 logf("read fail #3");
2321 close(masterfd); 2321 close(masterfd);
2322 return false; 2322 return false;
2323 } 2323 }
2324 2324
2325 /** 2325 /**
2326 * Skip unless the entry is marked as being deleted 2326 * Skip unless the entry is marked as being deleted
2327 * or the data has already been resurrected. 2327 * or the data has already been resurrected.
2328 */ 2328 */
2329 if (!(idx.flag & FLAG_DELETED) || (idx.flag & FLAG_RESURRECTED)) 2329 if (!(idx.flag & FLAG_DELETED) || (idx.flag & FLAG_RESURRECTED))
2330 continue; 2330 continue;
2331 2331
2332 /* Now try to match the entry. */ 2332 /* Now try to match the entry. */
2333 /** 2333 /**
2334 * To succesfully match a song, the following conditions 2334 * To succesfully match a song, the following conditions
2335 * must apply: 2335 * must apply:
2336 * 2336 *
2337 * For numeric fields: tag_length 2337 * For numeric fields: tag_length
2338 * - Full identical match is required 2338 * - Full identical match is required
2339 * 2339 *
2340 * If tag_filename matches, no further checking necessary. 2340 * If tag_filename matches, no further checking necessary.
2341 * 2341 *
2342 * For string hashes: tag_artist, tag_album, tag_title 2342 * For string hashes: tag_artist, tag_album, tag_title
2343 * - All three of these must match 2343 * - All three of these must match
2344 */ 2344 */
2345 for (j = 0; j < count; j++) 2345 for (j = 0; j < count; j++)
2346 { 2346 {
2347 struct temp_file_entry *tfe = &entrybuf[j]; 2347 struct temp_file_entry *tfe = &entrybuf[j];
2348 2348
2349 /* Try to match numeric fields first. */ 2349 /* Try to match numeric fields first. */
2350 if (tfe->tag_offset[tag_length] != idx.tag_seek[tag_length]) 2350 if (tfe->tag_offset[tag_length] != idx.tag_seek[tag_length])
2351 continue; 2351 continue;
2352 2352
2353 /* Now it's time to do the hash matching. */ 2353 /* Now it's time to do the hash matching. */
2354 if (tfe->tag_offset[tag_filename] != idx.tag_seek[tag_filename]) 2354 if (tfe->tag_offset[tag_filename] != idx.tag_seek[tag_filename])
2355 { 2355 {
2356 int match_count = 0; 2356 int match_count = 0;
2357 2357
2358 /* No filename match, check if we can match two other tags. */ 2358 /* No filename match, check if we can match two other tags. */
2359#define tmpdb_match(tag) \ 2359#define tmpdb_match(tag) \
2360 if (tfe->tag_offset[tag] == idx.tag_seek[tag]) \ 2360 if (tfe->tag_offset[tag] == idx.tag_seek[tag]) \
2361 match_count++ 2361 match_count++
2362 2362
2363 tmpdb_match(tag_artist); 2363 tmpdb_match(tag_artist);
2364 tmpdb_match(tag_album); 2364 tmpdb_match(tag_album);
2365 tmpdb_match(tag_title); 2365 tmpdb_match(tag_title);
2366 2366
2367 if (match_count < 3) 2367 if (match_count < 3)
2368 { 2368 {
2369 /* Still no match found, give up. */ 2369 /* Still no match found, give up. */
2370 continue; 2370 continue;
2371 } 2371 }
2372 } 2372 }
2373 2373
2374 /* A match found, now copy & resurrect the statistical data. */ 2374 /* A match found, now copy & resurrect the statistical data. */
2375#define tmpdb_copy_tag(tag) \ 2375#define tmpdb_copy_tag(tag) \
2376 tfe->tag_offset[tag] = idx.tag_seek[tag] 2376 tfe->tag_offset[tag] = idx.tag_seek[tag]
2377 2377
2378 tmpdb_copy_tag(tag_playcount); 2378 tmpdb_copy_tag(tag_playcount);
2379 tmpdb_copy_tag(tag_rating); 2379 tmpdb_copy_tag(tag_rating);
2380 tmpdb_copy_tag(tag_playtime); 2380 tmpdb_copy_tag(tag_playtime);
@@ -2382,10 +2382,10 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2382 tmpdb_copy_tag(tag_commitid); 2382 tmpdb_copy_tag(tag_commitid);
2383 tmpdb_copy_tag(tag_lastelapsed); 2383 tmpdb_copy_tag(tag_lastelapsed);
2384 tmpdb_copy_tag(tag_lastoffset); 2384 tmpdb_copy_tag(tag_lastoffset);
2385 2385
2386 /* Avoid processing this entry again. */ 2386 /* Avoid processing this entry again. */
2387 idx.flag |= FLAG_RESURRECTED; 2387 idx.flag |= FLAG_RESURRECTED;
2388 2388
2389 lseek(masterfd, -(off_t)sizeof(struct index_entry), SEEK_CUR); 2389 lseek(masterfd, -(off_t)sizeof(struct index_entry), SEEK_CUR);
2390 if (ecwrite_index_entry(masterfd, &idx) != sizeof(struct index_entry)) 2390 if (ecwrite_index_entry(masterfd, &idx) != sizeof(struct index_entry))
2391 { 2391 {
@@ -2393,36 +2393,36 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2393 close(masterfd); 2393 close(masterfd);
2394 return false; 2394 return false;
2395 } 2395 }
2396 2396
2397 logf("Entry resurrected"); 2397 logf("Entry resurrected");
2398 } 2398 }
2399 } 2399 }
2400 2400
2401 2401
2402 /* Restore the master index position. */ 2402 /* Restore the master index position. */
2403 lseek(masterfd, masterfd_pos, SEEK_SET); 2403 lseek(masterfd, masterfd_pos, SEEK_SET);
2404 2404
2405 /* Commit the data to the index. */ 2405 /* Commit the data to the index. */
2406 for (i = 0; i < count; i++) 2406 for (i = 0; i < count; i++)
2407 { 2407 {
2408 int loc = lseek(masterfd, 0, SEEK_CUR); 2408 int loc = lseek(masterfd, 0, SEEK_CUR);
2409 2409
2410 if (ecread_index_entry(masterfd, &idx) != sizeof(struct index_entry)) 2410 if (ecread_index_entry(masterfd, &idx) != sizeof(struct index_entry))
2411 { 2411 {
2412 logf("read fail #3"); 2412 logf("read fail #3");
2413 close(masterfd); 2413 close(masterfd);
2414 return false; 2414 return false;
2415 } 2415 }
2416 2416
2417 for (j = 0; j < TAG_COUNT; j++) 2417 for (j = 0; j < TAG_COUNT; j++)
2418 { 2418 {
2419 if (!TAGCACHE_IS_NUMERIC(j)) 2419 if (!TAGCACHE_IS_NUMERIC(j))
2420 continue; 2420 continue;
2421 2421
2422 idx.tag_seek[j] = entrybuf[i].tag_offset[j]; 2422 idx.tag_seek[j] = entrybuf[i].tag_offset[j];
2423 } 2423 }
2424 idx.flag = entrybuf[i].flag; 2424 idx.flag = entrybuf[i].flag;
2425 2425
2426 if (idx.tag_seek[tag_commitid]) 2426 if (idx.tag_seek[tag_commitid])
2427 { 2427 {
2428 /* Data has been resurrected. */ 2428 /* Data has been resurrected. */
@@ -2433,7 +2433,7 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2433 idx.tag_seek[tag_commitid] = current_tcmh.commitid; 2433 idx.tag_seek[tag_commitid] = current_tcmh.commitid;
2434 idx.flag |= FLAG_DIRTYNUM; 2434 idx.flag |= FLAG_DIRTYNUM;
2435 } 2435 }
2436 2436
2437 /* Write back the updated index. */ 2437 /* Write back the updated index. */
2438 lseek(masterfd, loc, SEEK_SET); 2438 lseek(masterfd, loc, SEEK_SET);
2439 if (ecwrite_index_entry(masterfd, &idx) != sizeof(struct index_entry)) 2439 if (ecwrite_index_entry(masterfd, &idx) != sizeof(struct index_entry))
@@ -2443,13 +2443,13 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
2443 return false; 2443 return false;
2444 } 2444 }
2445 } 2445 }
2446 2446
2447 entries_processed += count; 2447 entries_processed += count;
2448 logf("%d/%ld entries processed", entries_processed, h->entry_count); 2448 logf("%d/%ld entries processed", entries_processed, h->entry_count);
2449 } 2449 }
2450 2450
2451 close(masterfd); 2451 close(masterfd);
2452 2452
2453 return true; 2453 return true;
2454} 2454}
2455 2455
@@ -2471,12 +2471,12 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2471 bool error = false; 2471 bool error = false;
2472 int init; 2472 int init;
2473 int masterfd_pos; 2473 int masterfd_pos;
2474 2474
2475 logf("Building index: %d", index_type); 2475 logf("Building index: %d", index_type);
2476 2476
2477 /* Check the number of entries we need to allocate ram for. */ 2477 /* Check the number of entries we need to allocate ram for. */
2478 commit_entry_count = h->entry_count + 1; 2478 commit_entry_count = h->entry_count + 1;
2479 2479
2480 masterfd = open_master_fd(&tcmh, false); 2480 masterfd = open_master_fd(&tcmh, false);
2481 if (masterfd >= 0) 2481 if (masterfd >= 0)
2482 { 2482 {
@@ -2501,10 +2501,10 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2501 /* First part */ commit_entry_count + 2501 /* First part */ commit_entry_count +
2502 /* Second part */ 0; 2502 /* Second part */ 0;
2503 } 2503 }
2504 2504
2505 logf("lookup_buffer_depth=%ld", lookup_buffer_depth); 2505 logf("lookup_buffer_depth=%ld", lookup_buffer_depth);
2506 logf("commit_entry_count=%ld", commit_entry_count); 2506 logf("commit_entry_count=%ld", commit_entry_count);
2507 2507
2508 /* Allocate buffer for all index entries from both old and new 2508 /* Allocate buffer for all index entries from both old and new
2509 * tag files. */ 2509 * tag files. */
2510 tempbufidx = 0; 2510 tempbufidx = 0;
@@ -2513,21 +2513,21 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2513 /* Allocate lookup buffer. The first portion of commit_entry_count 2513 /* Allocate lookup buffer. The first portion of commit_entry_count
2514 * contains the new tags in the temporary file and the second 2514 * contains the new tags in the temporary file and the second
2515 * part for locating entries already in the db. 2515 * part for locating entries already in the db.
2516 * 2516 *
2517 * New tags Old tags 2517 * New tags Old tags
2518 * +---------+---------------------------+ 2518 * +---------+---------------------------+
2519 * | index | position/ENTRY_CHUNK_SIZE | lookup buffer 2519 * | index | position/ENTRY_CHUNK_SIZE | lookup buffer
2520 * +---------+---------------------------+ 2520 * +---------+---------------------------+
2521 * 2521 *
2522 * Old tags are inserted to a temporary buffer with position: 2522 * Old tags are inserted to a temporary buffer with position:
2523 * tempbuf_insert(position/ENTRY_CHUNK_SIZE, ...); 2523 * tempbuf_insert(position/ENTRY_CHUNK_SIZE, ...);
2524 * And new tags with index: 2524 * And new tags with index:
2525 * tempbuf_insert(idx, ...); 2525 * tempbuf_insert(idx, ...);
2526 * 2526 *
2527 * The buffer is sorted and written into tag file: 2527 * The buffer is sorted and written into tag file:
2528 * tempbuf_sort(...); 2528 * tempbuf_sort(...);
2529 * leaving master index locations messed up. 2529 * leaving master index locations messed up.
2530 * 2530 *
2531 * That is fixed using the lookup buffer for old tags: 2531 * That is fixed using the lookup buffer for old tags:
2532 * new_seek = tempbuf_find_location(old_seek, ...); 2532 * new_seek = tempbuf_find_location(old_seek, ...);
2533 * and for new tags: 2533 * and for new tags:
@@ -2536,7 +2536,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2536 lookup = (struct tempbuf_searchidx **)&tempbuf[tempbuf_pos]; 2536 lookup = (struct tempbuf_searchidx **)&tempbuf[tempbuf_pos];
2537 tempbuf_pos += lookup_buffer_depth * sizeof(void **); 2537 tempbuf_pos += lookup_buffer_depth * sizeof(void **);
2538 memset(lookup, 0, lookup_buffer_depth * sizeof(void **)); 2538 memset(lookup, 0, lookup_buffer_depth * sizeof(void **));
2539 2539
2540 /* And calculate the remaining data space used mainly for storing 2540 /* And calculate the remaining data space used mainly for storing
2541 * tag data (strings). */ 2541 * tag data (strings). */
2542 tempbuf_left = tempbuf_size - tempbuf_pos - 8; 2542 tempbuf_left = tempbuf_size - tempbuf_pos - 8;
@@ -2561,21 +2561,21 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2561 struct tagfile_entry entry; 2561 struct tagfile_entry entry;
2562 int loc = lseek(fd, 0, SEEK_CUR); 2562 int loc = lseek(fd, 0, SEEK_CUR);
2563 bool ret; 2563 bool ret;
2564 2564
2565 if (ecread_tagfile_entry(fd, &entry) != sizeof(struct tagfile_entry)) 2565 if (ecread_tagfile_entry(fd, &entry) != sizeof(struct tagfile_entry))
2566 { 2566 {
2567 logf("read error #7"); 2567 logf("read error #7");
2568 close(fd); 2568 close(fd);
2569 return -2; 2569 return -2;
2570 } 2570 }
2571 2571
2572 if (entry.tag_length >= (int)sizeof(buf)) 2572 if (entry.tag_length >= (int)sizeof(buf))
2573 { 2573 {
2574 logf("too long tag #3"); 2574 logf("too long tag #3");
2575 close(fd); 2575 close(fd);
2576 return -2; 2576 return -2;
2577 } 2577 }
2578 2578
2579 if (read(fd, buf, entry.tag_length) != entry.tag_length) 2579 if (read(fd, buf, entry.tag_length) != entry.tag_length)
2580 { 2580 {
2581 logf("read error #8"); 2581 logf("read error #8");
@@ -2586,13 +2586,13 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2586 /* Skip deleted entries. */ 2586 /* Skip deleted entries. */
2587 if (buf[0] == '\0') 2587 if (buf[0] == '\0')
2588 continue; 2588 continue;
2589 2589
2590 /** 2590 /**
2591 * Save the tag and tag id in the memory buffer. Tag id 2591 * Save the tag and tag id in the memory buffer. Tag id
2592 * is saved so we can later reindex the master lookup 2592 * is saved so we can later reindex the master lookup
2593 * table when the index gets resorted. 2593 * table when the index gets resorted.
2594 */ 2594 */
2595 ret = tempbuf_insert(buf, loc/TAGFILE_ENTRY_CHUNK_LENGTH 2595 ret = tempbuf_insert(buf, loc/TAGFILE_ENTRY_CHUNK_LENGTH
2596 + commit_entry_count, entry.idx_id, 2596 + commit_entry_count, entry.idx_id,
2597 TAGCACHE_IS_UNIQUE(index_type)); 2597 TAGCACHE_IS_UNIQUE(index_type));
2598 if (!ret) 2598 if (!ret)
@@ -2620,12 +2620,12 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2620 logf("%s open fail", buf); 2620 logf("%s open fail", buf);
2621 return -2; 2621 return -2;
2622 } 2622 }
2623 2623
2624 tch.magic = TAGCACHE_MAGIC; 2624 tch.magic = TAGCACHE_MAGIC;
2625 tch.entry_count = 0; 2625 tch.entry_count = 0;
2626 tch.datasize = 0; 2626 tch.datasize = 0;
2627 2627
2628 if (ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ) 2628 if (ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ)
2629 != sizeof(struct tagcache_header)) 2629 != sizeof(struct tagcache_header))
2630 { 2630 {
2631 logf("header write failed"); 2631 logf("header write failed");
@@ -2705,7 +2705,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2705 for (i = 0; i < h->entry_count; i++) 2705 for (i = 0; i < h->entry_count; i++)
2706 { 2706 {
2707 struct temp_file_entry entry; 2707 struct temp_file_entry entry;
2708 2708
2709 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) != 2709 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
2710 sizeof(struct temp_file_entry)) 2710 sizeof(struct temp_file_entry))
2711 { 2711 {
@@ -2730,18 +2730,18 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2730 error = true; 2730 error = true;
2731 goto error_exit; 2731 goto error_exit;
2732 } 2732 }
2733 2733
2734 if (TAGCACHE_IS_UNIQUE(index_type)) 2734 if (TAGCACHE_IS_UNIQUE(index_type))
2735 error = !tempbuf_insert(buf, i, -1, true); 2735 error = !tempbuf_insert(buf, i, -1, true);
2736 else 2736 else
2737 error = !tempbuf_insert(buf, i, tcmh.tch.entry_count + i, false); 2737 error = !tempbuf_insert(buf, i, tcmh.tch.entry_count + i, false);
2738 2738
2739 if (error) 2739 if (error)
2740 { 2740 {
2741 logf("insert error"); 2741 logf("insert error");
2742 goto error_exit; 2742 goto error_exit;
2743 } 2743 }
2744 2744
2745 /* Skip to next. */ 2745 /* Skip to next. */
2746 lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] - 2746 lseek(tmpfd, entry.data_length - entry.tag_offset[index_type] -
2747 entry.tag_length[index_type], SEEK_CUR); 2747 entry.tag_length[index_type], SEEK_CUR);
@@ -2757,12 +2757,12 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2757 * entry_count and don't crash with that). 2757 * entry_count and don't crash with that).
2758 */ 2758 */
2759 ftruncate(fd, lseek(fd, 0, SEEK_CUR)); 2759 ftruncate(fd, lseek(fd, 0, SEEK_CUR));
2760 2760
2761 i = tempbuf_sort(fd); 2761 i = tempbuf_sort(fd);
2762 if (i < 0) 2762 if (i < 0)
2763 goto error_exit; 2763 goto error_exit;
2764 logf("sorted %d tags", i); 2764 logf("sorted %d tags", i);
2765 2765
2766 /** 2766 /**
2767 * Now update all indexes in the master lookup file. 2767 * Now update all indexes in the master lookup file.
2768 */ 2768 */
@@ -2772,10 +2772,10 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2772 { 2772 {
2773 int j; 2773 int j;
2774 int loc = lseek(masterfd, 0, SEEK_CUR); 2774 int loc = lseek(masterfd, 0, SEEK_CUR);
2775 2775
2776 idxbuf_pos = MIN(tcmh.tch.entry_count - i, IDX_BUF_DEPTH); 2776 idxbuf_pos = MIN(tcmh.tch.entry_count - i, IDX_BUF_DEPTH);
2777 2777
2778 if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ) 2778 if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ)
2779 != (int)sizeof(struct index_entry)*idxbuf_pos) 2779 != (int)sizeof(struct index_entry)*idxbuf_pos)
2780 { 2780 {
2781 logf("read fail #5"); 2781 logf("read fail #5");
@@ -2783,7 +2783,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2783 goto error_exit ; 2783 goto error_exit ;
2784 } 2784 }
2785 lseek(masterfd, loc, SEEK_SET); 2785 lseek(masterfd, loc, SEEK_SET);
2786 2786
2787 for (j = 0; j < idxbuf_pos; j++) 2787 for (j = 0; j < idxbuf_pos; j++)
2788 { 2788 {
2789 if (idxbuf[j].flag & FLAG_DELETED) 2789 if (idxbuf[j].flag & FLAG_DELETED)
@@ -2792,22 +2792,22 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2792 // idxbuf[j].tag_seek[index_type] = 0; 2792 // idxbuf[j].tag_seek[index_type] = 0;
2793 continue; 2793 continue;
2794 } 2794 }
2795 2795
2796 idxbuf[j].tag_seek[index_type] = tempbuf_find_location( 2796 idxbuf[j].tag_seek[index_type] = tempbuf_find_location(
2797 idxbuf[j].tag_seek[index_type]/TAGFILE_ENTRY_CHUNK_LENGTH 2797 idxbuf[j].tag_seek[index_type]/TAGFILE_ENTRY_CHUNK_LENGTH
2798 + commit_entry_count); 2798 + commit_entry_count);
2799 2799
2800 if (idxbuf[j].tag_seek[index_type] < 0) 2800 if (idxbuf[j].tag_seek[index_type] < 0)
2801 { 2801 {
2802 logf("update error: %ld/%d/%ld", 2802 logf("update error: %ld/%d/%ld",
2803 idxbuf[j].flag, i+j, tcmh.tch.entry_count); 2803 idxbuf[j].flag, i+j, tcmh.tch.entry_count);
2804 error = true; 2804 error = true;
2805 goto error_exit; 2805 goto error_exit;
2806 } 2806 }
2807 2807
2808 do_timed_yield(); 2808 do_timed_yield();
2809 } 2809 }
2810 2810
2811 /* Write back the updated index. */ 2811 /* Write back the updated index. */
2812 if (ecwrite(masterfd, idxbuf, idxbuf_pos, 2812 if (ecwrite(masterfd, idxbuf, idxbuf_pos,
2813 index_entry_ec, tc_stat.econ) != 2813 index_entry_ec, tc_stat.econ) !=
@@ -2832,7 +2832,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2832 for (i = 0; i < h->entry_count; i += idxbuf_pos) 2832 for (i = 0; i < h->entry_count; i += idxbuf_pos)
2833 { 2833 {
2834 int j; 2834 int j;
2835 2835
2836 idxbuf_pos = MIN(h->entry_count - i, IDX_BUF_DEPTH); 2836 idxbuf_pos = MIN(h->entry_count - i, IDX_BUF_DEPTH);
2837 if (init) 2837 if (init)
2838 { 2838 {
@@ -2841,8 +2841,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2841 else 2841 else
2842 { 2842 {
2843 int loc = lseek(masterfd, 0, SEEK_CUR); 2843 int loc = lseek(masterfd, 0, SEEK_CUR);
2844 2844
2845 if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ) 2845 if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ)
2846 != (int)sizeof(struct index_entry)*idxbuf_pos) 2846 != (int)sizeof(struct index_entry)*idxbuf_pos)
2847 { 2847 {
2848 logf("read fail #6"); 2848 logf("read fail #6");
@@ -2859,7 +2859,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2859 { 2859 {
2860 struct temp_file_entry entry; 2860 struct temp_file_entry entry;
2861 struct tagfile_entry fe; 2861 struct tagfile_entry fe;
2862 2862
2863 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) != 2863 if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
2864 sizeof(struct temp_file_entry)) 2864 sizeof(struct temp_file_entry))
2865 { 2865 {
@@ -2867,7 +2867,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2867 error = true; 2867 error = true;
2868 break ; 2868 break ;
2869 } 2869 }
2870 2870
2871 /* Read data. */ 2871 /* Read data. */
2872 if (entry.tag_length[index_type] >= (int)sizeof(buf)) 2872 if (entry.tag_length[index_type] >= (int)sizeof(buf))
2873 { 2873 {
@@ -2877,7 +2877,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2877 error = true; 2877 error = true;
2878 break ; 2878 break ;
2879 } 2879 }
2880 2880
2881 lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR); 2881 lseek(tmpfd, entry.tag_offset[index_type], SEEK_CUR);
2882 if (read(tmpfd, buf, entry.tag_length[index_type]) != 2882 if (read(tmpfd, buf, entry.tag_length[index_type]) !=
2883 entry.tag_length[index_type]) 2883 entry.tag_length[index_type])
@@ -2923,29 +2923,29 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2923 error = true; 2923 error = true;
2924 break ; 2924 break ;
2925 } 2925 }
2926 2926
2927 do_timed_yield(); 2927 do_timed_yield();
2928 } 2928 }
2929 logf("done"); 2929 logf("done");
2930 2930
2931 /* Finally write the header. */ 2931 /* Finally write the header. */
2932 tch.magic = TAGCACHE_MAGIC; 2932 tch.magic = TAGCACHE_MAGIC;
2933 tch.entry_count = tempbufidx; 2933 tch.entry_count = tempbufidx;
2934 tch.datasize = lseek(fd, 0, SEEK_END) - sizeof(struct tagcache_header); 2934 tch.datasize = lseek(fd, 0, SEEK_END) - sizeof(struct tagcache_header);
2935 lseek(fd, 0, SEEK_SET); 2935 lseek(fd, 0, SEEK_SET);
2936 ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ); 2936 ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ);
2937 2937
2938 if (index_type != tag_filename) 2938 if (index_type != tag_filename)
2939 h->datasize += tch.datasize; 2939 h->datasize += tch.datasize;
2940 logf("s:%d/%ld/%ld", index_type, tch.datasize, h->datasize); 2940 logf("s:%d/%ld/%ld", index_type, tch.datasize, h->datasize);
2941 error_exit: 2941 error_exit:
2942 2942
2943 close(fd); 2943 close(fd);
2944 close(masterfd); 2944 close(masterfd);
2945 2945
2946 if (error) 2946 if (error)
2947 return -2; 2947 return -2;
2948 2948
2949 return 1; 2949 return 1;
2950} 2950}
2951 2951
@@ -2963,7 +2963,7 @@ static bool commit(void)
2963 bool ramcache_buffer_stolen = false; 2963 bool ramcache_buffer_stolen = false;
2964#endif 2964#endif
2965 logf("committing tagcache"); 2965 logf("committing tagcache");
2966 2966
2967 while (write_lock) 2967 while (write_lock)
2968 sleep(1); 2968 sleep(1);
2969 2969
@@ -2973,12 +2973,12 @@ static bool commit(void)
2973 logf("nothing to commit"); 2973 logf("nothing to commit");
2974 return true; 2974 return true;
2975 } 2975 }
2976 2976
2977 2977
2978 /* Load the header. */ 2978 /* Load the header. */
2979 len = sizeof(struct tagcache_header); 2979 len = sizeof(struct tagcache_header);
2980 rc = read(tmpfd, &tch, len); 2980 rc = read(tmpfd, &tch, len);
2981 2981
2982 if (tch.magic != TAGCACHE_MAGIC || rc != len) 2982 if (tch.magic != TAGCACHE_MAGIC || rc != len)
2983 { 2983 {
2984 logf("incorrect tmpheader"); 2984 logf("incorrect tmpheader");
@@ -2992,11 +2992,11 @@ static bool commit(void)
2992 2992
2993 /* Fully initialize existing headers (if any) before going further. */ 2993 /* Fully initialize existing headers (if any) before going further. */
2994 tc_stat.ready = check_all_headers(); 2994 tc_stat.ready = check_all_headers();
2995 2995
2996#ifdef HAVE_EEPROM_SETTINGS 2996#ifdef HAVE_EEPROM_SETTINGS
2997 remove(TAGCACHE_STATEFILE); 2997 remove(TAGCACHE_STATEFILE);
2998#endif 2998#endif
2999 2999
3000 /* At first be sure to unload the ramcache! */ 3000 /* At first be sure to unload the ramcache! */
3001#ifdef HAVE_TC_RAMCACHE 3001#ifdef HAVE_TC_RAMCACHE
3002 tc_stat.ramcache = false; 3002 tc_stat.ramcache = false;
@@ -3005,7 +3005,7 @@ static bool commit(void)
3005 /* Beyond here, jump to commit_error to undo locks and restore dircache */ 3005 /* Beyond here, jump to commit_error to undo locks and restore dircache */
3006 rc = false; 3006 rc = false;
3007 read_lock++; 3007 read_lock++;
3008 3008
3009 /* Try to steal every buffer we can :) */ 3009 /* Try to steal every buffer we can :) */
3010#ifdef HAVE_DIRCACHE 3010#ifdef HAVE_DIRCACHE
3011 if (tempbuf_size == 0) 3011 if (tempbuf_size == 0)
@@ -3017,7 +3017,7 @@ static bool commit(void)
3017 allocate_tempbuf(); 3017 allocate_tempbuf();
3018 } 3018 }
3019#endif /* HAVE_DIRCACHE */ 3019#endif /* HAVE_DIRCACHE */
3020 3020
3021#ifdef HAVE_TC_RAMCACHE 3021#ifdef HAVE_TC_RAMCACHE
3022 if (tempbuf_size == 0 && tc_stat.ramcache_allocated > 0) 3022 if (tempbuf_size == 0 && tc_stat.ramcache_allocated > 0)
3023 { 3023 {
@@ -3028,7 +3028,7 @@ static bool commit(void)
3028 ramcache_buffer_stolen = true; 3028 ramcache_buffer_stolen = true;
3029 } 3029 }
3030#endif /* HAVE_TC_RAMCACHE */ 3030#endif /* HAVE_TC_RAMCACHE */
3031 3031
3032 /* And finally fail if there are no buffers available. */ 3032 /* And finally fail if there are no buffers available. */
3033 if (tempbuf_size == 0) 3033 if (tempbuf_size == 0)
3034 { 3034 {
@@ -3037,25 +3037,25 @@ static bool commit(void)
3037 close(tmpfd); 3037 close(tmpfd);
3038 goto commit_error; 3038 goto commit_error;
3039 } 3039 }
3040 3040
3041 logf("commit %ld entries...", tch.entry_count); 3041 logf("commit %ld entries...", tch.entry_count);
3042 3042
3043 /* Mark DB dirty so it will stay disabled if commit fails. */ 3043 /* Mark DB dirty so it will stay disabled if commit fails. */
3044 current_tcmh.dirty = true; 3044 current_tcmh.dirty = true;
3045 update_master_header(); 3045 update_master_header();
3046 3046
3047 /* Now create the index files. */ 3047 /* Now create the index files. */
3048 tc_stat.commit_step = 0; 3048 tc_stat.commit_step = 0;
3049 tch.datasize = 0; 3049 tch.datasize = 0;
3050 tc_stat.commit_delayed = false; 3050 tc_stat.commit_delayed = false;
3051 3051
3052 for (i = 0; i < TAG_COUNT; i++) 3052 for (i = 0; i < TAG_COUNT; i++)
3053 { 3053 {
3054 int ret; 3054 int ret;
3055 3055
3056 if (TAGCACHE_IS_NUMERIC(i)) 3056 if (TAGCACHE_IS_NUMERIC(i))
3057 continue; 3057 continue;
3058 3058
3059 tc_stat.commit_step++; 3059 tc_stat.commit_step++;
3060 ret = build_index(i, &tch, tmpfd); 3060 ret = build_index(i, &tch, tmpfd);
3061 if (ret <= 0) 3061 if (ret <= 0)
@@ -3064,12 +3064,12 @@ static bool commit(void)
3064 logf("tagcache failed init"); 3064 logf("tagcache failed init");
3065 if (ret == 0) 3065 if (ret == 0)
3066 tc_stat.commit_delayed = true; 3066 tc_stat.commit_delayed = true;
3067 3067
3068 tc_stat.commit_step = 0; 3068 tc_stat.commit_step = 0;
3069 goto commit_error; 3069 goto commit_error;
3070 } 3070 }
3071 } 3071 }
3072 3072
3073 if (!build_numeric_indices(&tch, tmpfd)) 3073 if (!build_numeric_indices(&tch, tmpfd))
3074 { 3074 {
3075 logf("Failure to commit numeric indices"); 3075 logf("Failure to commit numeric indices");
@@ -3077,19 +3077,19 @@ static bool commit(void)
3077 tc_stat.commit_step = 0; 3077 tc_stat.commit_step = 0;
3078 goto commit_error; 3078 goto commit_error;
3079 } 3079 }
3080 3080
3081 close(tmpfd); 3081 close(tmpfd);
3082 3082
3083 tc_stat.commit_step = 0; 3083 tc_stat.commit_step = 0;
3084 3084
3085 /* Update the master index headers. */ 3085 /* Update the master index headers. */
3086 if ( (masterfd = open_master_fd(&tcmh, true)) < 0) 3086 if ( (masterfd = open_master_fd(&tcmh, true)) < 0)
3087 goto commit_error; 3087 goto commit_error;
3088 3088
3089 remove(TAGCACHE_FILE_TEMP); 3089 remove(TAGCACHE_FILE_TEMP);
3090 3090
3091 tcmh.tch.entry_count += tch.entry_count; 3091 tcmh.tch.entry_count += tch.entry_count;
3092 tcmh.tch.datasize = sizeof(struct master_header) 3092 tcmh.tch.datasize = sizeof(struct master_header)
3093 + sizeof(struct index_entry) * tcmh.tch.entry_count 3093 + sizeof(struct index_entry) * tcmh.tch.entry_count
3094 + tch.datasize; 3094 + tch.datasize;
3095 tcmh.dirty = false; 3095 tcmh.dirty = false;
@@ -3098,11 +3098,11 @@ static bool commit(void)
3098 lseek(masterfd, 0, SEEK_SET); 3098 lseek(masterfd, 0, SEEK_SET);
3099 ecwrite(masterfd, &tcmh, 1, master_header_ec, tc_stat.econ); 3099 ecwrite(masterfd, &tcmh, 1, master_header_ec, tc_stat.econ);
3100 close(masterfd); 3100 close(masterfd);
3101 3101
3102 logf("tagcache committed"); 3102 logf("tagcache committed");
3103 tc_stat.ready = check_all_headers(); 3103 tc_stat.ready = check_all_headers();
3104 tc_stat.readyvalid = true; 3104 tc_stat.readyvalid = true;
3105 3105
3106#ifdef HAVE_TC_RAMCACHE 3106#ifdef HAVE_TC_RAMCACHE
3107 if (ramcache_buffer_stolen) 3107 if (ramcache_buffer_stolen)
3108 { 3108 {
@@ -3116,7 +3116,7 @@ static bool commit(void)
3116 if (tc_stat.ramcache_allocated > 0) 3116 if (tc_stat.ramcache_allocated > 0)
3117 tagcache_start_scan(); 3117 tagcache_start_scan();
3118#endif /* HAVE_TC_RAMCACHE */ 3118#endif /* HAVE_TC_RAMCACHE */
3119 3119
3120 rc = true; 3120 rc = true;
3121 3121
3122commit_error: 3122commit_error:
@@ -3139,7 +3139,7 @@ commit_error:
3139 dircache_resume(); 3139 dircache_resume();
3140 } 3140 }
3141#endif /* HAVE_DIRCACHE */ 3141#endif /* HAVE_DIRCACHE */
3142 3142
3143 return rc; 3143 return rc;
3144} 3144}
3145 3145
@@ -3148,34 +3148,34 @@ commit_error:
3148static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) 3148static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
3149{ 3149{
3150 struct index_entry idx; 3150 struct index_entry idx;
3151 3151
3152 if (!tc_stat.ready) 3152 if (!tc_stat.ready)
3153 return false; 3153 return false;
3154 3154
3155 if (!TAGCACHE_IS_NUMERIC(tag)) 3155 if (!TAGCACHE_IS_NUMERIC(tag))
3156 return false; 3156 return false;
3157 3157
3158 if (!get_index(masterfd, idx_id, &idx, false)) 3158 if (!get_index(masterfd, idx_id, &idx, false))
3159 return false; 3159 return false;
3160 3160
3161 idx.tag_seek[tag] = data; 3161 idx.tag_seek[tag] = data;
3162 idx.flag |= FLAG_DIRTYNUM; 3162 idx.flag |= FLAG_DIRTYNUM;
3163 3163
3164 return write_index(masterfd, idx_id, &idx); 3164 return write_index(masterfd, idx_id, &idx);
3165} 3165}
3166 3166
3167#if 0 3167#if 0
3168bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, 3168bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
3169 int tag, long data) 3169 int tag, long data)
3170{ 3170{
3171 struct master_header myhdr; 3171 struct master_header myhdr;
3172 3172
3173 if (tcs->masterfd < 0) 3173 if (tcs->masterfd < 0)
3174 { 3174 {
3175 if ( (tcs->masterfd = open_master_fd(&myhdr, true)) < 0) 3175 if ( (tcs->masterfd = open_master_fd(&myhdr, true)) < 0)
3176 return false; 3176 return false;
3177 } 3177 }
3178 3178
3179 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data); 3179 return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data);
3180} 3180}
3181#endif 3181#endif
@@ -3183,11 +3183,11 @@ bool tagcache_modify_numeric_entry(struct tagcache_search *tcs,
3183static bool command_queue_is_full(void) 3183static bool command_queue_is_full(void)
3184{ 3184{
3185 int next; 3185 int next;
3186 3186
3187 next = command_queue_widx + 1; 3187 next = command_queue_widx + 1;
3188 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH) 3188 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
3189 next = 0; 3189 next = 0;
3190 3190
3191 return (next == command_queue_ridx); 3191 return (next == command_queue_ridx);
3192} 3192}
3193 3193
@@ -3195,27 +3195,27 @@ static void command_queue_sync_callback(void)
3195{ 3195{
3196 struct master_header myhdr; 3196 struct master_header myhdr;
3197 int masterfd; 3197 int masterfd;
3198 3198
3199 mutex_lock(&command_queue_mutex); 3199 mutex_lock(&command_queue_mutex);
3200 3200
3201 if ( (masterfd = open_master_fd(&myhdr, true)) < 0) 3201 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
3202 return; 3202 return;
3203 3203
3204 while (command_queue_ridx != command_queue_widx) 3204 while (command_queue_ridx != command_queue_widx)
3205 { 3205 {
3206 struct tagcache_command_entry *ce = &command_queue[command_queue_ridx]; 3206 struct tagcache_command_entry *ce = &command_queue[command_queue_ridx];
3207 3207
3208 switch (ce->command) 3208 switch (ce->command)
3209 { 3209 {
3210 case CMD_UPDATE_MASTER_HEADER: 3210 case CMD_UPDATE_MASTER_HEADER:
3211 { 3211 {
3212 close(masterfd); 3212 close(masterfd);
3213 update_master_header(); 3213 update_master_header();
3214 3214
3215 /* Re-open the masterfd. */ 3215 /* Re-open the masterfd. */
3216 if ( (masterfd = open_master_fd(&myhdr, true)) < 0) 3216 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
3217 return; 3217 return;
3218 3218
3219 break; 3219 break;
3220 } 3220 }
3221 case CMD_UPDATE_NUMERIC: 3221 case CMD_UPDATE_NUMERIC:
@@ -3224,13 +3224,13 @@ static void command_queue_sync_callback(void)
3224 break; 3224 break;
3225 } 3225 }
3226 } 3226 }
3227 3227
3228 if (++command_queue_ridx >= TAGCACHE_COMMAND_QUEUE_LENGTH) 3228 if (++command_queue_ridx >= TAGCACHE_COMMAND_QUEUE_LENGTH)
3229 command_queue_ridx = 0; 3229 command_queue_ridx = 0;
3230 } 3230 }
3231 3231
3232 close(masterfd); 3232 close(masterfd);
3233 3233
3234 tc_stat.queue_length = 0; 3234 tc_stat.queue_length = 0;
3235 mutex_unlock(&command_queue_mutex); 3235 mutex_unlock(&command_queue_mutex);
3236} 3236}
@@ -3239,7 +3239,7 @@ static void run_command_queue(bool force)
3239{ 3239{
3240 if (COMMAND_QUEUE_IS_EMPTY) 3240 if (COMMAND_QUEUE_IS_EMPTY)
3241 return; 3241 return;
3242 3242
3243 if (force || command_queue_is_full()) 3243 if (force || command_queue_is_full())
3244 command_queue_sync_callback(); 3244 command_queue_sync_callback();
3245 else 3245 else
@@ -3251,30 +3251,30 @@ static void queue_command(int cmd, long idx_id, int tag, long data)
3251 while (1) 3251 while (1)
3252 { 3252 {
3253 int next; 3253 int next;
3254 3254
3255 mutex_lock(&command_queue_mutex); 3255 mutex_lock(&command_queue_mutex);
3256 next = command_queue_widx + 1; 3256 next = command_queue_widx + 1;
3257 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH) 3257 if (next >= TAGCACHE_COMMAND_QUEUE_LENGTH)
3258 next = 0; 3258 next = 0;
3259 3259
3260 /* Make sure queue is not full. */ 3260 /* Make sure queue is not full. */
3261 if (next != command_queue_ridx) 3261 if (next != command_queue_ridx)
3262 { 3262 {
3263 struct tagcache_command_entry *ce = &command_queue[command_queue_widx]; 3263 struct tagcache_command_entry *ce = &command_queue[command_queue_widx];
3264 3264
3265 ce->command = cmd; 3265 ce->command = cmd;
3266 ce->idx_id = idx_id; 3266 ce->idx_id = idx_id;
3267 ce->tag = tag; 3267 ce->tag = tag;
3268 ce->data = data; 3268 ce->data = data;
3269 3269
3270 command_queue_widx = next; 3270 command_queue_widx = next;
3271 3271
3272 tc_stat.queue_length++; 3272 tc_stat.queue_length++;
3273 3273
3274 mutex_unlock(&command_queue_mutex); 3274 mutex_unlock(&command_queue_mutex);
3275 break; 3275 break;
3276 } 3276 }
3277 3277
3278 /* Queue is full, try again later... */ 3278 /* Queue is full, try again later... */
3279 mutex_unlock(&command_queue_mutex); 3279 mutex_unlock(&command_queue_mutex);
3280 sleep(1); 3280 sleep(1);
@@ -3284,16 +3284,16 @@ static void queue_command(int cmd, long idx_id, int tag, long data)
3284long tagcache_increase_serial(void) 3284long tagcache_increase_serial(void)
3285{ 3285{
3286 long old; 3286 long old;
3287 3287
3288 if (!tc_stat.ready) 3288 if (!tc_stat.ready)
3289 return -2; 3289 return -2;
3290 3290
3291 while (read_lock) 3291 while (read_lock)
3292 sleep(1); 3292 sleep(1);
3293 3293
3294 old = current_tcmh.serial++; 3294 old = current_tcmh.serial++;
3295 queue_command(CMD_UPDATE_MASTER_HEADER, 0, 0, 0); 3295 queue_command(CMD_UPDATE_MASTER_HEADER, 0, 0, 0);
3296 3296
3297 return old; 3297 return old;
3298} 3298}
3299 3299
@@ -3307,50 +3307,50 @@ static bool write_tag(int fd, const char *tagstr, const char *datastr)
3307{ 3307{
3308 char buf[512]; 3308 char buf[512];
3309 int i; 3309 int i;
3310 3310
3311 snprintf(buf, sizeof buf, "%s=\"", tagstr); 3311 snprintf(buf, sizeof buf, "%s=\"", tagstr);
3312 for (i = strlen(buf); i < (long)sizeof(buf)-4; i++) 3312 for (i = strlen(buf); i < (long)sizeof(buf)-4; i++)
3313 { 3313 {
3314 if (*datastr == '\0') 3314 if (*datastr == '\0')
3315 break; 3315 break;
3316 3316
3317 if (*datastr == '"' || *datastr == '\\') 3317 if (*datastr == '"' || *datastr == '\\')
3318 buf[i++] = '\\'; 3318 buf[i++] = '\\';
3319 3319
3320 else if (*datastr == '\n') 3320 else if (*datastr == '\n')
3321 { 3321 {
3322 buf[i++] = '\\'; 3322 buf[i++] = '\\';
3323 buf[i] = 'n'; 3323 buf[i] = 'n';
3324 continue; 3324 continue;
3325 } 3325 }
3326 3326
3327 buf[i] = *(datastr++); 3327 buf[i] = *(datastr++);
3328 } 3328 }
3329 3329
3330 strcpy(&buf[i], "\" "); 3330 strcpy(&buf[i], "\" ");
3331 3331
3332 write(fd, buf, i + 2); 3332 write(fd, buf, i + 2);
3333 3333
3334 return true; 3334 return true;
3335} 3335}
3336 3336
3337#ifndef __PCTOOL__ 3337#ifndef __PCTOOL__
3338 3338
3339static bool read_tag(char *dest, long size, 3339static bool read_tag(char *dest, long size,
3340 const char *src, const char *tagstr) 3340 const char *src, const char *tagstr)
3341{ 3341{
3342 int pos; 3342 int pos;
3343 char current_tag[32]; 3343 char current_tag[32];
3344 3344
3345 while (*src != '\0') 3345 while (*src != '\0')
3346 { 3346 {
3347 /* Skip all whitespace */ 3347 /* Skip all whitespace */
3348 while (*src == ' ') 3348 while (*src == ' ')
3349 src++; 3349 src++;
3350 3350
3351 if (*src == '\0') 3351 if (*src == '\0')
3352 break; 3352 break;
3353 3353
3354 pos = 0; 3354 pos = 0;
3355 /* Read in tag name */ 3355 /* Read in tag name */
3356 while (*src != '=' && *src != ' ') 3356 while (*src != '=' && *src != ' ')
@@ -3358,27 +3358,27 @@ static bool read_tag(char *dest, long size,
3358 current_tag[pos] = *src; 3358 current_tag[pos] = *src;
3359 src++; 3359 src++;
3360 pos++; 3360 pos++;
3361 3361
3362 if (*src == '\0' || pos >= (long)sizeof(current_tag)) 3362 if (*src == '\0' || pos >= (long)sizeof(current_tag))
3363 return false; 3363 return false;
3364 } 3364 }
3365 current_tag[pos] = '\0'; 3365 current_tag[pos] = '\0';
3366 3366
3367 /* Read in tag data */ 3367 /* Read in tag data */
3368 3368
3369 /* Find the start. */ 3369 /* Find the start. */
3370 while (*src != '"' && *src != '\0') 3370 while (*src != '"' && *src != '\0')
3371 src++; 3371 src++;
3372 3372
3373 if (*src == '\0' || *(++src) == '\0') 3373 if (*src == '\0' || *(++src) == '\0')
3374 return false; 3374 return false;
3375 3375
3376 /* Read the data. */ 3376 /* Read the data. */
3377 for (pos = 0; pos < size; pos++) 3377 for (pos = 0; pos < size; pos++)
3378 { 3378 {
3379 if (*src == '\0') 3379 if (*src == '\0')
3380 break; 3380 break;
3381 3381
3382 if (*src == '\\') 3382 if (*src == '\\')
3383 { 3383 {
3384 src++; 3384 src++;
@@ -3386,29 +3386,29 @@ static bool read_tag(char *dest, long size,
3386 dest[pos] = '\n'; 3386 dest[pos] = '\n';
3387 else 3387 else
3388 dest[pos] = *src; 3388 dest[pos] = *src;
3389 3389
3390 src++; 3390 src++;
3391 continue; 3391 continue;
3392 } 3392 }
3393 3393
3394 if (*src == '\0') 3394 if (*src == '\0')
3395 break; 3395 break;
3396 3396
3397 if (*src == '"') 3397 if (*src == '"')
3398 { 3398 {
3399 src++; 3399 src++;
3400 break; 3400 break;
3401 } 3401 }
3402 3402
3403 dest[pos] = *(src++); 3403 dest[pos] = *(src++);
3404 } 3404 }
3405 3405
3406 dest[pos] = '\0'; 3406 dest[pos] = '\0';
3407 3407
3408 if (!strcasecmp(tagstr, current_tag)) 3408 if (!strcasecmp(tagstr, current_tag))
3409 return true; 3409 return true;
3410 } 3410 }
3411 3411
3412 return false; 3412 return false;
3413} 3413}
3414 3414
@@ -3423,10 +3423,10 @@ static int parse_changelog_line(int line_n, char *buf, void *parameters)
3423 tag_lastoffset }; 3423 tag_lastoffset };
3424 int i; 3424 int i;
3425 (void)line_n; 3425 (void)line_n;
3426 3426
3427 if (*buf == '#') 3427 if (*buf == '#')
3428 return 0; 3428 return 0;
3429 3429
3430 /* logf("%d/%s", line_n, buf); */ 3430 /* logf("%d/%s", line_n, buf); */
3431 if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) 3431 if (!read_tag(tag_data, sizeof tag_data, buf, "filename"))
3432 { 3432 {
@@ -3434,49 +3434,49 @@ static int parse_changelog_line(int line_n, char *buf, void *parameters)
3434 logf("-> %s", buf); 3434 logf("-> %s", buf);
3435 return 0; 3435 return 0;
3436 } 3436 }
3437 3437
3438 idx_id = find_index(tag_data); 3438 idx_id = find_index(tag_data);
3439 if (idx_id < 0) 3439 if (idx_id < 0)
3440 { 3440 {
3441 logf("%d/entry not found", line_n); 3441 logf("%d/entry not found", line_n);
3442 return 0; 3442 return 0;
3443 } 3443 }
3444 3444
3445 if (!get_index(masterfd, idx_id, &idx, false)) 3445 if (!get_index(masterfd, idx_id, &idx, false))
3446 { 3446 {
3447 logf("%d/failed to retrieve index entry", line_n); 3447 logf("%d/failed to retrieve index entry", line_n);
3448 return 0; 3448 return 0;
3449 } 3449 }
3450 3450
3451 /* Stop if tag has already been modified. */ 3451 /* Stop if tag has already been modified. */
3452 if (idx.flag & FLAG_DIRTYNUM) 3452 if (idx.flag & FLAG_DIRTYNUM)
3453 return 0; 3453 return 0;
3454 3454
3455 logf("%d/import: %s", line_n, tag_data); 3455 logf("%d/import: %s", line_n, tag_data);
3456 3456
3457 idx.flag |= FLAG_DIRTYNUM; 3457 idx.flag |= FLAG_DIRTYNUM;
3458 for (i = 0; i < (long)(sizeof(import_tags)/sizeof(import_tags[0])); i++) 3458 for (i = 0; i < (long)(sizeof(import_tags)/sizeof(import_tags[0])); i++)
3459 { 3459 {
3460 int data; 3460 int data;
3461 3461
3462 if (!read_tag(tag_data, sizeof tag_data, buf, 3462 if (!read_tag(tag_data, sizeof tag_data, buf,
3463 tagcache_tag_to_str(import_tags[i]))) 3463 tagcache_tag_to_str(import_tags[i])))
3464 { 3464 {
3465 continue; 3465 continue;
3466 } 3466 }
3467 3467
3468 data = atoi(tag_data); 3468 data = atoi(tag_data);
3469 if (data < 0) 3469 if (data < 0)
3470 continue; 3470 continue;
3471 3471
3472 idx.tag_seek[import_tags[i]] = data; 3472 idx.tag_seek[import_tags[i]] = data;
3473 3473
3474 if (import_tags[i] == tag_lastplayed && data >= current_tcmh.serial) 3474 if (import_tags[i] == tag_lastplayed && data >= current_tcmh.serial)
3475 current_tcmh.serial = data + 1; 3475 current_tcmh.serial = data + 1;
3476 else if (import_tags[i] == tag_commitid && data >= current_tcmh.commitid) 3476 else if (import_tags[i] == tag_commitid && data >= current_tcmh.commitid)
3477 current_tcmh.commitid = data + 1; 3477 current_tcmh.commitid = data + 1;
3478 } 3478 }
3479 3479
3480 return write_index(masterfd, idx_id, &idx) ? 0 : -5; 3480 return write_index(masterfd, idx_id, &idx) ? 0 : -5;
3481} 3481}
3482 3482
@@ -3487,46 +3487,46 @@ bool tagcache_import_changelog(void)
3487 int clfd; 3487 int clfd;
3488 long masterfd; 3488 long masterfd;
3489 char buf[2048]; 3489 char buf[2048];
3490 3490
3491 if (!tc_stat.ready) 3491 if (!tc_stat.ready)
3492 return false; 3492 return false;
3493 3493
3494 while (read_lock) 3494 while (read_lock)
3495 sleep(1); 3495 sleep(1);
3496 3496
3497 clfd = open(TAGCACHE_FILE_CHANGELOG, O_RDONLY); 3497 clfd = open(TAGCACHE_FILE_CHANGELOG, O_RDONLY);
3498 if (clfd < 0) 3498 if (clfd < 0)
3499 { 3499 {
3500 logf("failure to open changelog"); 3500 logf("failure to open changelog");
3501 return false; 3501 return false;
3502 } 3502 }
3503 3503
3504 if ( (masterfd = open_master_fd(&myhdr, true)) < 0) 3504 if ( (masterfd = open_master_fd(&myhdr, true)) < 0)
3505 { 3505 {
3506 close(clfd); 3506 close(clfd);
3507 return false; 3507 return false;
3508 } 3508 }
3509 3509
3510 write_lock++; 3510 write_lock++;
3511 3511
3512 filenametag_fd = open_tag_fd(&tch, tag_filename, false); 3512 filenametag_fd = open_tag_fd(&tch, tag_filename, false);
3513 3513
3514 fast_readline(clfd, buf, sizeof buf, (void *)(intptr_t)masterfd, 3514 fast_readline(clfd, buf, sizeof buf, (void *)(intptr_t)masterfd,
3515 parse_changelog_line); 3515 parse_changelog_line);
3516 3516
3517 close(clfd); 3517 close(clfd);
3518 close(masterfd); 3518 close(masterfd);
3519 3519
3520 if (filenametag_fd >= 0) 3520 if (filenametag_fd >= 0)
3521 { 3521 {
3522 close(filenametag_fd); 3522 close(filenametag_fd);
3523 filenametag_fd = -1; 3523 filenametag_fd = -1;
3524 } 3524 }
3525 3525
3526 write_lock--; 3526 write_lock--;
3527 3527
3528 update_master_header(); 3528 update_master_header();
3529 3529
3530 return true; 3530 return true;
3531} 3531}
3532 3532
@@ -3540,13 +3540,13 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
3540 char temp[32]; 3540 char temp[32];
3541 int clfd; 3541 int clfd;
3542 int i, j; 3542 int i, j;
3543 3543
3544 if (!tc_stat.ready) 3544 if (!tc_stat.ready)
3545 return false; 3545 return false;
3546 3546
3547 if (!tagcache_search(tcs, tag_filename)) 3547 if (!tagcache_search(tcs, tag_filename))
3548 return false; 3548 return false;
3549 3549
3550 /* Initialize the changelog */ 3550 /* Initialize the changelog */
3551 clfd = open(TAGCACHE_FILE_CHANGELOG, O_WRONLY | O_CREAT | O_TRUNC, 0666); 3551 clfd = open(TAGCACHE_FILE_CHANGELOG, O_WRONLY | O_CREAT | O_TRUNC, 0666);
3552 if (clfd < 0) 3552 if (clfd < 0)
@@ -3554,7 +3554,7 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
3554 logf("failure to open changelog"); 3554 logf("failure to open changelog");
3555 return false; 3555 return false;
3556 } 3556 }
3557 3557
3558 if (tcs->masterfd < 0) 3558 if (tcs->masterfd < 0)
3559 { 3559 {
3560 if ( (tcs->masterfd = open_master_fd(&myhdr, false)) < 0) 3560 if ( (tcs->masterfd = open_master_fd(&myhdr, false)) < 0)
@@ -3568,9 +3568,9 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
3568 lseek(tcs->masterfd, 0, SEEK_SET); 3568 lseek(tcs->masterfd, 0, SEEK_SET);
3569 ecread(tcs->masterfd, &myhdr, 1, master_header_ec, tc_stat.econ); 3569 ecread(tcs->masterfd, &myhdr, 1, master_header_ec, tc_stat.econ);
3570 } 3570 }
3571 3571
3572 write(clfd, "## Changelog version 1\n", 23); 3572 write(clfd, "## Changelog version 1\n", 23);
3573 3573
3574 for (i = 0; i < myhdr.tch.entry_count; i++) 3574 for (i = 0; i < myhdr.tch.entry_count; i++)
3575 { 3575 {
3576 if (ecread_index_entry(tcs->masterfd, &idx) != sizeof(struct index_entry)) 3576 if (ecread_index_entry(tcs->masterfd, &idx) != sizeof(struct index_entry))
@@ -3580,15 +3580,15 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
3580 close(clfd); 3580 close(clfd);
3581 return false; 3581 return false;
3582 } 3582 }
3583 3583
3584 /* Skip until the entry found has been modified. */ 3584 /* Skip until the entry found has been modified. */
3585 if (! (idx.flag & FLAG_DIRTYNUM) ) 3585 if (! (idx.flag & FLAG_DIRTYNUM) )
3586 continue; 3586 continue;
3587 3587
3588 /* Skip deleted entries too. */ 3588 /* Skip deleted entries too. */
3589 if (idx.flag & FLAG_DELETED) 3589 if (idx.flag & FLAG_DELETED)
3590 continue; 3590 continue;
3591 3591
3592 /* Now retrieve all tags. */ 3592 /* Now retrieve all tags. */
3593 for (j = 0; j < TAG_COUNT; j++) 3593 for (j = 0; j < TAG_COUNT; j++)
3594 { 3594 {
@@ -3598,20 +3598,20 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
3598 write_tag(clfd, tagcache_tag_to_str(j), temp); 3598 write_tag(clfd, tagcache_tag_to_str(j), temp);
3599 continue; 3599 continue;
3600 } 3600 }
3601 3601
3602 tcs->type = j; 3602 tcs->type = j;
3603 tagcache_retrieve(tcs, i, tcs->type, buf, sizeof buf); 3603 tagcache_retrieve(tcs, i, tcs->type, buf, sizeof buf);
3604 write_tag(clfd, tagcache_tag_to_str(j), buf); 3604 write_tag(clfd, tagcache_tag_to_str(j), buf);
3605 } 3605 }
3606 3606
3607 write(clfd, "\n", 1); 3607 write(clfd, "\n", 1);
3608 do_timed_yield(); 3608 do_timed_yield();
3609 } 3609 }
3610 3610
3611 close(clfd); 3611 close(clfd);
3612 3612
3613 tagcache_search_finish(tcs); 3613 tagcache_search_finish(tcs);
3614 3614
3615 return true; 3615 return true;
3616} 3616}
3617 3617
@@ -3624,31 +3624,31 @@ static bool delete_entry(long idx_id)
3624 struct master_header myhdr; 3624 struct master_header myhdr;
3625 char buf[TAG_MAXLEN+32]; 3625 char buf[TAG_MAXLEN+32];
3626 int in_use[TAG_COUNT]; 3626 int in_use[TAG_COUNT];
3627 3627
3628 logf("delete_entry(): %ld", idx_id); 3628 logf("delete_entry(): %ld", idx_id);
3629 3629
3630#ifdef HAVE_TC_RAMCACHE 3630#ifdef HAVE_TC_RAMCACHE
3631 /* At first mark the entry removed from ram cache. */ 3631 /* At first mark the entry removed from ram cache. */
3632 if (tc_stat.ramcache) 3632 if (tc_stat.ramcache)
3633 tcramcache.hdr->indices[idx_id].flag |= FLAG_DELETED; 3633 tcramcache.hdr->indices[idx_id].flag |= FLAG_DELETED;
3634#endif 3634#endif
3635 3635
3636 if ( (masterfd = open_master_fd(&myhdr, true) ) < 0) 3636 if ( (masterfd = open_master_fd(&myhdr, true) ) < 0)
3637 return false; 3637 return false;
3638 3638
3639 lseek(masterfd, idx_id * sizeof(struct index_entry), SEEK_CUR); 3639 lseek(masterfd, idx_id * sizeof(struct index_entry), SEEK_CUR);
3640 if (ecread_index_entry(masterfd, &myidx) != sizeof(struct index_entry)) 3640 if (ecread_index_entry(masterfd, &myidx) != sizeof(struct index_entry))
3641 { 3641 {
3642 logf("delete_entry(): read error"); 3642 logf("delete_entry(): read error");
3643 goto cleanup; 3643 goto cleanup;
3644 } 3644 }
3645 3645
3646 if (myidx.flag & FLAG_DELETED) 3646 if (myidx.flag & FLAG_DELETED)
3647 { 3647 {
3648 logf("delete_entry(): already deleted!"); 3648 logf("delete_entry(): already deleted!");
3649 goto cleanup; 3649 goto cleanup;
3650 } 3650 }
3651 3651
3652 myidx.flag |= FLAG_DELETED; 3652 myidx.flag |= FLAG_DELETED;
3653 lseek(masterfd, -(off_t)sizeof(struct index_entry), SEEK_CUR); 3653 lseek(masterfd, -(off_t)sizeof(struct index_entry), SEEK_CUR);
3654 if (ecwrite_index_entry(masterfd, &myidx) != sizeof(struct index_entry)) 3654 if (ecwrite_index_entry(masterfd, &myidx) != sizeof(struct index_entry))
@@ -3660,12 +3660,12 @@ static bool delete_entry(long idx_id)
3660 /* Now check which tags are no longer in use (if any) */ 3660 /* Now check which tags are no longer in use (if any) */
3661 for (tag = 0; tag < TAG_COUNT; tag++) 3661 for (tag = 0; tag < TAG_COUNT; tag++)
3662 in_use[tag] = 0; 3662 in_use[tag] = 0;
3663 3663
3664 lseek(masterfd, sizeof(struct master_header), SEEK_SET); 3664 lseek(masterfd, sizeof(struct master_header), SEEK_SET);
3665 for (i = 0; i < myhdr.tch.entry_count; i++) 3665 for (i = 0; i < myhdr.tch.entry_count; i++)
3666 { 3666 {
3667 struct index_entry *idxp; 3667 struct index_entry *idxp;
3668 3668
3669#ifdef HAVE_TC_RAMCACHE 3669#ifdef HAVE_TC_RAMCACHE
3670 /* Use RAM DB if available for greater speed */ 3670 /* Use RAM DB if available for greater speed */
3671 if (tc_stat.ramcache) 3671 if (tc_stat.ramcache)
@@ -3680,30 +3680,30 @@ static bool delete_entry(long idx_id)
3680 } 3680 }
3681 idxp = &idx; 3681 idxp = &idx;
3682 } 3682 }
3683 3683
3684 if (idxp->flag & FLAG_DELETED) 3684 if (idxp->flag & FLAG_DELETED)
3685 continue; 3685 continue;
3686 3686
3687 for (tag = 0; tag < TAG_COUNT; tag++) 3687 for (tag = 0; tag < TAG_COUNT; tag++)
3688 { 3688 {
3689 if (TAGCACHE_IS_NUMERIC(tag)) 3689 if (TAGCACHE_IS_NUMERIC(tag))
3690 continue; 3690 continue;
3691 3691
3692 if (idxp->tag_seek[tag] == myidx.tag_seek[tag]) 3692 if (idxp->tag_seek[tag] == myidx.tag_seek[tag])
3693 in_use[tag]++; 3693 in_use[tag]++;
3694 } 3694 }
3695 } 3695 }
3696 3696
3697 /* Now delete all tags no longer in use. */ 3697 /* Now delete all tags no longer in use. */
3698 for (tag = 0; tag < TAG_COUNT; tag++) 3698 for (tag = 0; tag < TAG_COUNT; tag++)
3699 { 3699 {
3700 struct tagcache_header tch; 3700 struct tagcache_header tch;
3701 int oldseek = myidx.tag_seek[tag]; 3701 int oldseek = myidx.tag_seek[tag];
3702 3702
3703 if (TAGCACHE_IS_NUMERIC(tag)) 3703 if (TAGCACHE_IS_NUMERIC(tag))
3704 continue; 3704 continue;
3705 3705
3706 /** 3706 /**
3707 * Replace tag seek with a hash value of the field string data. 3707 * Replace tag seek with a hash value of the field string data.
3708 * That way runtime statistics of moved or altered files can be 3708 * That way runtime statistics of moved or altered files can be
3709 * resurrected. 3709 * resurrected.
@@ -3724,11 +3724,11 @@ static bool delete_entry(long idx_id)
3724#endif /* HAVE_TC_RAMCACHE */ 3724#endif /* HAVE_TC_RAMCACHE */
3725 { 3725 {
3726 struct tagfile_entry tfe; 3726 struct tagfile_entry tfe;
3727 3727
3728 /* Open the index file, which contains the tag names. */ 3728 /* Open the index file, which contains the tag names. */
3729 if ((fd = open_tag_fd(&tch, tag, true)) < 0) 3729 if ((fd = open_tag_fd(&tch, tag, true)) < 0)
3730 goto cleanup; 3730 goto cleanup;
3731 3731
3732 /* Skip the header block */ 3732 /* Skip the header block */
3733 lseek(fd, myidx.tag_seek[tag], SEEK_SET); 3733 lseek(fd, myidx.tag_seek[tag], SEEK_SET);
3734 if (ecread_tagfile_entry(fd, &tfe) != sizeof(struct tagfile_entry)) 3734 if (ecread_tagfile_entry(fd, &tfe) != sizeof(struct tagfile_entry))
@@ -3736,16 +3736,16 @@ static bool delete_entry(long idx_id)
3736 logf("delete_entry(): read error #3"); 3736 logf("delete_entry(): read error #3");
3737 goto cleanup; 3737 goto cleanup;
3738 } 3738 }
3739 3739
3740 if (read(fd, buf, tfe.tag_length) != tfe.tag_length) 3740 if (read(fd, buf, tfe.tag_length) != tfe.tag_length)
3741 { 3741 {
3742 logf("delete_entry(): read error #4"); 3742 logf("delete_entry(): read error #4");
3743 goto cleanup; 3743 goto cleanup;
3744 } 3744 }
3745 3745
3746 myidx.tag_seek[tag] = crc_32(buf, strlen(buf), 0xffffffff); 3746 myidx.tag_seek[tag] = crc_32(buf, strlen(buf), 0xffffffff);
3747 } 3747 }
3748 3748
3749 if (in_use[tag]) 3749 if (in_use[tag])
3750 { 3750 {
3751 logf("in use: %d/%d", tag, in_use[tag]); 3751 logf("in use: %d/%d", tag, in_use[tag]);
@@ -3756,7 +3756,7 @@ static bool delete_entry(long idx_id)
3756 } 3756 }
3757 continue; 3757 continue;
3758 } 3758 }
3759 3759
3760#ifdef HAVE_TC_RAMCACHE 3760#ifdef HAVE_TC_RAMCACHE
3761 /* Delete from ram. */ 3761 /* Delete from ram. */
3762 if (tc_stat.ramcache && tag != tag_filename) 3762 if (tc_stat.ramcache && tag != tag_filename)
@@ -3766,32 +3766,32 @@ static bool delete_entry(long idx_id)
3766 tagentry->tag_data[0] = '\0'; 3766 tagentry->tag_data[0] = '\0';
3767 } 3767 }
3768#endif /* HAVE_TC_RAMCACHE */ 3768#endif /* HAVE_TC_RAMCACHE */
3769 3769
3770 /* Open the index file, which contains the tag names. */ 3770 /* Open the index file, which contains the tag names. */
3771 if (fd < 0) 3771 if (fd < 0)
3772 { 3772 {
3773 if ((fd = open_tag_fd(&tch, tag, true)) < 0) 3773 if ((fd = open_tag_fd(&tch, tag, true)) < 0)
3774 goto cleanup; 3774 goto cleanup;
3775 } 3775 }
3776 3776
3777 /* Skip the header block */ 3777 /* Skip the header block */
3778 lseek(fd, oldseek + sizeof(struct tagfile_entry), SEEK_SET); 3778 lseek(fd, oldseek + sizeof(struct tagfile_entry), SEEK_SET);
3779 3779
3780 /* Debug, print 10 first characters of the tag 3780 /* Debug, print 10 first characters of the tag
3781 read(fd, buf, 10); 3781 read(fd, buf, 10);
3782 buf[10]='\0'; 3782 buf[10]='\0';
3783 logf("TAG:%s", buf); 3783 logf("TAG:%s", buf);
3784 lseek(fd, -10, SEEK_CUR); 3784 lseek(fd, -10, SEEK_CUR);
3785 */ 3785 */
3786 3786
3787 /* Write first data byte in tag as \0 */ 3787 /* Write first data byte in tag as \0 */
3788 write(fd, "", 1); 3788 write(fd, "", 1);
3789 3789
3790 /* Now tag data has been removed */ 3790 /* Now tag data has been removed */
3791 close(fd); 3791 close(fd);
3792 fd = -1; 3792 fd = -1;
3793 } 3793 }
3794 3794
3795 /* Write index entry back into master index. */ 3795 /* Write index entry back into master index. */
3796 lseek(masterfd, sizeof(struct master_header) + 3796 lseek(masterfd, sizeof(struct master_header) +
3797 (idx_id * sizeof(struct index_entry)), SEEK_SET); 3797 (idx_id * sizeof(struct index_entry)), SEEK_SET);
@@ -3800,17 +3800,17 @@ static bool delete_entry(long idx_id)
3800 logf("delete_entry(): write_error #2"); 3800 logf("delete_entry(): write_error #2");
3801 goto cleanup; 3801 goto cleanup;
3802 } 3802 }
3803 3803
3804 close(masterfd); 3804 close(masterfd);
3805 3805
3806 return true; 3806 return true;
3807 3807
3808 cleanup: 3808 cleanup:
3809 if (fd >= 0) 3809 if (fd >= 0)
3810 close(fd); 3810 close(fd);
3811 if (masterfd >= 0) 3811 if (masterfd >= 0)
3812 close(masterfd); 3812 close(masterfd);
3813 3813
3814 return false; 3814 return false;
3815} 3815}
3816 3816
@@ -3822,10 +3822,10 @@ static bool check_event_queue(void)
3822{ 3822{
3823#ifndef __PCTOOL__ 3823#ifndef __PCTOOL__
3824 struct queue_event ev; 3824 struct queue_event ev;
3825 3825
3826 if(!queue_peek(&tagcache_queue, &ev)) 3826 if(!queue_peek(&tagcache_queue, &ev))
3827 return false; 3827 return false;
3828 3828
3829 switch (ev.id) 3829 switch (ev.id)
3830 { 3830 {
3831 case Q_STOP_SCAN: 3831 case Q_STOP_SCAN:
@@ -3834,7 +3834,7 @@ static bool check_event_queue(void)
3834 return true; 3834 return true;
3835 } 3835 }
3836#endif /* __PCTOOL__ */ 3836#endif /* __PCTOOL__ */
3837 3837
3838 return false; 3838 return false;
3839} 3839}
3840 3840
@@ -3874,12 +3874,12 @@ static bool allocate_tagcache(void)
3874 int fd = open_master_fd(&tcmh, false); 3874 int fd = open_master_fd(&tcmh, false);
3875 if (fd < 0) 3875 if (fd < 0)
3876 return false; 3876 return false;
3877 3877
3878 close(fd); 3878 close(fd);
3879 3879
3880 /** 3880 /**
3881 * Now calculate the required cache size plus 3881 * Now calculate the required cache size plus
3882 * some extra space for alignment fixes. 3882 * some extra space for alignment fixes.
3883 */ 3883 */
3884 size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + 3884 size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE +
3885 sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); 3885 sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *);
@@ -3910,14 +3910,14 @@ static bool tagcache_dumpload(void)
3910 3910
3911 tcramcache.handle = 0; 3911 tcramcache.handle = 0;
3912 tcramcache.hdr = NULL; 3912 tcramcache.hdr = NULL;
3913 3913
3914 fd = open(TAGCACHE_STATEFILE, O_RDONLY); 3914 fd = open(TAGCACHE_STATEFILE, O_RDONLY);
3915 if (fd < 0) 3915 if (fd < 0)
3916 { 3916 {
3917 logf("no tagcache statedump"); 3917 logf("no tagcache statedump");
3918 return false; 3918 return false;
3919 } 3919 }
3920 3920
3921 /* Check the statefile memory placement */ 3921 /* Check the statefile memory placement */
3922 rc = read(fd, &shdr, sizeof(struct statefile_header)); 3922 rc = read(fd, &shdr, sizeof(struct statefile_header));
3923 if (rc != sizeof(struct statefile_header) 3923 if (rc != sizeof(struct statefile_header)
@@ -3953,13 +3953,13 @@ static bool tagcache_dumpload(void)
3953 } 3953 }
3954 3954
3955 tc_stat = shdr.tc_stat; 3955 tc_stat = shdr.tc_stat;
3956 3956
3957 /* Now fix the pointers */ 3957 /* Now fix the pointers */
3958 fix_ramcache(shdr.hdr, tcramcache.hdr); 3958 fix_ramcache(shdr.hdr, tcramcache.hdr);
3959 3959
3960 /* Load the tagcache master header (should match the actual DB file header). */ 3960 /* Load the tagcache master header (should match the actual DB file header). */
3961 memcpy(&current_tcmh, &shdr.mh, sizeof current_tcmh); 3961 memcpy(&current_tcmh, &shdr.mh, sizeof current_tcmh);
3962 3962
3963 return true; 3963 return true;
3964} 3964}
3965 3965
@@ -3967,30 +3967,30 @@ static bool tagcache_dumpsave(void)
3967{ 3967{
3968 struct statefile_header shdr; 3968 struct statefile_header shdr;
3969 int fd; 3969 int fd;
3970 3970
3971 if (!tc_stat.ramcache) 3971 if (!tc_stat.ramcache)
3972 return false; 3972 return false;
3973 3973
3974 fd = open(TAGCACHE_STATEFILE, O_WRONLY | O_CREAT | O_TRUNC, 0666); 3974 fd = open(TAGCACHE_STATEFILE, O_WRONLY | O_CREAT | O_TRUNC, 0666);
3975 if (fd < 0) 3975 if (fd < 0)
3976 { 3976 {
3977 logf("failed to create a statedump"); 3977 logf("failed to create a statedump");
3978 return false; 3978 return false;
3979 } 3979 }
3980 3980
3981 /* Create the header */ 3981 /* Create the header */
3982 shdr.magic = TAGCACHE_STATEFILE_MAGIC; 3982 shdr.magic = TAGCACHE_STATEFILE_MAGIC;
3983 shdr.hdr = tcramcache.hdr; 3983 shdr.hdr = tcramcache.hdr;
3984 memcpy(&shdr.mh, &current_tcmh, sizeof current_tcmh); 3984 memcpy(&shdr.mh, &current_tcmh, sizeof current_tcmh);
3985 memcpy(&shdr.tc_stat, &tc_stat, sizeof tc_stat); 3985 memcpy(&shdr.tc_stat, &tc_stat, sizeof tc_stat);
3986 write(fd, &shdr, sizeof shdr); 3986 write(fd, &shdr, sizeof shdr);
3987 3987
3988 /* And dump the data too */ 3988 /* And dump the data too */
3989 tcrc_buffer_lock(); 3989 tcrc_buffer_lock();
3990 write(fd, tcramcache.hdr, tc_stat.ramcache_allocated); 3990 write(fd, tcramcache.hdr, tc_stat.ramcache_allocated);
3991 tcrc_buffer_unlock(); 3991 tcrc_buffer_unlock();
3992 close(fd); 3992 close(fd);
3993 3993
3994 return true; 3994 return true;
3995} 3995}
3996#endif /* HAVE_EEPROM_SETTINGS */ 3996#endif /* HAVE_EEPROM_SETTINGS */
@@ -4014,7 +4014,7 @@ static bool load_tagcache(void)
4014 logf("loading tagcache to ram..."); 4014 logf("loading tagcache to ram...");
4015 4015
4016 tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */ 4016 tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */
4017 4017
4018 fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); 4018 fd = open(TAGCACHE_FILE_MASTER, O_RDONLY);
4019 if (fd < 0) 4019 if (fd < 0)
4020 { 4020 {
@@ -4100,7 +4100,7 @@ static bool load_tagcache(void)
4100 logf("Too big tagcache #10.75"); 4100 logf("Too big tagcache #10.75");
4101 goto failure; 4101 goto failure;
4102 } 4102 }
4103 4103
4104 struct tagfile_entry *fe = (struct tagfile_entry *)p; 4104 struct tagfile_entry *fe = (struct tagfile_entry *)p;
4105 off_t pos = lseek(fd, 0, SEEK_CUR); 4105 off_t pos = lseek(fd, 0, SEEK_CUR);
4106 4106
@@ -4234,7 +4234,7 @@ static bool load_tagcache(void)
4234 4234
4235 close(fd); 4235 close(fd);
4236 } 4236 }
4237 4237
4238 tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft; 4238 tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft;
4239 logf("tagcache loaded into ram!"); 4239 logf("tagcache loaded into ram!");
4240 logf("utilization: %d%%", 100*tc_stat.ramcache_used / tc_stat.ramcache_allocated); 4240 logf("utilization: %d%%", 100*tc_stat.ramcache_used / tc_stat.ramcache_allocated);
@@ -4255,11 +4255,11 @@ static bool check_deleted_files(void)
4255 int fd; 4255 int fd;
4256 char buf[TAG_MAXLEN+32]; 4256 char buf[TAG_MAXLEN+32];
4257 struct tagfile_entry tfe; 4257 struct tagfile_entry tfe;
4258 4258
4259 logf("reverse scan..."); 4259 logf("reverse scan...");
4260 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag_filename); 4260 snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, tag_filename);
4261 fd = open(buf, O_RDONLY); 4261 fd = open(buf, O_RDONLY);
4262 4262
4263 if (fd < 0) 4263 if (fd < 0)
4264 { 4264 {
4265 logf("%s open fail", buf); 4265 logf("%s open fail", buf);
@@ -4267,7 +4267,7 @@ static bool check_deleted_files(void)
4267 } 4267 }
4268 4268
4269 lseek(fd, sizeof(struct tagcache_header), SEEK_SET); 4269 lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
4270 while (ecread_tagfile_entry(fd, &tfe) == sizeof(struct tagfile_entry) 4270 while (ecread_tagfile_entry(fd, &tfe) == sizeof(struct tagfile_entry)
4271 && !check_event_queue()) 4271 && !check_event_queue())
4272 { 4272 {
4273 if (tfe.tag_length >= (long)sizeof(buf)-1) 4273 if (tfe.tag_length >= (long)sizeof(buf)-1)
@@ -4276,18 +4276,18 @@ static bool check_deleted_files(void)
4276 close(fd); 4276 close(fd);
4277 return false; 4277 return false;
4278 } 4278 }
4279 4279
4280 if (read(fd, buf, tfe.tag_length) != tfe.tag_length) 4280 if (read(fd, buf, tfe.tag_length) != tfe.tag_length)
4281 { 4281 {
4282 logf("read error #14"); 4282 logf("read error #14");
4283 close(fd); 4283 close(fd);
4284 return false; 4284 return false;
4285 } 4285 }
4286 4286
4287 /* Check if the file has already deleted from the db. */ 4287 /* Check if the file has already deleted from the db. */
4288 if (*buf == '\0') 4288 if (*buf == '\0')
4289 continue; 4289 continue;
4290 4290
4291 /* Now check if the file exists. */ 4291 /* Now check if the file exists. */
4292 if (!file_exists(buf)) 4292 if (!file_exists(buf))
4293 { 4293 {
@@ -4298,11 +4298,11 @@ static bool check_deleted_files(void)
4298 4298
4299 do_timed_yield(); 4299 do_timed_yield();
4300 } 4300 }
4301 4301
4302 close(fd); 4302 close(fd);
4303 4303
4304 logf("done"); 4304 logf("done");
4305 4305
4306 return true; 4306 return true;
4307} 4307}
4308 4308
@@ -4354,7 +4354,7 @@ static bool search_root_exists(const char *path)
4354 * search root. 4354 * search root.
4355 * 4355 *
4356 * Returns true if it added the path to the search roots 4356 * Returns true if it added the path to the search roots
4357 * 4357 *
4358 * Windows 2000 and greater supports symlinks, but they don't provide 4358 * Windows 2000 and greater supports symlinks, but they don't provide
4359 * realpath() or readlink(), and symlinks are rarely used on them so 4359 * realpath() or readlink(), and symlinks are rarely used on them so
4360 * ignore this for windows for now 4360 * ignore this for windows for now
@@ -4490,20 +4490,20 @@ static bool check_dir(const char *dirname, int add_files)
4490 else if (add_files) 4490 else if (add_files)
4491 { 4491 {
4492 tc_stat.curentry = curpath; 4492 tc_stat.curentry = curpath;
4493 4493
4494 /* Add a new entry to the temporary db file. */ 4494 /* Add a new entry to the temporary db file. */
4495 add_tagcache(curpath, info.mtime); 4495 add_tagcache(curpath, info.mtime);
4496 4496
4497 /* Wait until current path for debug screen is read and unset. */ 4497 /* Wait until current path for debug screen is read and unset. */
4498 while (tc_stat.syncscreen && tc_stat.curentry != NULL) 4498 while (tc_stat.syncscreen && tc_stat.curentry != NULL)
4499 yield(); 4499 yield();
4500 4500
4501 tc_stat.curentry = NULL; 4501 tc_stat.curentry = NULL;
4502 } 4502 }
4503 4503
4504 curpath[len] = '\0'; 4504 curpath[len] = '\0';
4505 } 4505 }
4506 4506
4507 closedir(dir); 4507 closedir(dir);
4508 4508
4509 return success; 4509 return success;
@@ -4532,13 +4532,13 @@ void do_tagcache_build(const char *path[])
4532 data_size = 0; 4532 data_size = 0;
4533 total_entry_count = 0; 4533 total_entry_count = 0;
4534 processed_dir_count = 0; 4534 processed_dir_count = 0;
4535 4535
4536#ifdef HAVE_DIRCACHE 4536#ifdef HAVE_DIRCACHE
4537 dircache_wait(); 4537 dircache_wait();
4538#endif 4538#endif
4539 4539
4540 logf("updating tagcache"); 4540 logf("updating tagcache");
4541 4541
4542 cachefd = open(TAGCACHE_FILE_TEMP, O_RDONLY); 4542 cachefd = open(TAGCACHE_FILE_TEMP, O_RDONLY);
4543 if (cachefd >= 0) 4543 if (cachefd >= 0)
4544 { 4544 {
@@ -4546,7 +4546,7 @@ void do_tagcache_build(const char *path[])
4546 close(cachefd); 4546 close(cachefd);
4547 return ; 4547 return ;
4548 } 4548 }
4549 4549
4550 cachefd = open(TAGCACHE_FILE_TEMP, O_RDWR | O_CREAT | O_TRUNC, 0666); 4550 cachefd = open(TAGCACHE_FILE_TEMP, O_RDWR | O_CREAT | O_TRUNC, 0666);
4551 if (cachefd < 0) 4551 if (cachefd < 0)
4552 { 4552 {
@@ -4555,7 +4555,7 @@ void do_tagcache_build(const char *path[])
4555 } 4555 }
4556 4556
4557 filenametag_fd = open_tag_fd(&header, tag_filename, false); 4557 filenametag_fd = open_tag_fd(&header, tag_filename, false);
4558 4558
4559 cpu_boost(true); 4559 cpu_boost(true);
4560 4560
4561 logf("Scanning files..."); 4561 logf("Scanning files...");
@@ -4620,7 +4620,7 @@ void do_tagcache_build(const char *path[])
4620#ifdef __PCTOOL__ 4620#ifdef __PCTOOL__
4621 free_tempbuf(); 4621 free_tempbuf();
4622#endif 4622#endif
4623 4623
4624#ifdef HAVE_TC_RAMCACHE 4624#ifdef HAVE_TC_RAMCACHE
4625 if (tcramcache.hdr) 4625 if (tcramcache.hdr)
4626 { 4626 {
@@ -4629,7 +4629,7 @@ void do_tagcache_build(const char *path[])
4629 queue_post(&tagcache_queue, Q_IMPORT_CHANGELOG, 0); 4629 queue_post(&tagcache_queue, Q_IMPORT_CHANGELOG, 0);
4630 } 4630 }
4631#endif 4631#endif
4632 4632
4633 cpu_boost(false); 4633 cpu_boost(false);
4634} 4634}
4635 4635
@@ -4652,9 +4652,9 @@ static void load_ramcache(void)
4652{ 4652{
4653 if (!tcramcache.hdr) 4653 if (!tcramcache.hdr)
4654 return ; 4654 return ;
4655 4655
4656 cpu_boost(true); 4656 cpu_boost(true);
4657 4657
4658 /* At first we should load the cache (if exists). */ 4658 /* At first we should load the cache (if exists). */
4659 tc_stat.ramcache = load_tagcache(); 4659 tc_stat.ramcache = load_tagcache();
4660 4660
@@ -4668,7 +4668,7 @@ static void load_ramcache(void)
4668 tcramcache.handle = 0; 4668 tcramcache.handle = 0;
4669 core_free(handle); 4669 core_free(handle);
4670 } 4670 }
4671 4671
4672 cpu_boost(false); 4672 cpu_boost(false);
4673} 4673}
4674 4674
@@ -4692,7 +4692,7 @@ static void tagcache_thread(void)
4692 allocate_tempbuf(); 4692 allocate_tempbuf();
4693 commit(); 4693 commit();
4694 free_tempbuf(); 4694 free_tempbuf();
4695 4695
4696#ifdef HAVE_TC_RAMCACHE 4696#ifdef HAVE_TC_RAMCACHE
4697#ifdef HAVE_EEPROM_SETTINGS 4697#ifdef HAVE_EEPROM_SETTINGS
4698 if (firmware_settings.initialized && firmware_settings.disk_clean 4698 if (firmware_settings.initialized && firmware_settings.disk_clean
@@ -4703,15 +4703,15 @@ static void tagcache_thread(void)
4703 4703
4704 remove(TAGCACHE_STATEFILE); 4704 remove(TAGCACHE_STATEFILE);
4705#endif /* HAVE_EEPROM_SETTINGS */ 4705#endif /* HAVE_EEPROM_SETTINGS */
4706 4706
4707 /* Allocate space for the tagcache if found on disk. */ 4707 /* Allocate space for the tagcache if found on disk. */
4708 if (global_settings.tagcache_ram && !tc_stat.ramcache) 4708 if (global_settings.tagcache_ram && !tc_stat.ramcache)
4709 allocate_tagcache(); 4709 allocate_tagcache();
4710#endif /* HAVE_TC_RAMCACHE */ 4710#endif /* HAVE_TC_RAMCACHE */
4711 4711
4712 cpu_boost(false); 4712 cpu_boost(false);
4713 tc_stat.initialized = true; 4713 tc_stat.initialized = true;
4714 4714
4715 /* Don't delay bootup with the header check but do it on background. */ 4715 /* Don't delay bootup with the header check but do it on background. */
4716 if (!tc_stat.ready) 4716 if (!tc_stat.ready)
4717 { 4717 {
@@ -4719,11 +4719,11 @@ static void tagcache_thread(void)
4719 tc_stat.ready = check_all_headers(); 4719 tc_stat.ready = check_all_headers();
4720 tc_stat.readyvalid = true; 4720 tc_stat.readyvalid = true;
4721 } 4721 }
4722 4722
4723 while (1) 4723 while (1)
4724 { 4724 {
4725 run_command_queue(false); 4725 run_command_queue(false);
4726 4726
4727 queue_wait_w_tmo(&tagcache_queue, &ev, HZ); 4727 queue_wait_w_tmo(&tagcache_queue, &ev, HZ);
4728 4728
4729 switch (ev.id) 4729 switch (ev.id)
@@ -4731,13 +4731,13 @@ static void tagcache_thread(void)
4731 case Q_IMPORT_CHANGELOG: 4731 case Q_IMPORT_CHANGELOG:
4732 tagcache_import_changelog(); 4732 tagcache_import_changelog();
4733 break; 4733 break;
4734 4734
4735 case Q_REBUILD: 4735 case Q_REBUILD:
4736 remove_files(); 4736 remove_files();
4737 remove(TAGCACHE_FILE_TEMP); 4737 remove(TAGCACHE_FILE_TEMP);
4738 tagcache_build(); 4738 tagcache_build();
4739 break; 4739 break;
4740 4740
4741 case Q_UPDATE: 4741 case Q_UPDATE:
4742 tagcache_build(); 4742 tagcache_build();
4743#ifdef HAVE_TC_RAMCACHE 4743#ifdef HAVE_TC_RAMCACHE
@@ -4745,13 +4745,13 @@ static void tagcache_thread(void)
4745#endif 4745#endif
4746 check_deleted_files(); 4746 check_deleted_files();
4747 break ; 4747 break ;
4748 4748
4749 case Q_START_SCAN: 4749 case Q_START_SCAN:
4750 check_done = false; 4750 check_done = false;
4751 case SYS_TIMEOUT: 4751 case SYS_TIMEOUT:
4752 if (check_done || !tc_stat.ready) 4752 if (check_done || !tc_stat.ready)
4753 break ; 4753 break ;
4754 4754
4755#ifdef HAVE_TC_RAMCACHE 4755#ifdef HAVE_TC_RAMCACHE
4756 if (!tc_stat.ramcache && global_settings.tagcache_ram) 4756 if (!tc_stat.ramcache && global_settings.tagcache_ram)
4757 { 4757 {
@@ -4764,24 +4764,24 @@ static void tagcache_thread(void)
4764 if (global_settings.tagcache_autoupdate) 4764 if (global_settings.tagcache_autoupdate)
4765 { 4765 {
4766 tagcache_build(); 4766 tagcache_build();
4767 4767
4768 /* This will be very slow unless dircache is enabled 4768 /* This will be very slow unless dircache is enabled
4769 or target is flash based, but do it anyway for 4769 or target is flash based, but do it anyway for
4770 consistency. */ 4770 consistency. */
4771 check_deleted_files(); 4771 check_deleted_files();
4772 } 4772 }
4773 4773
4774 logf("tagcache check done"); 4774 logf("tagcache check done");
4775 4775
4776 check_done = true; 4776 check_done = true;
4777 break ; 4777 break ;
4778 4778
4779 case Q_STOP_SCAN: 4779 case Q_STOP_SCAN:
4780 break ; 4780 break ;
4781 4781
4782 case SYS_POWEROFF: 4782 case SYS_POWEROFF:
4783 break ; 4783 break ;
4784 4784
4785 case SYS_USB_CONNECTED: 4785 case SYS_USB_CONNECTED:
4786 logf("USB: TagCache"); 4786 logf("USB: TagCache");
4787 usb_acknowledge(SYS_USB_CONNECTED_ACK); 4787 usb_acknowledge(SYS_USB_CONNECTED_ACK);
@@ -4795,11 +4795,11 @@ bool tagcache_prepare_shutdown(void)
4795{ 4795{
4796 if (tagcache_get_commit_step() > 0) 4796 if (tagcache_get_commit_step() > 0)
4797 return false; 4797 return false;
4798 4798
4799 tagcache_stop_scan(); 4799 tagcache_stop_scan();
4800 while (read_lock || write_lock) 4800 while (read_lock || write_lock)
4801 sleep(1); 4801 sleep(1);
4802 4802
4803 return true; 4803 return true;
4804} 4804}
4805 4805
@@ -4807,7 +4807,7 @@ void tagcache_shutdown(void)
4807{ 4807{
4808 /* Flush the command queue. */ 4808 /* Flush the command queue. */
4809 run_command_queue(true); 4809 run_command_queue(true);
4810 4810
4811#if defined(HAVE_EEPROM_SETTINGS) && defined(HAVE_TC_RAMCACHE) 4811#if defined(HAVE_EEPROM_SETTINGS) && defined(HAVE_TC_RAMCACHE)
4812 if (tc_stat.ramcache) 4812 if (tc_stat.ramcache)
4813 tagcache_dumpsave(); 4813 tagcache_dumpsave();
@@ -4848,7 +4848,7 @@ struct tagcache_stat* tagcache_get_stat(void)
4848{ 4848{
4849 tc_stat.progress = get_progress(); 4849 tc_stat.progress = get_progress();
4850 tc_stat.processed_entries = processed_dir_count; 4850 tc_stat.processed_entries = processed_dir_count;
4851 4851
4852 return &tc_stat; 4852 return &tc_stat;
4853} 4853}
4854 4854
@@ -4861,7 +4861,7 @@ bool tagcache_update(void)
4861{ 4861{
4862 if (!tc_stat.ready) 4862 if (!tc_stat.ready)
4863 return false; 4863 return false;
4864 4864
4865 queue_post(&tagcache_queue, Q_UPDATE, 0); 4865 queue_post(&tagcache_queue, Q_UPDATE, 0);
4866 return false; 4866 return false;
4867} 4867}
@@ -4886,12 +4886,12 @@ void tagcache_init(void)
4886 memset(&current_tcmh, 0, sizeof(struct master_header)); 4886 memset(&current_tcmh, 0, sizeof(struct master_header));
4887 filenametag_fd = -1; 4887 filenametag_fd = -1;
4888 write_lock = read_lock = 0; 4888 write_lock = read_lock = 0;
4889 4889
4890#ifndef __PCTOOL__ 4890#ifndef __PCTOOL__
4891 mutex_init(&command_queue_mutex); 4891 mutex_init(&command_queue_mutex);
4892 queue_init(&tagcache_queue, true); 4892 queue_init(&tagcache_queue, true);
4893 create_thread(tagcache_thread, tagcache_stack, 4893 create_thread(tagcache_thread, tagcache_stack,
4894 sizeof(tagcache_stack), 0, tagcache_thread_name 4894 sizeof(tagcache_stack), 0, tagcache_thread_name
4895 IF_PRIO(, PRIORITY_BACKGROUND) 4895 IF_PRIO(, PRIORITY_BACKGROUND)
4896 IF_COP(, CPU)); 4896 IF_COP(, CPU));
4897#else 4897#else