summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/tagcache.c214
-rw-r--r--apps/tagcache.h33
-rw-r--r--apps/tagtree.c68
3 files changed, 192 insertions, 123 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c
index d4ec1078d8..d7a377e7e2 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -410,7 +410,7 @@ static long find_entry_ram(const char *filename,
410} 410}
411#endif 411#endif
412 412
413static long find_entry_disk(const char *filename) 413static long find_entry_disk(const char *filename, bool localfd)
414{ 414{
415 struct tagcache_header tch; 415 struct tagcache_header tch;
416 static long last_pos = -1; 416 static long last_pos = -1;
@@ -427,7 +427,7 @@ static long find_entry_disk(const char *filename)
427 return -2; 427 return -2;
428 428
429 fd = filenametag_fd; 429 fd = filenametag_fd;
430 if (fd < 0) 430 if (fd < 0 || localfd)
431 { 431 {
432 last_pos = -1; 432 last_pos = -1;
433 if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0) 433 if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0)
@@ -458,6 +458,8 @@ static long find_entry_disk(const char *filename)
458 { 458 {
459 logf("too long tag #1"); 459 logf("too long tag #1");
460 close(fd); 460 close(fd);
461 if (!localfd)
462 filenametag_fd = -1;
461 last_pos = -1; 463 last_pos = -1;
462 return -2; 464 return -2;
463 } 465 }
@@ -466,6 +468,8 @@ static long find_entry_disk(const char *filename)
466 { 468 {
467 logf("read error #2"); 469 logf("read error #2");
468 close(fd); 470 close(fd);
471 if (!localfd)
472 filenametag_fd = -1;
469 last_pos = -1; 473 last_pos = -1;
470 return -3; 474 return -3;
471 } 475 }
@@ -491,12 +495,12 @@ static long find_entry_disk(const char *filename)
491 goto check_again; 495 goto check_again;
492 } 496 }
493 497
494 if (fd != filenametag_fd) 498 if (fd != filenametag_fd || localfd)
495 close(fd); 499 close(fd);
496 return -4; 500 return -4;
497 } 501 }
498 502
499 if (fd != filenametag_fd) 503 if (fd != filenametag_fd || localfd)
500 close(fd); 504 close(fd);
501 505
502 return tfe.idx_id; 506 return tfe.idx_id;
@@ -512,7 +516,7 @@ static int find_index(const char *filename)
512#endif 516#endif
513 517
514 if (idx_id < 0) 518 if (idx_id < 0)
515 idx_id = find_entry_disk(filename); 519 idx_id = find_entry_disk(filename, true);
516 520
517 return idx_id; 521 return idx_id;
518} 522}
@@ -554,8 +558,14 @@ static bool get_index(int masterfd, int idxid,
554 if (hdr->indices[idxid].flag & FLAG_DELETED) 558 if (hdr->indices[idxid].flag & FLAG_DELETED)
555 return false; 559 return false;
556 560
557 memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry)); 561# ifdef HAVE_DIRCACHE
558 return true; 562 if (!(hdr->indices[idxid].flag & FLAG_DIRCACHE)
563 || is_dircache_intact())
564#endif
565 {
566 memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry));
567 return true;
568 }
559 } 569 }
560#else 570#else
561 (void)use_ram; 571 (void)use_ram;
@@ -1006,17 +1016,20 @@ static bool add_uniqbuf(struct tagcache_search *tcs, unsigned long id)
1006static bool build_lookup_list(struct tagcache_search *tcs) 1016static bool build_lookup_list(struct tagcache_search *tcs)
1007{ 1017{
1008 struct index_entry entry; 1018 struct index_entry entry;
1009 int i; 1019 int i, j;
1010 1020
1011 tcs->seek_list_count = 0; 1021 tcs->seek_list_count = 0;
1012 1022
1013#ifdef HAVE_TC_RAMCACHE 1023#ifdef HAVE_TC_RAMCACHE
1014 if (tcs->ramsearch) 1024 if (tcs->ramsearch
1025# ifdef HAVE_DIRCACHE
1026 && (tcs->type != tag_filename || is_dircache_intact())
1027# endif
1028 )
1015 { 1029 {
1016 int j;
1017
1018 for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) 1030 for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++)
1019 { 1031 {
1032 struct tagcache_seeklist_entry *seeklist;
1020 struct index_entry *idx = &hdr->indices[i]; 1033 struct index_entry *idx = &hdr->indices[i];
1021 if (tcs->seek_list_count == SEEK_LIST_SIZE) 1034 if (tcs->seek_list_count == SEEK_LIST_SIZE)
1022 break ; 1035 break ;
@@ -1046,26 +1059,37 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1046 continue; 1059 continue;
1047 1060
1048 /* Lets add it. */ 1061 /* Lets add it. */
1049 tcs->seek_list[tcs->seek_list_count] = idx->tag_seek[tcs->type]; 1062 seeklist = &tcs->seeklist[tcs->seek_list_count];
1050 tcs->seek_flags[tcs->seek_list_count] = idx->flag; 1063 seeklist->seek = idx->tag_seek[tcs->type];
1064 seeklist->flag = idx->flag;
1065 seeklist->idx_id = i;
1051 tcs->seek_list_count++; 1066 tcs->seek_list_count++;
1052 } 1067 }
1053 1068
1054 tcs->seek_pos = i; 1069 tcs->seek_pos = i;
1055 1070
1056 return tcs->seek_list_count > 0; 1071 return tcs->seek_list_count > 0;
1057 } 1072 }
1058#endif 1073#endif
1059 1074
1075 if (tcs->masterfd < 0)
1076 {
1077 struct master_header tcmh;
1078 tcs->masterfd = open_master_fd(&tcmh, false);
1079 }
1080
1060 lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + 1081 lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) +
1061 sizeof(struct master_header), SEEK_SET); 1082 sizeof(struct master_header), SEEK_SET);
1062 1083
1063 while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ) 1084 while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ)
1064 == sizeof(struct index_entry)) 1085 == sizeof(struct index_entry))
1065 { 1086 {
1087 struct tagcache_seeklist_entry *seeklist;
1088
1066 if (tcs->seek_list_count == SEEK_LIST_SIZE) 1089 if (tcs->seek_list_count == SEEK_LIST_SIZE)
1067 break ; 1090 break ;
1068 1091
1092 i = tcs->seek_pos;
1069 tcs->seek_pos++; 1093 tcs->seek_pos++;
1070 1094
1071 /* Check if entry has been deleted. */ 1095 /* Check if entry has been deleted. */
@@ -1073,13 +1097,13 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1073 continue; 1097 continue;
1074 1098
1075 /* Go through all filters.. */ 1099 /* Go through all filters.. */
1076 for (i = 0; i < tcs->filter_count; i++) 1100 for (j = 0; j < tcs->filter_count; j++)
1077 { 1101 {
1078 if (entry.tag_seek[tcs->filter_tag[i]] != tcs->filter_seek[i]) 1102 if (entry.tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j])
1079 break ; 1103 break ;
1080 } 1104 }
1081 1105
1082 if (i < tcs->filter_count) 1106 if (j < tcs->filter_count)
1083 continue ; 1107 continue ;
1084 1108
1085 /* Check for conditions. */ 1109 /* Check for conditions. */
@@ -1091,8 +1115,10 @@ static bool build_lookup_list(struct tagcache_search *tcs)
1091 continue; 1115 continue;
1092 1116
1093 /* Lets add it. */ 1117 /* Lets add it. */
1094 tcs->seek_list[tcs->seek_list_count] = entry.tag_seek[tcs->type]; 1118 seeklist = &tcs->seeklist[tcs->seek_list_count];
1095 tcs->seek_flags[tcs->seek_list_count] = entry.flag; 1119 seeklist->seek = entry.tag_seek[tcs->type];
1120 seeklist->flag = entry.flag;
1121 seeklist->idx_id = i;
1096 tcs->seek_list_count++; 1122 tcs->seek_list_count++;
1097 1123
1098 yield(); 1124 yield();
@@ -1155,15 +1181,17 @@ static bool check_all_headers(void)
1155 return true; 1181 return true;
1156} 1182}
1157 1183
1184bool tagcache_is_busy(void)
1185{
1186 return read_lock || write_lock;
1187}
1188
1158bool tagcache_search(struct tagcache_search *tcs, int tag) 1189bool tagcache_search(struct tagcache_search *tcs, int tag)
1159{ 1190{
1160 struct tagcache_header tag_hdr; 1191 struct tagcache_header tag_hdr;
1161 struct master_header master_hdr; 1192 struct master_header master_hdr;
1162 int i; 1193 int i;
1163 1194
1164 if (tcs->initialized)
1165 tagcache_search_finish(tcs);
1166
1167 while (read_lock) 1195 while (read_lock)
1168 sleep(1); 1196 sleep(1);
1169 1197
@@ -1174,6 +1202,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
1174 tcs->position = sizeof(struct tagcache_header); 1202 tcs->position = sizeof(struct tagcache_header);
1175 tcs->type = tag; 1203 tcs->type = tag;
1176 tcs->seek_pos = 0; 1204 tcs->seek_pos = 0;
1205 tcs->list_position = 0;
1177 tcs->seek_list_count = 0; 1206 tcs->seek_list_count = 0;
1178 tcs->filter_count = 0; 1207 tcs->filter_count = 0;
1179 tcs->masterfd = -1; 1208 tcs->masterfd = -1;
@@ -1192,19 +1221,24 @@ bool tagcache_search(struct tagcache_search *tcs, int tag)
1192 else 1221 else
1193#endif 1222#endif
1194 { 1223 {
1224 /* Always open as R/W so we can pass tcs to functions that modify data also
1225 * without failing. */
1226 tcs->masterfd = open_master_fd(&master_hdr, true);
1227 if (tcs->masterfd < 0)
1228 return false;
1229
1195 if (!TAGCACHE_IS_NUMERIC(tcs->type)) 1230 if (!TAGCACHE_IS_NUMERIC(tcs->type))
1196 { 1231 {
1197 tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false); 1232 tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false);
1198 if (tcs->idxfd[tcs->type] < 0) 1233 if (tcs->idxfd[tcs->type] < 0)
1199 return false; 1234 return false;
1235
1236 tcs->entry_count = tag_hdr.entry_count;
1237 }
1238 else
1239 {
1240 tcs->entry_count = master_hdr.tch.entry_count;
1200 } 1241 }
1201
1202 /* Always open as R/W so we can pass tcs to functions that modify data also
1203 * without failing. */
1204 tcs->masterfd = open_master_fd(&master_hdr, true);
1205
1206 if (tcs->masterfd < 0)
1207 return false;
1208 } 1242 }
1209 1243
1210 tcs->valid = true; 1244 tcs->valid = true;
@@ -1272,14 +1306,6 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs,
1272 return true; 1306 return true;
1273} 1307}
1274 1308
1275/* TODO: Remove this mess. */
1276#ifdef HAVE_DIRCACHE
1277#define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \
1278 ? ((flag & FLAG_DIRCACHE) && is_dircache_intact()) : 1)
1279#else
1280#define TAG_FILENAME_RAM(tcs) (tcs->type != tag_filename)
1281#endif
1282
1283static bool get_next(struct tagcache_search *tcs) 1309static bool get_next(struct tagcache_search *tcs)
1284{ 1310{
1285 static char buf[TAG_MAXLEN+32]; 1311 static char buf[TAG_MAXLEN+32];
@@ -1298,11 +1324,20 @@ static bool get_next(struct tagcache_search *tcs)
1298 1324
1299 /* Relative fetch. */ 1325 /* Relative fetch. */
1300 if (tcs->filter_count > 0 || tcs->clause_count > 0 1326 if (tcs->filter_count > 0 || tcs->clause_count > 0
1301 || TAGCACHE_IS_NUMERIC(tcs->type)) 1327 || TAGCACHE_IS_NUMERIC(tcs->type)
1328#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1329 /* We need to retrieve flag status for dircache. */
1330 || (tcs->ramsearch && tcs->type == tag_filename)
1331#endif
1332 )
1302 { 1333 {
1334 struct tagcache_seeklist_entry *seeklist;
1335
1303 /* Check for end of list. */ 1336 /* Check for end of list. */
1304 if (tcs->seek_list_count == 0) 1337 if (tcs->list_position == tcs->seek_list_count)
1305 { 1338 {
1339 tcs->list_position = 0;
1340
1306 /* Try to fetch more. */ 1341 /* Try to fetch more. */
1307 if (!build_lookup_list(tcs)) 1342 if (!build_lookup_list(tcs))
1308 { 1343 {
@@ -1311,15 +1346,28 @@ static bool get_next(struct tagcache_search *tcs)
1311 } 1346 }
1312 } 1347 }
1313 1348
1314 tcs->seek_list_count--; 1349 seeklist = &tcs->seeklist[tcs->list_position];
1315 flag = tcs->seek_flags[tcs->seek_list_count]; 1350 flag = seeklist->flag;
1316 tcs->position = tcs->seek_list[tcs->seek_list_count]; 1351 tcs->position = seeklist->seek;
1352 tcs->idx_id = seeklist->idx_id;
1353 tcs->list_position++;
1317 } 1354 }
1355 else
1356 {
1357 if (tcs->entry_count == 0)
1358 {
1359 tcs->valid = false;
1360 return false;
1361 }
1362
1363 tcs->entry_count--;
1364 }
1365
1366 tcs->result_seek = tcs->position;
1318 1367
1319 if (TAGCACHE_IS_NUMERIC(tcs->type)) 1368 if (TAGCACHE_IS_NUMERIC(tcs->type))
1320 { 1369 {
1321 snprintf(buf, sizeof(buf), "%d", tcs->position); 1370 snprintf(buf, sizeof(buf), "%d", tcs->position);
1322 tcs->result_seek = tcs->position;
1323 tcs->result = buf; 1371 tcs->result = buf;
1324 tcs->result_len = strlen(buf) + 1; 1372 tcs->result_len = strlen(buf) + 1;
1325 return true; 1373 return true;
@@ -1327,55 +1375,54 @@ static bool get_next(struct tagcache_search *tcs)
1327 1375
1328 /* Direct fetch. */ 1376 /* Direct fetch. */
1329#ifdef HAVE_TC_RAMCACHE 1377#ifdef HAVE_TC_RAMCACHE
1330 if (tcs->ramsearch && TAG_FILENAME_RAM(tcs)) 1378 if (tcs->ramsearch)
1331 { 1379 {
1332 struct tagfile_entry *ep;
1333
1334 if (tcs->entry_count == 0)
1335 {
1336 tcs->valid = false;
1337 return false;
1338 }
1339 tcs->entry_count--;
1340 1380
1341 tcs->result_seek = tcs->position; 1381#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1342 1382 if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE)
1343# ifdef HAVE_DIRCACHE 1383 && is_dircache_intact())
1344 if (tcs->type == tag_filename)
1345 { 1384 {
1346 dircache_copy_path((struct dirent *)tcs->position, 1385 dircache_copy_path((struct dirent *)tcs->position,
1347 buf, sizeof buf); 1386 buf, sizeof buf);
1348 tcs->result = buf; 1387 tcs->result = buf;
1349 tcs->result_len = strlen(buf) + 1; 1388 tcs->result_len = strlen(buf) + 1;
1350 tcs->idx_id = FLAG_GET_ATTR(flag);
1351 tcs->ramresult = false; 1389 tcs->ramresult = false;
1352 1390
1353 return true; 1391 return true;
1354 } 1392 }
1355# endif 1393 else
1356 1394#endif
1357 ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; 1395 if (tcs->type != tag_filename)
1358 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; 1396 {
1359 tcs->result = ep->tag_data; 1397 struct tagfile_entry *ep;
1360 tcs->result_len = strlen(tcs->result) + 1; 1398
1361 tcs->idx_id = ep->idx_id; 1399 ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position];
1362 tcs->ramresult = true; 1400 tcs->result = ep->tag_data;
1363 1401 tcs->result_len = strlen(tcs->result) + 1;
1364 return true; 1402 tcs->idx_id = ep->idx_id;
1403 tcs->ramresult = true;
1404
1405 /* Increase position for the next run. This may get overwritten. */
1406 tcs->position += sizeof(struct tagfile_entry) + ep->tag_length;
1407
1408 return true;
1409 }
1365 } 1410 }
1366#endif 1411#endif
1367 1412
1368 if (!open_files(tcs, tcs->type)) 1413 if (!open_files(tcs, tcs->type))
1414 {
1415 tcs->valid = false;
1369 return false; 1416 return false;
1417 }
1370 1418
1371 /* Seek stream to the correct position and continue to direct fetch. */ 1419 /* Seek stream to the correct position and continue to direct fetch. */
1372 lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET); 1420 lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET);
1373 tcs->result_seek = tcs->position;
1374 1421
1375 if (ecread(tcs->idxfd[tcs->type], &entry, 1, 1422 if (ecread(tcs->idxfd[tcs->type], &entry, 1,
1376 tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry)) 1423 tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry))
1377 { 1424 {
1378 /* End of data. */ 1425 logf("read error #5");
1379 tcs->valid = false; 1426 tcs->valid = false;
1380 return false; 1427 return false;
1381 } 1428 }
@@ -1384,6 +1431,7 @@ static bool get_next(struct tagcache_search *tcs)
1384 { 1431 {
1385 tcs->valid = false; 1432 tcs->valid = false;
1386 logf("too long tag #2"); 1433 logf("too long tag #2");
1434 logf("P:%X/%X", tcs->position, entry.tag_length);
1387 return false; 1435 return false;
1388 } 1436 }
1389 1437
@@ -1536,12 +1584,12 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
1536 struct index_entry *entry; 1584 struct index_entry *entry;
1537 int idx_id; 1585 int idx_id;
1538 1586
1539 if (!tc_stat.ready) 1587 if (!tc_stat.ready || !tc_stat.ramcache)
1540 return false; 1588 return false;
1541 1589
1542 /* Find the corresponding entry in tagcache. */ 1590 /* Find the corresponding entry in tagcache. */
1543 idx_id = find_entry_ram(filename, NULL); 1591 idx_id = find_entry_ram(filename, NULL);
1544 if (idx_id < 0 || !tc_stat.ramcache) 1592 if (idx_id < 0)
1545 return false; 1593 return false;
1546 1594
1547 entry = &hdr->indices[idx_id]; 1595 entry = &hdr->indices[idx_id];
@@ -1644,14 +1692,11 @@ static void add_tagcache(char *path, unsigned long mtime
1644 { 1692 {
1645 idx_id = find_entry_ram(path, dc); 1693 idx_id = find_entry_ram(path, dc);
1646 } 1694 }
1647 else
1648#endif 1695#endif
1649 { 1696
1650 if (filenametag_fd >= 0) 1697 /* Be sure the entry doesn't exist. */
1651 { 1698 if (filenametag_fd >= 0 && idx_id < 0)
1652 idx_id = find_entry_disk(path); 1699 idx_id = find_entry_disk(path, false);
1653 }
1654 }
1655 1700
1656 /* Check if file has been modified. */ 1701 /* Check if file has been modified. */
1657 if (idx_id >= 0) 1702 if (idx_id >= 0)
@@ -2548,6 +2593,13 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
2548 2593
2549 /* Sort the buffer data and write it to the index file. */ 2594 /* Sort the buffer data and write it to the index file. */
2550 lseek(fd, sizeof(struct tagcache_header), SEEK_SET); 2595 lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
2596 /**
2597 * We need to truncate the index file now. There can be junk left
2598 * at the end of file (however, we _should_ always follow the
2599 * entry_count and don't crash with that).
2600 */
2601 ftruncate(fd, lseek(fd, 0, SEEK_CUR));
2602
2551 i = tempbuf_sort(fd); 2603 i = tempbuf_sort(fd);
2552 if (i < 0) 2604 if (i < 0)
2553 goto error_exit; 2605 goto error_exit;
@@ -3328,7 +3380,10 @@ bool tagcache_import_changelog(void)
3328 close(masterfd); 3380 close(masterfd);
3329 3381
3330 if (filenametag_fd >= 0) 3382 if (filenametag_fd >= 0)
3383 {
3331 close(filenametag_fd); 3384 close(filenametag_fd);
3385 filenametag_fd = -1;
3386 }
3332 3387
3333 write_lock--; 3388 write_lock--;
3334 3389
@@ -3919,7 +3974,6 @@ static bool load_tagcache(void)
3919 } 3974 }
3920 3975
3921 idx->flag |= FLAG_DIRCACHE; 3976 idx->flag |= FLAG_DIRCACHE;
3922 FLAG_SET_ATTR(idx->flag, fe->idx_id);
3923 idx->tag_seek[tag_filename] = (long)dc; 3977 idx->tag_seek[tag_filename] = (long)dc;
3924 } 3978 }
3925 else 3979 else
diff --git a/apps/tagcache.h b/apps/tagcache.h
index f2b975c566..0908e3571c 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -112,8 +112,6 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
112#define FLAG_DIRTYNUM 0x0004 /* Numeric data has been modified */ 112#define FLAG_DIRTYNUM 0x0004 /* Numeric data has been modified */
113#define FLAG_TRKNUMGEN 0x0008 /* Track number has been generated */ 113#define FLAG_TRKNUMGEN 0x0008 /* Track number has been generated */
114#define FLAG_RESURRECTED 0x0010 /* Statistics data has been resurrected */ 114#define FLAG_RESURRECTED 0x0010 /* Statistics data has been resurrected */
115#define FLAG_GET_ATTR(flag) ((flag >> 16) & 0x0000ffff)
116#define FLAG_SET_ATTR(flag,attr) flag = (flag & 0x0000ffff) | (attr << 16)
117 115
118enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, 116enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq,
119 clause_lt, clause_lteq, clause_contains, clause_not_contains, 117 clause_lt, clause_lteq, clause_contains, clause_not_contains,
@@ -156,20 +154,26 @@ struct tagcache_search_clause
156 char *str; 154 char *str;
157}; 155};
158 156
157struct tagcache_seeklist_entry {
158 int32_t seek;
159 int32_t flag;
160 int32_t idx_id;
161};
162
159struct tagcache_search { 163struct tagcache_search {
160 /* For internal use only. */ 164 /* For internal use only. */
161 int fd, masterfd; 165 int fd, masterfd;
162 int idxfd[TAG_COUNT]; 166 int idxfd[TAG_COUNT];
163 long seek_list[SEEK_LIST_SIZE]; 167 struct tagcache_seeklist_entry seeklist[SEEK_LIST_SIZE];
164 long seek_flags[SEEK_LIST_SIZE]; 168 int seek_list_count;
165 long filter_tag[TAGCACHE_MAX_FILTERS]; 169 int32_t filter_tag[TAGCACHE_MAX_FILTERS];
166 long filter_seek[TAGCACHE_MAX_FILTERS]; 170 int32_t filter_seek[TAGCACHE_MAX_FILTERS];
167 int filter_count; 171 int filter_count;
168 struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES]; 172 struct tagcache_search_clause *clause[TAGCACHE_MAX_CLAUSES];
169 int clause_count; 173 int clause_count;
170 int seek_list_count; 174 int list_position;
171 int seek_pos; 175 int seek_pos;
172 long position; 176 int32_t position;
173 int entry_count; 177 int entry_count;
174 bool valid; 178 bool valid;
175 bool initialized; 179 bool initialized;
@@ -178,13 +182,13 @@ struct tagcache_search {
178 int unique_list_count; 182 int unique_list_count;
179 183
180 /* Exported variables. */ 184 /* Exported variables. */
181 bool ramsearch; 185 bool ramsearch; /* Is ram copy of the tagcache being used. */
182 bool ramresult; 186 bool ramresult; /* False if result is not static, and must be copied. */
183 int type; 187 int type;
184 char *result; 188 char *result; /* The result data for all tags. */
185 int result_len; 189 int result_len; /* Length of the result including \0 */
186 long result_seek; 190 int32_t result_seek; /* Current position in the tag data. */
187 int idx_id; 191 int32_t idx_id; /* Entry number in the master index. */
188}; 192};
189 193
190void tagcache_build(const char *path); 194void tagcache_build(const char *path);
@@ -201,6 +205,7 @@ bool tagcache_is_numeric_tag(int type);
201bool tagcache_find_index(struct tagcache_search *tcs, const char *filename); 205bool tagcache_find_index(struct tagcache_search *tcs, const char *filename);
202bool tagcache_check_clauses(struct tagcache_search *tcs, 206bool tagcache_check_clauses(struct tagcache_search *tcs,
203 struct tagcache_search_clause **clause, int count); 207 struct tagcache_search_clause **clause, int count);
208bool tagcache_is_busy(void);
204bool tagcache_search(struct tagcache_search *tcs, int tag); 209bool tagcache_search(struct tagcache_search *tcs, int tag);
205void tagcache_search_set_uniqbuf(struct tagcache_search *tcs, 210void tagcache_search_set_uniqbuf(struct tagcache_search *tcs,
206 void *buffer, long length); 211 void *buffer, long length);
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 9635052ef3..691b2273de 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -23,6 +23,9 @@
23 * Basic structure on this file was copied from dbtree.c and modified to 23 * Basic structure on this file was copied from dbtree.c and modified to
24 * support the tag cache interface. 24 * support the tag cache interface.
25 */ 25 */
26
27/* #define LOGF_ENABLE */
28
26#include <stdio.h> 29#include <stdio.h>
27#include <string.h> 30#include <string.h>
28#include <stdlib.h> 31#include <stdlib.h>
@@ -96,7 +99,6 @@ static long *uniqbuf;
96#define MAX_TAGS 5 99#define MAX_TAGS 5
97#define MAX_MENU_ID_SIZE 32 100#define MAX_MENU_ID_SIZE 32
98 101
99static struct tagcache_search tcs, tcs2;
100static bool sort_inverse; 102static bool sort_inverse;
101 103
102/* 104/*
@@ -642,6 +644,8 @@ static int compare(const void *p1, const void *p2)
642 644
643static void tagtree_buffer_event(struct mp3entry *id3) 645static void tagtree_buffer_event(struct mp3entry *id3)
644{ 646{
647 struct tagcache_search tcs;
648
645 /* Do not gather data unless proper setting has been enabled. */ 649 /* Do not gather data unless proper setting has been enabled. */
646 if (!global_settings.runtimedb) 650 if (!global_settings.runtimedb)
647 return; 651 return;
@@ -719,6 +723,8 @@ static void tagtree_track_finish_event(struct mp3entry *id3)
719 723
720bool tagtree_export(void) 724bool tagtree_export(void)
721{ 725{
726 struct tagcache_search tcs;
727
722 splash(0, str(LANG_CREATING)); 728 splash(0, str(LANG_CREATING));
723 if (!tagcache_create_changelog(&tcs)) 729 if (!tagcache_create_changelog(&tcs))
724 { 730 {
@@ -1040,9 +1046,9 @@ static int format_str(struct tagcache_search *tcs, struct display_format *fmt,
1040 return 0; 1046 return 0;
1041} 1047}
1042 1048
1043static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, 1049static int retrieve_entries(struct tree_context *c, int offset, bool init)
1044 int offset, bool init)
1045{ 1050{
1051 struct tagcache_search tcs;
1046 struct tagentry *dptr = (struct tagentry *)c->dircache; 1052 struct tagentry *dptr = (struct tagentry *)c->dircache;
1047 struct display_format *fmt; 1053 struct display_format *fmt;
1048 int i; 1054 int i;
@@ -1055,15 +1061,16 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1055 int sort_limit; 1061 int sort_limit;
1056 int strip; 1062 int strip;
1057 1063
1058 if (init 1064 if (init && (tagcache_is_busy()
1059#ifdef HAVE_TC_RAMCACHE 1065#ifdef HAVE_TC_RAMCACHE
1060 && !tagcache_is_ramcache() 1066 || !tagcache_is_ramcache()
1061#endif 1067#endif
1062 ) 1068 ) )
1063 { 1069 {
1064 /* Show search progress straight away if the disk needs to spin up, 1070 /* Show search progress straight away if the disk needs to spin up,
1065 otherwise show it after the normal 1/2 second delay */ 1071 otherwise show it after the normal 1/2 second delay */
1066 show_search_progress( 1072 show_search_progress(
1073 !tagcache_is_busy() &&
1067#ifdef HAVE_DISK_STORAGE 1074#ifdef HAVE_DISK_STORAGE
1068 storage_disk_is_active() 1075 storage_disk_is_active()
1069#else 1076#else
@@ -1080,11 +1087,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1080 else 1087 else
1081 tag = csi->tagorder[level]; 1088 tag = csi->tagorder[level];
1082 1089
1083 if (!tagcache_search(tcs, tag)) 1090 if (!tagcache_search(&tcs, tag))
1084 return -1; 1091 return -1;
1085 1092
1086 /* Prevent duplicate entries in the search list. */ 1093 /* Prevent duplicate entries in the search list. */
1087 tagcache_search_set_uniqbuf(tcs, uniqbuf, UNIQBUF_SIZE); 1094 tagcache_search_set_uniqbuf(&tcs, uniqbuf, UNIQBUF_SIZE);
1088 1095
1089 if (level || csi->clause_count[0] || TAGCACHE_IS_NUMERIC(tag)) 1096 if (level || csi->clause_count[0] || TAGCACHE_IS_NUMERIC(tag))
1090 sort = true; 1097 sort = true;
@@ -1100,11 +1107,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1100 cc.type = clause_is; 1107 cc.type = clause_is;
1101 cc.numeric = true; 1108 cc.numeric = true;
1102 cc.numeric_data = csi->result_seek[i]; 1109 cc.numeric_data = csi->result_seek[i];
1103 tagcache_search_add_clause(tcs, &cc); 1110 tagcache_search_add_clause(&tcs, &cc);
1104 } 1111 }
1105 else 1112 else
1106 { 1113 {
1107 tagcache_search_add_filter(tcs, csi->tagorder[i], 1114 tagcache_search_add_filter(&tcs, csi->tagorder[i],
1108 csi->result_seek[i]); 1115 csi->result_seek[i]);
1109 } 1116 }
1110 } 1117 }
@@ -1114,7 +1121,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1114 int j; 1121 int j;
1115 1122
1116 for (j = 0; j < csi->clause_count[i]; j++) 1123 for (j = 0; j < csi->clause_count[i]; j++)
1117 tagcache_search_add_clause(tcs, csi->clause[i][j]); 1124 tagcache_search_add_clause(&tcs, csi->clause[i][j]);
1118 } 1125 }
1119 1126
1120 current_offset = offset; 1127 current_offset = offset;
@@ -1164,7 +1171,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1164 1171
1165 total_count += special_entry_count; 1172 total_count += special_entry_count;
1166 1173
1167 while (tagcache_get_next(tcs)) 1174 while (tagcache_get_next(&tcs))
1168 { 1175 {
1169 if (total_count++ < offset) 1176 if (total_count++ < offset)
1170 continue; 1177 continue;
@@ -1173,10 +1180,10 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1173 if (tag == tag_title || tag == tag_filename) 1180 if (tag == tag_title || tag == tag_filename)
1174 { 1181 {
1175 dptr->newtable = PLAYTRACK; 1182 dptr->newtable = PLAYTRACK;
1176 dptr->extraseek = tcs->idx_id; 1183 dptr->extraseek = tcs.idx_id;
1177 } 1184 }
1178 else 1185 else
1179 dptr->extraseek = tcs->result_seek; 1186 dptr->extraseek = tcs.result_seek;
1180 1187
1181 fmt = NULL; 1188 fmt = NULL;
1182 /* Check the format */ 1189 /* Check the format */
@@ -1185,7 +1192,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1185 if (formats[i]->group_id != csi->format_id[level]) 1192 if (formats[i]->group_id != csi->format_id[level])
1186 continue; 1193 continue;
1187 1194
1188 if (tagcache_check_clauses(tcs, formats[i]->clause, 1195 if (tagcache_check_clauses(&tcs, formats[i]->clause,
1189 formats[i]->clause_count)) 1196 formats[i]->clause_count))
1190 { 1197 {
1191 fmt = formats[i]; 1198 fmt = formats[i];
@@ -1193,15 +1200,16 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1193 } 1200 }
1194 } 1201 }
1195 1202
1196 if (!tcs->ramresult || fmt) 1203 if (!tcs.ramresult || fmt)
1197 { 1204 {
1198 char buf[MAX_PATH]; 1205 char buf[MAX_PATH];
1199 1206
1200 if (fmt) 1207 if (fmt)
1201 { 1208 {
1202 if (format_str(tcs, fmt, buf, sizeof buf) < 0) 1209 if (format_str(&tcs, fmt, buf, sizeof buf) < 0)
1203 { 1210 {
1204 logf("format_str() failed"); 1211 logf("format_str() failed");
1212 tagcache_search_finish(&tcs);
1205 return 0; 1213 return 0;
1206 } 1214 }
1207 } 1215 }
@@ -1210,7 +1218,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1210 if (fmt) 1218 if (fmt)
1211 namebufused += strlen(buf)+1; 1219 namebufused += strlen(buf)+1;
1212 else 1220 else
1213 namebufused += tcs->result_len; 1221 namebufused += tcs.result_len;
1214 1222
1215 if (namebufused >= c->name_buffer_size) 1223 if (namebufused >= c->name_buffer_size)
1216 { 1224 {
@@ -1222,10 +1230,10 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1222 if (fmt) 1230 if (fmt)
1223 strcpy(dptr->name, buf); 1231 strcpy(dptr->name, buf);
1224 else 1232 else
1225 strcpy(dptr->name, tcs->result); 1233 strcpy(dptr->name, tcs.result);
1226 } 1234 }
1227 else 1235 else
1228 dptr->name = tcs->result; 1236 dptr->name = tcs.result;
1229 1237
1230 dptr++; 1238 dptr++;
1231 current_entry_count++; 1239 current_entry_count++;
@@ -1238,11 +1246,11 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1238 break ; 1246 break ;
1239 } 1247 }
1240 1248
1241 if (init && !tcs->ramsearch) 1249 if (init && !tcs.ramsearch)
1242 { 1250 {
1243 if (!show_search_progress(false, total_count)) 1251 if (!show_search_progress(false, total_count))
1244 { 1252 {
1245 tagcache_search_finish(tcs); 1253 tagcache_search_finish(&tcs);
1246 return current_entry_count; 1254 return current_entry_count;
1247 } 1255 }
1248 } 1256 }
@@ -1255,13 +1263,13 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1255 1263
1256 if (!init) 1264 if (!init)
1257 { 1265 {
1258 tagcache_search_finish(tcs); 1266 tagcache_search_finish(&tcs);
1259 return current_entry_count; 1267 return current_entry_count;
1260 } 1268 }
1261 1269
1262 while (tagcache_get_next(tcs)) 1270 while (tagcache_get_next(&tcs))
1263 { 1271 {
1264 if (!tcs->ramsearch) 1272 if (!tcs.ramsearch)
1265 { 1273 {
1266 if (!show_search_progress(false, total_count)) 1274 if (!show_search_progress(false, total_count))
1267 break; 1275 break;
@@ -1269,7 +1277,7 @@ static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs,
1269 total_count++; 1277 total_count++;
1270 } 1278 }
1271 1279
1272 tagcache_search_finish(tcs); 1280 tagcache_search_finish(&tcs);
1273 1281
1274 if (!sort && (sort_inverse || sort_limit)) 1282 if (!sort && (sort_inverse || sort_limit))
1275 { 1283 {
@@ -1363,7 +1371,7 @@ int tagtree_load(struct tree_context* c)
1363 case NAVIBROWSE: 1371 case NAVIBROWSE:
1364 logf("navibrowse..."); 1372 logf("navibrowse...");
1365 cpu_boost(true); 1373 cpu_boost(true);
1366 count = retrieve_entries(c, &tcs, 0, true); 1374 count = retrieve_entries(c, 0, true);
1367 cpu_boost(false); 1375 cpu_boost(false);
1368 break; 1376 break;
1369 1377
@@ -1549,6 +1557,7 @@ void tagtree_exit(struct tree_context* c)
1549 1557
1550int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) 1558int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
1551{ 1559{
1560 struct tagcache_search tcs;
1552 struct tagentry *entry; 1561 struct tagentry *entry;
1553 1562
1554 entry = tagtree_get_entry(c, c->selected_item); 1563 entry = tagtree_get_entry(c, c->selected_item);
@@ -1569,6 +1578,7 @@ int tagtree_get_filename(struct tree_context* c, char *buf, int buflen)
1569 1578
1570static bool insert_all_playlist(struct tree_context *c, int position, bool queue) 1579static bool insert_all_playlist(struct tree_context *c, int position, bool queue)
1571{ 1580{
1581 struct tagcache_search tcs;
1572 int i; 1582 int i;
1573 char buf[MAX_PATH]; 1583 char buf[MAX_PATH];
1574 int from, to, direction; 1584 int from, to, direction;
@@ -1639,7 +1649,7 @@ bool tagtree_insert_selection_playlist(int position, bool queue)
1639 int dirlevel = tc->dirlevel; 1649 int dirlevel = tc->dirlevel;
1640 1650
1641 /* We need to set the table to allsubentries. */ 1651 /* We need to set the table to allsubentries. */
1642 show_search_progress(true, 0); 1652 show_search_progress(!tagcache_is_busy(), 0);
1643 1653
1644 dptr = tagtree_get_entry(tc, tc->selected_item); 1654 dptr = tagtree_get_entry(tc, tc->selected_item);
1645 1655
@@ -1732,7 +1742,7 @@ struct tagentry* tagtree_get_entry(struct tree_context *c, int id)
1732 if (realid >= current_entry_count || realid < 0) 1742 if (realid >= current_entry_count || realid < 0)
1733 { 1743 {
1734 cpu_boost(true); 1744 cpu_boost(true);
1735 if (retrieve_entries(c, &tcs2, MAX(0, id - (current_entry_count / 2)), 1745 if (retrieve_entries(c, MAX(0, id - (current_entry_count / 2)),
1736 false) < 0) 1746 false) < 0)
1737 { 1747 {
1738 logf("retrieve failed"); 1748 logf("retrieve failed");