summaryrefslogtreecommitdiff
path: root/apps/tagcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r--apps/tagcache.c214
1 files changed, 134 insertions, 80 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