diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-20 12:19:31 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-07-20 12:19:31 +0000 |
commit | cb8c79541504ce8a4e1d4243ccec826707e30544 (patch) | |
tree | 66c065035b31fc480db2fe3e83daf1672829a87a /apps/tagcache.c | |
parent | 7b5af8c045d1db6e805981e1c6d1b32de200e3f3 (diff) | |
download | rockbox-cb8c79541504ce8a4e1d4243ccec826707e30544.tar.gz rockbox-cb8c79541504ce8a4e1d4243ccec826707e30544.zip |
Support importing runtimedb data from ascii files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10260 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r-- | apps/tagcache.c | 645 |
1 files changed, 449 insertions, 196 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index dd52a3d716..8df7aef8de 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -61,6 +61,10 @@ static const int unique_tags[] = { tag_artist, tag_album, tag_genre, tag_compose | |||
61 | static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate, | 61 | static const int numeric_tags[] = { tag_year, tag_tracknumber, tag_length, tag_bitrate, |
62 | tag_playcount, tag_playtime, tag_lastplayed, tag_virt_autoscore }; | 62 | tag_playcount, tag_playtime, tag_lastplayed, tag_virt_autoscore }; |
63 | 63 | ||
64 | static const char *tags_str[] = { "artist", "album", "genre", "title", | ||
65 | "filename", "composer", "year", "tracknumber", "bitrate", "length", | ||
66 | "playcount", "playtime", "lastplayed" }; | ||
67 | |||
64 | /* Status information of the tagcache. */ | 68 | /* Status information of the tagcache. */ |
65 | static struct tagcache_stat stat; | 69 | static struct tagcache_stat stat; |
66 | 70 | ||
@@ -77,33 +81,41 @@ enum tagcache_queue { | |||
77 | 81 | ||
78 | /* Variable-length tag entry in tag files. */ | 82 | /* Variable-length tag entry in tag files. */ |
79 | struct tagfile_entry { | 83 | struct tagfile_entry { |
80 | short tag_length; | 84 | short tag_length; /* Length of the data in bytes including '\0' */ |
81 | short idx_id; | 85 | short idx_id; /* Corresponding entry location in index file of not unique tags */ |
82 | char tag_data[0]; | 86 | char tag_data[0]; /* Begin of the tag data */ |
83 | }; | 87 | }; |
84 | 88 | ||
85 | /* Fixed-size tag entry in master db index. */ | 89 | /* Fixed-size tag entry in master db index. */ |
86 | struct index_entry { | 90 | struct index_entry { |
87 | long tag_seek[TAG_COUNT]; | 91 | long tag_seek[TAG_COUNT]; /* Location of tag data or numeric tag data */ |
88 | long flag; | 92 | long flag; /* Status flags */ |
89 | }; | 93 | }; |
90 | 94 | ||
91 | /* Header is the same in every file. */ | 95 | /* Header is the same in every file. */ |
92 | struct tagcache_header { | 96 | struct tagcache_header { |
93 | long magic; | 97 | long magic; /* Header version number */ |
94 | long datasize; | 98 | long datasize; /* Data size in bytes */ |
95 | long entry_count; | 99 | long entry_count; /* Number of entries in this file */ |
100 | }; | ||
101 | |||
102 | struct master_header { | ||
103 | struct tagcache_header tch; | ||
104 | long serial; /* Increasing counting number */ | ||
96 | }; | 105 | }; |
97 | 106 | ||
107 | static long current_serial; | ||
108 | |||
98 | #ifdef HAVE_TC_RAMCACHE | 109 | #ifdef HAVE_TC_RAMCACHE |
99 | /* Header is created when loading database to ram. */ | 110 | /* Header is created when loading database to ram. */ |
100 | struct ramcache_header { | 111 | struct ramcache_header { |
101 | struct tagcache_header h; | 112 | struct master_header h; /* Header from the master index */ |
102 | struct index_entry *indices; | 113 | struct index_entry *indices; /* Master index file content */ |
103 | char *tags[TAG_COUNT]; | 114 | char *tags[TAG_COUNT]; /* Tag file content (not including filename tag) */ |
104 | int entry_count[TAG_COUNT]; | 115 | int entry_count[TAG_COUNT]; /* Number of entries in the indices. */ |
105 | }; | 116 | }; |
106 | 117 | ||
118 | /* Pointer to allocated ramcache_header */ | ||
107 | static struct ramcache_header *hdr; | 119 | static struct ramcache_header *hdr; |
108 | #endif | 120 | #endif |
109 | 121 | ||
@@ -140,6 +152,24 @@ static int total_entry_count = 0; | |||
140 | static int data_size = 0; | 152 | static int data_size = 0; |
141 | static int processed_dir_count; | 153 | static int processed_dir_count; |
142 | 154 | ||
155 | int tagcache_str_to_tag(const char *str) | ||
156 | { | ||
157 | int i; | ||
158 | |||
159 | for (i = 0; i < (long)(sizeof(tags_str)/sizeof(tags_str[0])); i++) | ||
160 | { | ||
161 | if (!strcasecmp(tags_str[i], str)) | ||
162 | return i; | ||
163 | } | ||
164 | |||
165 | return -1; | ||
166 | } | ||
167 | |||
168 | const char* tagcache_tag_to_str(int tag) | ||
169 | { | ||
170 | return tags_str[tag]; | ||
171 | } | ||
172 | |||
143 | bool tagcache_is_numeric_tag(int type) | 173 | bool tagcache_is_numeric_tag(int type) |
144 | { | 174 | { |
145 | int i; | 175 | int i; |
@@ -207,7 +237,7 @@ static long find_entry_ram(const char *filename, | |||
207 | else | 237 | else |
208 | i = 0; | 238 | i = 0; |
209 | 239 | ||
210 | for (; i < hdr->h.entry_count; i++) | 240 | for (; i < hdr->h.tch.entry_count; i++) |
211 | { | 241 | { |
212 | if (hdr->indices[i].tag_seek[tag_filename] == (long)dc) | 242 | if (hdr->indices[i].tag_seek[tag_filename] == (long)dc) |
213 | { | 243 | { |
@@ -257,7 +287,7 @@ static long find_entry_disk(const char *filename) | |||
257 | if (last_pos > 0) | 287 | if (last_pos > 0) |
258 | lseek(fd, last_pos, SEEK_SET); | 288 | lseek(fd, last_pos, SEEK_SET); |
259 | else | 289 | else |
260 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | 290 | lseek(fd, sizeof(struct master_header), SEEK_SET); |
261 | 291 | ||
262 | while (true) | 292 | while (true) |
263 | { | 293 | { |
@@ -320,7 +350,7 @@ static long find_entry_disk(const char *filename) | |||
320 | return tfe.idx_id; | 350 | return tfe.idx_id; |
321 | } | 351 | } |
322 | 352 | ||
323 | bool tagcache_find_index(struct tagcache_search *tcs, const char *filename) | 353 | static int find_index(const char *filename) |
324 | { | 354 | { |
325 | long idx_id = -1; | 355 | long idx_id = -1; |
326 | 356 | ||
@@ -335,6 +365,17 @@ bool tagcache_find_index(struct tagcache_search *tcs, const char *filename) | |||
335 | if (idx_id < 0) | 365 | if (idx_id < 0) |
336 | return false; | 366 | return false; |
337 | 367 | ||
368 | return idx_id; | ||
369 | } | ||
370 | |||
371 | bool tagcache_find_index(struct tagcache_search *tcs, const char *filename) | ||
372 | { | ||
373 | int idx_id; | ||
374 | |||
375 | idx_id = find_index(filename); | ||
376 | if (idx_id < 0) | ||
377 | return false; | ||
378 | |||
338 | if (!tagcache_search(tcs, tag_filename)) | 379 | if (!tagcache_search(tcs, tag_filename)) |
339 | return false; | 380 | return false; |
340 | 381 | ||
@@ -359,7 +400,7 @@ static bool tagcache_get_index(const struct tagcache_search *tcs, | |||
359 | #endif | 400 | #endif |
360 | 401 | ||
361 | lseek(tcs->masterfd, idxid * sizeof(struct index_entry) | 402 | lseek(tcs->masterfd, idxid * sizeof(struct index_entry) |
362 | + sizeof(struct tagcache_header), SEEK_SET); | 403 | + sizeof(struct master_header), SEEK_SET); |
363 | if (read(tcs->masterfd, idx, sizeof(struct index_entry)) != | 404 | if (read(tcs->masterfd, idx, sizeof(struct index_entry)) != |
364 | sizeof(struct index_entry)) | 405 | sizeof(struct index_entry)) |
365 | { | 406 | { |
@@ -453,7 +494,7 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
453 | { | 494 | { |
454 | int j; | 495 | int j; |
455 | 496 | ||
456 | for (i = tcs->seek_pos; i < hdr->h.entry_count; i++) | 497 | for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) |
457 | { | 498 | { |
458 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 499 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
459 | break ; | 500 | break ; |
@@ -531,7 +572,7 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
531 | #endif | 572 | #endif |
532 | 573 | ||
533 | lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + | 574 | lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + |
534 | sizeof(struct tagcache_header), SEEK_SET); | 575 | sizeof(struct master_header), SEEK_SET); |
535 | 576 | ||
536 | while (read(tcs->masterfd, &entry, sizeof(struct index_entry)) == | 577 | while (read(tcs->masterfd, &entry, sizeof(struct index_entry)) == |
537 | sizeof(struct index_entry)) | 578 | sizeof(struct index_entry)) |
@@ -612,9 +653,53 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
612 | } | 653 | } |
613 | 654 | ||
614 | 655 | ||
656 | static void remove_files(void) | ||
657 | { | ||
658 | int i; | ||
659 | char buf[MAX_PATH]; | ||
660 | |||
661 | stat.ready = false; | ||
662 | remove(TAGCACHE_FILE_MASTER); | ||
663 | for (i = 0; i < TAG_COUNT; i++) | ||
664 | { | ||
665 | if (tagcache_is_numeric_tag(i)) | ||
666 | continue; | ||
667 | |||
668 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i); | ||
669 | remove(buf); | ||
670 | } | ||
671 | } | ||
672 | |||
673 | static int open_master_fd(struct master_header *hdr, bool write) | ||
674 | { | ||
675 | int fd; | ||
676 | |||
677 | fd = open(TAGCACHE_FILE_MASTER, write ? O_RDWR : O_RDONLY); | ||
678 | if (fd < 0) | ||
679 | { | ||
680 | logf("master file open failed for R/W"); | ||
681 | stat.ready = false; | ||
682 | return fd; | ||
683 | } | ||
684 | |||
685 | /* Check the header. */ | ||
686 | read(fd, hdr, sizeof(struct master_header)); | ||
687 | if (hdr->tch.magic != TAGCACHE_MAGIC) | ||
688 | { | ||
689 | logf("header error"); | ||
690 | stat.ready = false; | ||
691 | close(fd); | ||
692 | remove_files(); | ||
693 | return -2; | ||
694 | } | ||
695 | |||
696 | return fd; | ||
697 | } | ||
698 | |||
615 | bool tagcache_search(struct tagcache_search *tcs, int tag) | 699 | bool tagcache_search(struct tagcache_search *tcs, int tag) |
616 | { | 700 | { |
617 | struct tagcache_header h; | 701 | struct tagcache_header tag_hdr; |
702 | struct master_header master_hdr; | ||
618 | char buf[MAX_PATH]; | 703 | char buf[MAX_PATH]; |
619 | int i; | 704 | int i; |
620 | 705 | ||
@@ -622,7 +707,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
622 | tagcache_search_finish(tcs); | 707 | tagcache_search_finish(tcs); |
623 | 708 | ||
624 | memset(tcs, 0, sizeof(struct tagcache_search)); | 709 | memset(tcs, 0, sizeof(struct tagcache_search)); |
625 | if (stat.commit_step > 0) | 710 | if (stat.commit_step > 0 || !stat.ready) |
626 | return false; | 711 | return false; |
627 | 712 | ||
628 | tcs->position = sizeof(struct tagcache_header); | 713 | tcs->position = sizeof(struct tagcache_header); |
@@ -659,29 +744,17 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
659 | } | 744 | } |
660 | 745 | ||
661 | /* Check the header. */ | 746 | /* Check the header. */ |
662 | if (read(tcs->idxfd[tcs->type], &h, sizeof(struct tagcache_header)) != | 747 | if (read(tcs->idxfd[tcs->type], &tag_hdr, sizeof(struct tagcache_header)) != |
663 | sizeof(struct tagcache_header) || h.magic != TAGCACHE_MAGIC) | 748 | sizeof(struct tagcache_header) || tag_hdr.magic != TAGCACHE_MAGIC) |
664 | { | 749 | { |
665 | logf("incorrect header"); | 750 | logf("incorrect header"); |
666 | return false; | 751 | return false; |
667 | } | 752 | } |
668 | 753 | ||
669 | tcs->masterfd = open(TAGCACHE_FILE_MASTER, O_RDONLY); | 754 | tcs->masterfd = open_master_fd(&master_hdr, false); |
670 | 755 | ||
671 | if (tcs->masterfd < 0) | 756 | if (tcs->masterfd < 0) |
672 | { | ||
673 | logf("open fail"); | ||
674 | return false; | 757 | return false; |
675 | } | ||
676 | |||
677 | if (read(tcs->masterfd, &h, sizeof(struct tagcache_header)) != | ||
678 | sizeof(struct tagcache_header) || h.magic != TAGCACHE_MAGIC) | ||
679 | { | ||
680 | logf("header error"); | ||
681 | close(tcs->masterfd); | ||
682 | tcs->masterfd = -1; | ||
683 | return false; | ||
684 | } | ||
685 | } | 758 | } |
686 | 759 | ||
687 | return true; | 760 | return true; |
@@ -1164,22 +1237,6 @@ static void add_tagcache(const char *path) | |||
1164 | total_entry_count++; | 1237 | total_entry_count++; |
1165 | } | 1238 | } |
1166 | 1239 | ||
1167 | static void remove_files(void) | ||
1168 | { | ||
1169 | int i; | ||
1170 | char buf[MAX_PATH]; | ||
1171 | |||
1172 | remove(TAGCACHE_FILE_MASTER); | ||
1173 | for (i = 0; i < TAG_COUNT; i++) | ||
1174 | { | ||
1175 | if (tagcache_is_numeric_tag(i)) | ||
1176 | continue; | ||
1177 | |||
1178 | snprintf(buf, sizeof buf, TAGCACHE_FILE_INDEX, i); | ||
1179 | remove(buf); | ||
1180 | } | ||
1181 | } | ||
1182 | |||
1183 | static bool tempbuf_insert(char *str, int id, int idx_id, bool unique) | 1240 | static bool tempbuf_insert(char *str, int id, int idx_id, bool unique) |
1184 | { | 1241 | { |
1185 | struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf; | 1242 | struct tempbuf_searchidx *index = (struct tempbuf_searchidx *)tempbuf; |
@@ -1377,7 +1434,7 @@ inline static int tempbuf_find_location(int id) | |||
1377 | 1434 | ||
1378 | static bool build_numeric_index(int index_type, struct tagcache_header *h, int tmpfd) | 1435 | static bool build_numeric_index(int index_type, struct tagcache_header *h, int tmpfd) |
1379 | { | 1436 | { |
1380 | struct tagcache_header tch; | 1437 | struct master_header tcmh; |
1381 | struct index_entry idx; | 1438 | struct index_entry idx; |
1382 | int masterfd; | 1439 | int masterfd; |
1383 | int masterfd_pos; | 1440 | int masterfd_pos; |
@@ -1416,23 +1473,10 @@ static bool build_numeric_index(int index_type, struct tagcache_header *h, int t | |||
1416 | } | 1473 | } |
1417 | 1474 | ||
1418 | /* Update the entries in index. */ | 1475 | /* Update the entries in index. */ |
1419 | masterfd = open(TAGCACHE_FILE_MASTER, O_RDWR); | 1476 | if ( (masterfd = open_master_fd(&tcmh, true)) < 0) |
1420 | |||
1421 | if (masterfd < 0) | ||
1422 | { | ||
1423 | logf("No master file found!"); | ||
1424 | return false; | 1477 | return false; |
1425 | } | ||
1426 | 1478 | ||
1427 | if (read(masterfd, &tch, sizeof(struct tagcache_header)) != | 1479 | masterfd_pos = lseek(masterfd, tcmh.tch.entry_count * sizeof(struct index_entry), |
1428 | sizeof(struct tagcache_header) || tch.magic != TAGCACHE_MAGIC) | ||
1429 | { | ||
1430 | logf("header error"); | ||
1431 | close(masterfd); | ||
1432 | return false; | ||
1433 | } | ||
1434 | |||
1435 | masterfd_pos = lseek(masterfd, tch.entry_count * sizeof(struct index_entry), | ||
1436 | SEEK_CUR); | 1480 | SEEK_CUR); |
1437 | if (masterfd_pos == filesize(masterfd)) | 1481 | if (masterfd_pos == filesize(masterfd)) |
1438 | { | 1482 | { |
@@ -1481,6 +1525,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1481 | { | 1525 | { |
1482 | int i; | 1526 | int i; |
1483 | struct tagcache_header tch; | 1527 | struct tagcache_header tch; |
1528 | struct master_header tcmh; | ||
1484 | struct index_entry idxbuf[IDX_BUF_DEPTH]; | 1529 | struct index_entry idxbuf[IDX_BUF_DEPTH]; |
1485 | int idxbuf_pos; | 1530 | int idxbuf_pos; |
1486 | char buf[MAX_PATH]; | 1531 | char buf[MAX_PATH]; |
@@ -1617,12 +1662,14 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1617 | } | 1662 | } |
1618 | 1663 | ||
1619 | /* Write the header (write real values later). */ | 1664 | /* Write the header (write real values later). */ |
1620 | tch = *h; | 1665 | memset(&tcmh, 0, sizeof(struct master_header)); |
1621 | tch.entry_count = 0; | 1666 | tcmh.tch = *h; |
1622 | tch.datasize = 0; | 1667 | tcmh.tch.entry_count = 0; |
1623 | write(masterfd, &tch, sizeof(struct tagcache_header)); | 1668 | tcmh.tch.datasize = 0; |
1669 | write(masterfd, &tcmh, sizeof(struct master_header)); | ||
1624 | init = true; | 1670 | init = true; |
1625 | masterfd_pos = lseek(masterfd, 0, SEEK_CUR); | 1671 | masterfd_pos = lseek(masterfd, 0, SEEK_CUR); |
1672 | current_serial = 0; | ||
1626 | } | 1673 | } |
1627 | else | 1674 | else |
1628 | { | 1675 | { |
@@ -1632,8 +1679,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1632 | */ | 1679 | */ |
1633 | init = false; | 1680 | init = false; |
1634 | 1681 | ||
1635 | if (read(masterfd, &tch, sizeof(struct tagcache_header)) != | 1682 | if (read(masterfd, &tcmh, sizeof(struct master_header)) != |
1636 | sizeof(struct tagcache_header) || tch.magic != TAGCACHE_MAGIC) | 1683 | sizeof(struct master_header) || tcmh.tch.magic != TAGCACHE_MAGIC) |
1637 | { | 1684 | { |
1638 | logf("header error"); | 1685 | logf("header error"); |
1639 | close(fd); | 1686 | close(fd); |
@@ -1648,7 +1695,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1648 | * However, if the index is sorted, we need to update all tag | 1695 | * However, if the index is sorted, we need to update all tag |
1649 | * pointers in the master file for the current index. | 1696 | * pointers in the master file for the current index. |
1650 | */ | 1697 | */ |
1651 | masterfd_pos = lseek(masterfd, tch.entry_count * sizeof(struct index_entry), | 1698 | masterfd_pos = lseek(masterfd, tcmh.tch.entry_count * sizeof(struct index_entry), |
1652 | SEEK_CUR); | 1699 | SEEK_CUR); |
1653 | if (masterfd_pos == filesize(masterfd)) | 1700 | if (masterfd_pos == filesize(masterfd)) |
1654 | { | 1701 | { |
@@ -1698,7 +1745,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1698 | if (tagcache_is_unique_tag(index_type)) | 1745 | if (tagcache_is_unique_tag(index_type)) |
1699 | error = !tempbuf_insert(buf, i, -1, true); | 1746 | error = !tempbuf_insert(buf, i, -1, true); |
1700 | else | 1747 | else |
1701 | error = !tempbuf_insert(buf, i, tch.entry_count + i, false); | 1748 | error = !tempbuf_insert(buf, i, tcmh.tch.entry_count + i, false); |
1702 | 1749 | ||
1703 | if (error) | 1750 | if (error) |
1704 | { | 1751 | { |
@@ -1724,13 +1771,13 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1724 | * Now update all indexes in the master lookup file. | 1771 | * Now update all indexes in the master lookup file. |
1725 | */ | 1772 | */ |
1726 | logf("updating indices..."); | 1773 | logf("updating indices..."); |
1727 | lseek(masterfd, sizeof(struct tagcache_header), SEEK_SET); | 1774 | lseek(masterfd, sizeof(struct master_header), SEEK_SET); |
1728 | for (i = 0; i < tch.entry_count; i += idxbuf_pos) | 1775 | for (i = 0; i < tcmh.tch.entry_count; i += idxbuf_pos) |
1729 | { | 1776 | { |
1730 | int j; | 1777 | int j; |
1731 | int loc = lseek(masterfd, 0, SEEK_CUR); | 1778 | int loc = lseek(masterfd, 0, SEEK_CUR); |
1732 | 1779 | ||
1733 | idxbuf_pos = MIN(tch.entry_count - i, IDX_BUF_DEPTH); | 1780 | idxbuf_pos = MIN(tcmh.tch.entry_count - i, IDX_BUF_DEPTH); |
1734 | 1781 | ||
1735 | if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) != | 1782 | if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) != |
1736 | (int)sizeof(struct index_entry)*idxbuf_pos) | 1783 | (int)sizeof(struct index_entry)*idxbuf_pos) |
@@ -1761,7 +1808,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1761 | 1808 | ||
1762 | if (idxbuf[j].tag_seek[index_type] < 0) | 1809 | if (idxbuf[j].tag_seek[index_type] < 0) |
1763 | { | 1810 | { |
1764 | logf("update error: %d/%d", i+j, tch.entry_count); | 1811 | logf("update error: %d/%d", i+j, tcmh.tch.entry_count); |
1765 | error = true; | 1812 | error = true; |
1766 | goto error_exit; | 1813 | goto error_exit; |
1767 | } | 1814 | } |
@@ -1852,7 +1899,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1852 | /* Write to index file. */ | 1899 | /* Write to index file. */ |
1853 | idxbuf[j].tag_seek[index_type] = lseek(fd, 0, SEEK_CUR); | 1900 | idxbuf[j].tag_seek[index_type] = lseek(fd, 0, SEEK_CUR); |
1854 | fe.tag_length = entry.tag_length[index_type]; | 1901 | fe.tag_length = entry.tag_length[index_type]; |
1855 | fe.idx_id = tch.entry_count + i + j; | 1902 | fe.idx_id = tcmh.tch.entry_count + i + j; |
1856 | write(fd, &fe, sizeof(struct tagfile_entry)); | 1903 | write(fd, &fe, sizeof(struct tagfile_entry)); |
1857 | write(fd, buf, fe.tag_length); | 1904 | write(fd, buf, fe.tag_length); |
1858 | tempbufidx++; | 1905 | tempbufidx++; |
@@ -1910,7 +1957,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
1910 | 1957 | ||
1911 | static bool commit(void) | 1958 | static bool commit(void) |
1912 | { | 1959 | { |
1913 | struct tagcache_header header, header_old; | 1960 | struct tagcache_header tch; |
1961 | struct master_header tcmh; | ||
1914 | int i, len, rc; | 1962 | int i, len, rc; |
1915 | int tmpfd; | 1963 | int tmpfd; |
1916 | int masterfd; | 1964 | int masterfd; |
@@ -1930,9 +1978,9 @@ static bool commit(void) | |||
1930 | 1978 | ||
1931 | /* Load the header. */ | 1979 | /* Load the header. */ |
1932 | len = sizeof(struct tagcache_header); | 1980 | len = sizeof(struct tagcache_header); |
1933 | rc = read(tmpfd, &header, len); | 1981 | rc = read(tmpfd, &tch, len); |
1934 | 1982 | ||
1935 | if (header.magic != TAGCACHE_MAGIC || rc != len) | 1983 | if (tch.magic != TAGCACHE_MAGIC || rc != len) |
1936 | { | 1984 | { |
1937 | logf("incorrect header"); | 1985 | logf("incorrect header"); |
1938 | close(tmpfd); | 1986 | close(tmpfd); |
@@ -1941,7 +1989,7 @@ static bool commit(void) | |||
1941 | return false; | 1989 | return false; |
1942 | } | 1990 | } |
1943 | 1991 | ||
1944 | if (header.entry_count == 0) | 1992 | if (tch.entry_count == 0) |
1945 | { | 1993 | { |
1946 | logf("nothing to commit"); | 1994 | logf("nothing to commit"); |
1947 | close(tmpfd); | 1995 | close(tmpfd); |
@@ -1987,11 +2035,11 @@ static bool commit(void) | |||
1987 | return false; | 2035 | return false; |
1988 | } | 2036 | } |
1989 | 2037 | ||
1990 | logf("commit %d entries...", header.entry_count); | 2038 | logf("commit %d entries...", tch.entry_count); |
1991 | 2039 | ||
1992 | /* Now create the index files. */ | 2040 | /* Now create the index files. */ |
1993 | stat.commit_step = 0; | 2041 | stat.commit_step = 0; |
1994 | header.datasize = 0; | 2042 | tch.datasize = 0; |
1995 | stat.commit_delayed = false; | 2043 | stat.commit_delayed = false; |
1996 | 2044 | ||
1997 | for (i = 0; i < TAG_COUNT; i++) | 2045 | for (i = 0; i < TAG_COUNT; i++) |
@@ -2001,11 +2049,11 @@ static bool commit(void) | |||
2001 | stat.commit_step++; | 2049 | stat.commit_step++; |
2002 | if (tagcache_is_numeric_tag(i)) | 2050 | if (tagcache_is_numeric_tag(i)) |
2003 | { | 2051 | { |
2004 | build_numeric_index(i, &header, tmpfd); | 2052 | build_numeric_index(i, &tch, tmpfd); |
2005 | continue; | 2053 | continue; |
2006 | } | 2054 | } |
2007 | 2055 | ||
2008 | ret = build_index(i, &header, tmpfd); | 2056 | ret = build_index(i, &tch, tmpfd); |
2009 | if (ret <= 0) | 2057 | if (ret <= 0) |
2010 | { | 2058 | { |
2011 | close(tmpfd); | 2059 | close(tmpfd); |
@@ -2023,33 +2071,21 @@ static bool commit(void) | |||
2023 | stat.commit_step = 0; | 2071 | stat.commit_step = 0; |
2024 | 2072 | ||
2025 | /* Update the master index headers. */ | 2073 | /* Update the master index headers. */ |
2026 | masterfd = open(TAGCACHE_FILE_MASTER, O_RDWR); | 2074 | if ( (masterfd = open_master_fd(&tcmh, true)) < 0) |
2027 | if (masterfd < 0) | ||
2028 | { | ||
2029 | logf("failed to open master index"); | ||
2030 | return false; | 2075 | return false; |
2031 | } | ||
2032 | 2076 | ||
2033 | if (read(masterfd, &header_old, sizeof(struct tagcache_header)) | 2077 | tcmh.tch.entry_count += tch.entry_count; |
2034 | != sizeof(struct tagcache_header) || | 2078 | tcmh.tch.datasize = sizeof(struct master_header) |
2035 | header_old.magic != TAGCACHE_MAGIC) | 2079 | + sizeof(struct index_entry) * tcmh.tch.entry_count |
2036 | { | 2080 | + tch.datasize; |
2037 | logf("incorrect header"); | ||
2038 | close(masterfd); | ||
2039 | remove_files(); | ||
2040 | return false; | ||
2041 | } | ||
2042 | |||
2043 | header.entry_count += header_old.entry_count; | ||
2044 | /* Datasize has been recalculated. */ | ||
2045 | // header.datasize += header_old.datasize; | ||
2046 | 2081 | ||
2047 | lseek(masterfd, 0, SEEK_SET); | 2082 | lseek(masterfd, 0, SEEK_SET); |
2048 | write(masterfd, &header, sizeof(struct tagcache_header)); | 2083 | write(masterfd, &tcmh, sizeof(struct master_header)); |
2049 | close(masterfd); | 2084 | close(masterfd); |
2050 | 2085 | ||
2051 | logf("tagcache committed"); | 2086 | logf("tagcache committed"); |
2052 | remove(TAGCACHE_FILE_TEMP); | 2087 | remove(TAGCACHE_FILE_TEMP); |
2088 | stat.ready = true; | ||
2053 | 2089 | ||
2054 | if (local_allocation) | 2090 | if (local_allocation) |
2055 | { | 2091 | { |
@@ -2090,27 +2126,95 @@ static void free_tempbuf(void) | |||
2090 | tempbuf_size = 0; | 2126 | tempbuf_size = 0; |
2091 | } | 2127 | } |
2092 | 2128 | ||
2093 | static int open_master_fd(struct tagcache_header *hdr) | 2129 | static bool update_current_serial(long serial) |
2094 | { | 2130 | { |
2131 | struct master_header myhdr; | ||
2095 | int fd; | 2132 | int fd; |
2096 | 2133 | ||
2097 | fd = open(TAGCACHE_FILE_MASTER, O_RDWR); | 2134 | if ( (fd = open_master_fd(&myhdr, true)) < 0) |
2098 | if (fd < 0) | 2135 | return false; |
2136 | |||
2137 | myhdr.serial = serial; | ||
2138 | current_serial = serial; | ||
2139 | |||
2140 | #ifdef HAVE_TC_RAMCACHE | ||
2141 | if (hdr) | ||
2142 | hdr->h.serial = serial; | ||
2143 | #endif | ||
2144 | |||
2145 | /* Write it back */ | ||
2146 | lseek(fd, 0, SEEK_SET); | ||
2147 | write(fd, &myhdr, sizeof(struct master_header)); | ||
2148 | close(fd); | ||
2149 | |||
2150 | return true; | ||
2151 | } | ||
2152 | |||
2153 | long tagcache_increase_serial(void) | ||
2154 | { | ||
2155 | if (!update_current_serial(current_serial + 1)) | ||
2156 | return -1; | ||
2157 | |||
2158 | return current_serial; | ||
2159 | } | ||
2160 | |||
2161 | long tagcache_get_serial(void) | ||
2162 | { | ||
2163 | return current_serial; | ||
2164 | } | ||
2165 | |||
2166 | static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) | ||
2167 | { | ||
2168 | struct index_entry idx; | ||
2169 | |||
2170 | if (!tagcache_is_numeric_tag(tag)) | ||
2171 | return false; | ||
2172 | |||
2173 | #ifdef HAVE_TC_RAMCACHE | ||
2174 | /* Update ram entries first. */ | ||
2175 | if (hdr) | ||
2099 | { | 2176 | { |
2100 | logf("master file open failed for R/W"); | 2177 | hdr->indices[idx_id].tag_seek[tag] = data; |
2101 | return fd; | 2178 | hdr->indices[idx_id].flag |= FLAG_DIRTYNUM; |
2102 | } | 2179 | } |
2180 | #endif | ||
2103 | 2181 | ||
2104 | /* Check the header. */ | 2182 | /* And now update the db on disk also. */ |
2105 | read(fd, hdr, sizeof(struct tagcache_header)); | 2183 | lseek(masterfd, idx_id * sizeof(struct index_entry) |
2106 | if (hdr->magic != TAGCACHE_MAGIC) | 2184 | + sizeof(struct master_header), SEEK_SET); |
2185 | if (read(masterfd, &idx, sizeof(struct index_entry)) | ||
2186 | != sizeof(struct index_entry)) | ||
2107 | { | 2187 | { |
2108 | logf("header error"); | 2188 | logf("read error"); |
2109 | close(fd); | 2189 | return false; |
2110 | return -2; | ||
2111 | } | 2190 | } |
2112 | 2191 | ||
2113 | return fd; | 2192 | idx.flag |= FLAG_DIRTYNUM; |
2193 | idx.tag_seek[tag] = data; | ||
2194 | |||
2195 | lseek(masterfd, -sizeof(struct index_entry), SEEK_CUR); | ||
2196 | if (write(masterfd, &idx, sizeof(struct index_entry)) | ||
2197 | != sizeof(struct index_entry)) | ||
2198 | { | ||
2199 | logf("write error"); | ||
2200 | return false; | ||
2201 | } | ||
2202 | |||
2203 | return true; | ||
2204 | } | ||
2205 | |||
2206 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | ||
2207 | int tag, long data) | ||
2208 | { | ||
2209 | struct master_header myhdr; | ||
2210 | |||
2211 | if (tcs->masterfd < 0) | ||
2212 | { | ||
2213 | if ( (tcs->masterfd = open_master_fd(&myhdr, true)) < 0) | ||
2214 | return false; | ||
2215 | } | ||
2216 | |||
2217 | return modify_numeric_entry(tcs->masterfd, tcs->idx_id, tag, data); | ||
2114 | } | 2218 | } |
2115 | 2219 | ||
2116 | static bool write_tag(int fd, const char *tagstr, const char *datastr) | 2220 | static bool write_tag(int fd, const char *tagstr, const char *datastr) |
@@ -2141,13 +2245,192 @@ static bool write_tag(int fd, const char *tagstr, const char *datastr) | |||
2141 | return true; | 2245 | return true; |
2142 | } | 2246 | } |
2143 | 2247 | ||
2248 | static bool read_tag(char *dest, long size, | ||
2249 | const char *src, const char *tagstr) | ||
2250 | { | ||
2251 | int pos; | ||
2252 | char current_tag[32]; | ||
2253 | |||
2254 | while (*src != '\0') | ||
2255 | { | ||
2256 | /* Skip all whitespace */ | ||
2257 | while (*src == ' ') | ||
2258 | src++; | ||
2259 | |||
2260 | if (*src == '\0') | ||
2261 | break; | ||
2262 | |||
2263 | pos = 0; | ||
2264 | /* Read in tag name */ | ||
2265 | while (*src != '=' && *src != ' ') | ||
2266 | { | ||
2267 | current_tag[pos] = *src; | ||
2268 | src++; | ||
2269 | pos++; | ||
2270 | |||
2271 | if (*src == '\0' || pos >= (long)sizeof(current_tag)) | ||
2272 | return false; | ||
2273 | } | ||
2274 | current_tag[pos] = '\0'; | ||
2275 | |||
2276 | /* Read in tag data */ | ||
2277 | |||
2278 | /* Find the start. */ | ||
2279 | while (*src != '"' && *src != '\0') | ||
2280 | src++; | ||
2281 | |||
2282 | if (*src == '\0' || *(++src) == '\0') | ||
2283 | return false; | ||
2284 | |||
2285 | /* Read the data. */ | ||
2286 | for (pos = 0; pos < size; pos++) | ||
2287 | { | ||
2288 | if (*src == '\0') | ||
2289 | break; | ||
2290 | |||
2291 | if (*src == '\\' && *(src+1) == '"') | ||
2292 | { | ||
2293 | dest[pos] = '"'; | ||
2294 | src += 2; | ||
2295 | continue; | ||
2296 | } | ||
2297 | |||
2298 | dest[pos] = *src; | ||
2299 | |||
2300 | if (*src == '"') | ||
2301 | { | ||
2302 | src++; | ||
2303 | break; | ||
2304 | } | ||
2305 | |||
2306 | if (*src == '\0') | ||
2307 | break; | ||
2308 | |||
2309 | src++; | ||
2310 | } | ||
2311 | dest[pos] = '\0'; | ||
2312 | |||
2313 | if (!strcasecmp(tagstr, current_tag)) | ||
2314 | return true; | ||
2315 | } | ||
2316 | |||
2317 | return false; | ||
2318 | } | ||
2319 | |||
2320 | static bool parse_changelog_line(int masterfd, const char *buf) | ||
2321 | { | ||
2322 | char tag_data[MAX_PATH]; | ||
2323 | int idx_id; | ||
2324 | const int import_tags[] = { tag_playcount, tag_playtime, tag_lastplayed }; | ||
2325 | int i; | ||
2326 | |||
2327 | if (*buf == '#') | ||
2328 | return true; | ||
2329 | |||
2330 | if (!read_tag(tag_data, sizeof tag_data, buf, "filename")) | ||
2331 | { | ||
2332 | logf("filename missing"); | ||
2333 | logf("-> %s", buf); | ||
2334 | return false; | ||
2335 | } | ||
2336 | |||
2337 | idx_id = find_index(tag_data); | ||
2338 | if (idx_id < 0) | ||
2339 | { | ||
2340 | logf("entry not found"); | ||
2341 | return false; | ||
2342 | } | ||
2343 | |||
2344 | for (i = 0; i < (long)(sizeof(import_tags)/sizeof(import_tags[0])); i++) | ||
2345 | { | ||
2346 | int data; | ||
2347 | |||
2348 | if (!read_tag(tag_data, sizeof tag_data, buf, | ||
2349 | tagcache_tag_to_str(import_tags[i]))) | ||
2350 | { | ||
2351 | continue; | ||
2352 | } | ||
2353 | |||
2354 | data = atoi(tag_data); | ||
2355 | if (data < 0) | ||
2356 | continue; | ||
2357 | |||
2358 | modify_numeric_entry(masterfd, idx_id, import_tags[i], data); | ||
2359 | |||
2360 | if (import_tags[i] == tag_lastplayed && data > current_serial) | ||
2361 | current_serial = data; | ||
2362 | } | ||
2363 | |||
2364 | return true; | ||
2365 | } | ||
2366 | |||
2367 | bool tagcache_import_changelog(void) | ||
2368 | { | ||
2369 | struct master_header myhdr; | ||
2370 | int clfd, masterfd; | ||
2371 | char buf[512]; | ||
2372 | int pos = 0; | ||
2373 | |||
2374 | clfd = open(TAGCACHE_FILE_CHANGELOG, O_RDONLY); | ||
2375 | if (clfd < 0) | ||
2376 | { | ||
2377 | logf("failure to open changelog"); | ||
2378 | return false; | ||
2379 | } | ||
2380 | |||
2381 | if ( (masterfd = open_master_fd(&myhdr, true)) < 0) | ||
2382 | { | ||
2383 | close(clfd); | ||
2384 | return false; | ||
2385 | } | ||
2386 | |||
2387 | /* Fast readline */ | ||
2388 | while ( 1 ) | ||
2389 | { | ||
2390 | char *p; | ||
2391 | char *next = NULL; | ||
2392 | int rc; | ||
2393 | |||
2394 | rc = read(clfd, &buf[pos], sizeof(buf)-pos-1); | ||
2395 | if (rc >= 0) | ||
2396 | buf[pos+rc] = '\0'; | ||
2397 | |||
2398 | if ( (p = strchr(buf, '\r')) != NULL) | ||
2399 | { | ||
2400 | *p = '\0'; | ||
2401 | next = ++p; | ||
2402 | } | ||
2403 | else | ||
2404 | p = buf; | ||
2405 | |||
2406 | if ( (p = strchr(p, '\n')) != NULL) | ||
2407 | { | ||
2408 | *p = '\0'; | ||
2409 | next = ++p; | ||
2410 | } | ||
2411 | |||
2412 | parse_changelog_line(masterfd, buf); | ||
2413 | |||
2414 | if (next) | ||
2415 | { | ||
2416 | pos = sizeof(buf) - ((long)next - (long)buf) - 1; | ||
2417 | memmove(buf, next, pos); | ||
2418 | } | ||
2419 | else | ||
2420 | break ; | ||
2421 | } | ||
2422 | |||
2423 | close(clfd); | ||
2424 | close(masterfd); | ||
2425 | |||
2426 | update_current_serial(current_serial); | ||
2427 | |||
2428 | return true; | ||
2429 | } | ||
2430 | |||
2144 | bool tagcache_create_changelog(struct tagcache_search *tcs) | 2431 | bool tagcache_create_changelog(struct tagcache_search *tcs) |
2145 | { | 2432 | { |
2146 | static const char *tags_str[] = { "artist", "album", "genre", "title", | 2433 | struct master_header myhdr; |
2147 | "filename", "playcount", "playtime", "lastplayed" }; | ||
2148 | static const int tags[] = { tag_artist, tag_album, tag_genre, tag_title, | ||
2149 | tag_filename, tag_playcount, tag_playtime, tag_lastplayed }; | ||
2150 | struct tagcache_header myhdr; | ||
2151 | struct index_entry idx; | 2434 | struct index_entry idx; |
2152 | char buf[256]; | 2435 | char buf[256]; |
2153 | char temp[32]; | 2436 | char temp[32]; |
@@ -2167,18 +2450,18 @@ bool tagcache_create_changelog(struct tagcache_search *tcs) | |||
2167 | 2450 | ||
2168 | if (tcs->masterfd < 0) | 2451 | if (tcs->masterfd < 0) |
2169 | { | 2452 | { |
2170 | if ( (tcs->masterfd = open_master_fd(&myhdr)) < 0) | 2453 | if ( (tcs->masterfd = open_master_fd(&myhdr, false)) < 0) |
2171 | return false; | 2454 | return false; |
2172 | } | 2455 | } |
2173 | else | 2456 | else |
2174 | { | 2457 | { |
2175 | lseek(tcs->masterfd, 0, SEEK_SET); | 2458 | lseek(tcs->masterfd, 0, SEEK_SET); |
2176 | read(tcs->masterfd, &myhdr, sizeof(struct tagcache_header)); | 2459 | read(tcs->masterfd, &myhdr, sizeof(struct master_header)); |
2177 | } | 2460 | } |
2178 | 2461 | ||
2179 | write(clfd, "## Changelog version 1\n", 23); | 2462 | write(clfd, "## Changelog version 1\n", 23); |
2180 | 2463 | ||
2181 | for (i = 0; i < myhdr.entry_count; i++) | 2464 | for (i = 0; i < myhdr.tch.entry_count; i++) |
2182 | { | 2465 | { |
2183 | if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) | 2466 | if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) |
2184 | != sizeof(struct index_entry)) | 2467 | != sizeof(struct index_entry)) |
@@ -2196,19 +2479,19 @@ bool tagcache_create_changelog(struct tagcache_search *tcs) | |||
2196 | logf("Found!"); | 2479 | logf("Found!"); |
2197 | 2480 | ||
2198 | /* Now retrieve all tags. */ | 2481 | /* Now retrieve all tags. */ |
2199 | for (j = 0; j < (long)(sizeof(tags) / sizeof(tags[0])); j++) | 2482 | for (j = 0; j < TAG_COUNT; j++) |
2200 | { | 2483 | { |
2201 | if (tagcache_is_numeric_tag(tags[j])) | 2484 | if (tagcache_is_numeric_tag(j)) |
2202 | { | 2485 | { |
2203 | snprintf(temp, sizeof temp, "%d", idx.tag_seek[tags[j]]); | 2486 | snprintf(temp, sizeof temp, "%d", idx.tag_seek[j]); |
2204 | write_tag(clfd, tags_str[j], temp); | 2487 | write_tag(clfd, tagcache_tag_to_str(j), temp); |
2205 | continue; | 2488 | continue; |
2206 | } | 2489 | } |
2207 | 2490 | ||
2208 | tcs->type = tags[j]; | 2491 | tcs->type = j; |
2209 | tagcache_retrieve(tcs, i, buf, sizeof buf); | 2492 | tagcache_retrieve(tcs, i, buf, sizeof buf); |
2210 | logf("tag: %s", buf); | 2493 | logf("tag: %s", buf); |
2211 | write_tag(clfd, tags_str[j], buf); | 2494 | write_tag(clfd, tagcache_tag_to_str(j), buf); |
2212 | } | 2495 | } |
2213 | 2496 | ||
2214 | write(clfd, "\n", 1); | 2497 | write(clfd, "\n", 1); |
@@ -2221,60 +2504,12 @@ bool tagcache_create_changelog(struct tagcache_search *tcs) | |||
2221 | return true; | 2504 | return true; |
2222 | } | 2505 | } |
2223 | 2506 | ||
2224 | bool tagcache_modify_numeric_entry(struct tagcache_search *tcs, | ||
2225 | int tag, long data) | ||
2226 | { | ||
2227 | struct index_entry idx; | ||
2228 | struct tagcache_header myhdr; | ||
2229 | |||
2230 | if (!tagcache_is_numeric_tag(tag)) | ||
2231 | return false; | ||
2232 | |||
2233 | #ifdef HAVE_TC_RAMCACHE | ||
2234 | /* Update ram entries first. */ | ||
2235 | if (tcs->ramsearch) | ||
2236 | { | ||
2237 | hdr->indices[tcs->idx_id].tag_seek[tag] = data; | ||
2238 | hdr->indices[tcs->idx_id].flag |= FLAG_DIRTYNUM; | ||
2239 | } | ||
2240 | #endif | ||
2241 | |||
2242 | /* And now update the db on disk also. */ | ||
2243 | if (tcs->masterfd < 0) | ||
2244 | { | ||
2245 | if ( (tcs->masterfd = open_master_fd(&myhdr)) < 0) | ||
2246 | return false; | ||
2247 | } | ||
2248 | |||
2249 | lseek(tcs->masterfd, tcs->idx_id * sizeof(struct index_entry) | ||
2250 | + sizeof(struct tagcache_header), SEEK_SET); | ||
2251 | if (read(tcs->masterfd, &idx, sizeof(struct index_entry)) | ||
2252 | != sizeof(struct index_entry)) | ||
2253 | { | ||
2254 | logf("read error"); | ||
2255 | return false; | ||
2256 | } | ||
2257 | |||
2258 | idx.flag |= FLAG_DIRTYNUM; | ||
2259 | idx.tag_seek[tag] = data; | ||
2260 | |||
2261 | lseek(tcs->masterfd, -sizeof(struct index_entry), SEEK_CUR); | ||
2262 | if (write(tcs->masterfd, &idx, sizeof(struct index_entry)) | ||
2263 | != sizeof(struct index_entry)) | ||
2264 | { | ||
2265 | logf("write error"); | ||
2266 | return false; | ||
2267 | } | ||
2268 | |||
2269 | return true; | ||
2270 | } | ||
2271 | |||
2272 | static bool delete_entry(long idx_id) | 2507 | static bool delete_entry(long idx_id) |
2273 | { | 2508 | { |
2274 | int fd; | 2509 | int fd; |
2275 | int tag, i; | 2510 | int tag, i; |
2276 | struct index_entry idx, myidx; | 2511 | struct index_entry idx, myidx; |
2277 | struct tagcache_header myhdr; | 2512 | struct master_header myhdr; |
2278 | char buf[MAX_PATH]; | 2513 | char buf[MAX_PATH]; |
2279 | int in_use[TAG_COUNT]; | 2514 | int in_use[TAG_COUNT]; |
2280 | 2515 | ||
@@ -2284,7 +2519,7 @@ static bool delete_entry(long idx_id) | |||
2284 | hdr->indices[idx_id].flag |= FLAG_DELETED; | 2519 | hdr->indices[idx_id].flag |= FLAG_DELETED; |
2285 | #endif | 2520 | #endif |
2286 | 2521 | ||
2287 | if ( (fd = open_master_fd(&myhdr) < 0) ) | 2522 | if ( (fd = open_master_fd(&myhdr, true) < 0) ) |
2288 | return false; | 2523 | return false; |
2289 | 2524 | ||
2290 | lseek(fd, idx_id * sizeof(struct index_entry), SEEK_CUR); | 2525 | lseek(fd, idx_id * sizeof(struct index_entry), SEEK_CUR); |
@@ -2310,8 +2545,8 @@ static bool delete_entry(long idx_id) | |||
2310 | for (tag = 0; tag < TAG_COUNT; tag++) | 2545 | for (tag = 0; tag < TAG_COUNT; tag++) |
2311 | in_use[tag] = 0; | 2546 | in_use[tag] = 0; |
2312 | 2547 | ||
2313 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | 2548 | lseek(fd, sizeof(struct master_header), SEEK_SET); |
2314 | for (i = 0; i < myhdr.entry_count; i++) | 2549 | for (i = 0; i < myhdr.tch.entry_count; i++) |
2315 | { | 2550 | { |
2316 | if (read(fd, &idx, sizeof(struct index_entry)) | 2551 | if (read(fd, &idx, sizeof(struct index_entry)) |
2317 | != sizeof(struct index_entry)) | 2552 | != sizeof(struct index_entry)) |
@@ -2394,11 +2629,11 @@ static bool allocate_tagcache(void) | |||
2394 | /* Load the header. */ | 2629 | /* Load the header. */ |
2395 | hdr = (struct ramcache_header *)(((long)audiobuf & ~0x03) + 0x04); | 2630 | hdr = (struct ramcache_header *)(((long)audiobuf & ~0x03) + 0x04); |
2396 | memset(hdr, 0, sizeof(struct ramcache_header)); | 2631 | memset(hdr, 0, sizeof(struct ramcache_header)); |
2397 | len = sizeof(struct tagcache_header); | 2632 | len = sizeof(struct master_header); |
2398 | rc = read(fd, &hdr->h, len); | 2633 | rc = read(fd, &hdr->h, len); |
2399 | close(fd); | 2634 | close(fd); |
2400 | 2635 | ||
2401 | if (hdr->h.magic != TAGCACHE_MAGIC || rc != len) | 2636 | if (hdr->h.tch.magic != TAGCACHE_MAGIC || rc != len) |
2402 | { | 2637 | { |
2403 | logf("incorrect header"); | 2638 | logf("incorrect header"); |
2404 | remove_files(); | 2639 | remove_files(); |
@@ -2412,8 +2647,7 @@ static bool allocate_tagcache(void) | |||
2412 | * Now calculate the required cache size plus | 2647 | * Now calculate the required cache size plus |
2413 | * some extra space for alignment fixes. | 2648 | * some extra space for alignment fixes. |
2414 | */ | 2649 | */ |
2415 | stat.ramcache_allocated = hdr->h.datasize + 128 + TAGCACHE_RESERVE + | 2650 | stat.ramcache_allocated = hdr->h.tch.datasize + 128 + TAGCACHE_RESERVE + |
2416 | sizeof(struct index_entry) * hdr->h.entry_count + | ||
2417 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); | 2651 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); |
2418 | logf("tagcache: %d bytes allocated.", stat.ramcache_allocated); | 2652 | logf("tagcache: %d bytes allocated.", stat.ramcache_allocated); |
2419 | logf("at: 0x%04x", audiobuf); | 2653 | logf("at: 0x%04x", audiobuf); |
@@ -2445,20 +2679,18 @@ static bool load_tagcache(void) | |||
2445 | return false; | 2679 | return false; |
2446 | } | 2680 | } |
2447 | 2681 | ||
2448 | if (read(fd, &hdr->h, sizeof(struct tagcache_header)) | 2682 | if (read(fd, &hdr->h, sizeof(struct master_header)) |
2449 | != sizeof(struct tagcache_header) | 2683 | != sizeof(struct master_header) |
2450 | || hdr->h.magic != TAGCACHE_MAGIC) | 2684 | || hdr->h.tch.magic != TAGCACHE_MAGIC) |
2451 | { | 2685 | { |
2452 | logf("incorrect header"); | 2686 | logf("incorrect header"); |
2453 | return false; | 2687 | return false; |
2454 | } | 2688 | } |
2455 | 2689 | ||
2456 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | ||
2457 | |||
2458 | idx = hdr->indices; | 2690 | idx = hdr->indices; |
2459 | 2691 | ||
2460 | /* Load the master index table. */ | 2692 | /* Load the master index table. */ |
2461 | for (i = 0; i < hdr->h.entry_count; i++) | 2693 | for (i = 0; i < hdr->h.tch.entry_count; i++) |
2462 | { | 2694 | { |
2463 | rc = read(fd, idx, sizeof(struct index_entry)); | 2695 | rc = read(fd, idx, sizeof(struct index_entry)); |
2464 | if (rc != sizeof(struct index_entry)) | 2696 | if (rc != sizeof(struct index_entry)) |
@@ -2865,6 +3097,20 @@ static void load_ramcache(void) | |||
2865 | } | 3097 | } |
2866 | #endif | 3098 | #endif |
2867 | 3099 | ||
3100 | static bool check_master_fd(void) | ||
3101 | { | ||
3102 | struct master_header myhdr; | ||
3103 | int fd; | ||
3104 | |||
3105 | if ( (fd = open_master_fd(&myhdr, false)) < 0) | ||
3106 | return false; | ||
3107 | |||
3108 | close(fd); | ||
3109 | current_serial = myhdr.serial; | ||
3110 | |||
3111 | return true; | ||
3112 | } | ||
3113 | |||
2868 | static void tagcache_thread(void) | 3114 | static void tagcache_thread(void) |
2869 | { | 3115 | { |
2870 | struct event ev; | 3116 | struct event ev; |
@@ -2885,6 +3131,8 @@ static void tagcache_thread(void) | |||
2885 | 3131 | ||
2886 | cpu_boost(false); | 3132 | cpu_boost(false); |
2887 | 3133 | ||
3134 | stat.ready = check_master_fd(); | ||
3135 | |||
2888 | stat.initialized = true; | 3136 | stat.initialized = true; |
2889 | 3137 | ||
2890 | while (1) | 3138 | while (1) |
@@ -2964,7 +3212,7 @@ static int get_progress(void) | |||
2964 | #ifdef HAVE_TC_RAMCACHE | 3212 | #ifdef HAVE_TC_RAMCACHE |
2965 | { | 3213 | { |
2966 | if (hdr && stat.ramcache) | 3214 | if (hdr && stat.ramcache) |
2967 | total_count = hdr->h.entry_count; | 3215 | total_count = hdr->h.tch.entry_count; |
2968 | } | 3216 | } |
2969 | #endif | 3217 | #endif |
2970 | 3218 | ||
@@ -2989,6 +3237,9 @@ void tagcache_start_scan(void) | |||
2989 | 3237 | ||
2990 | bool tagcache_update(void) | 3238 | bool tagcache_update(void) |
2991 | { | 3239 | { |
3240 | if (!stat.ready) | ||
3241 | return false; | ||
3242 | |||
2992 | queue_post(&tagcache_queue, Q_UPDATE, 0); | 3243 | queue_post(&tagcache_queue, Q_UPDATE, 0); |
2993 | gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); | 3244 | gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH)); |
2994 | 3245 | ||
@@ -3019,8 +3270,10 @@ bool tagcache_is_ramcache(void) | |||
3019 | void tagcache_init(void) | 3270 | void tagcache_init(void) |
3020 | { | 3271 | { |
3021 | stat.initialized = false; | 3272 | stat.initialized = false; |
3273 | stat.ready = false; | ||
3022 | stat.commit_step = 0; | 3274 | stat.commit_step = 0; |
3023 | filenametag_fd = -1; | 3275 | filenametag_fd = -1; |
3276 | current_serial = 0; | ||
3024 | 3277 | ||
3025 | queue_init(&tagcache_queue); | 3278 | queue_init(&tagcache_queue); |
3026 | create_thread(tagcache_thread, tagcache_stack, | 3279 | create_thread(tagcache_thread, tagcache_stack, |