diff options
-rw-r--r-- | apps/tagcache.c | 214 | ||||
-rw-r--r-- | apps/tagcache.h | 33 | ||||
-rw-r--r-- | apps/tagtree.c | 68 |
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 | ||
413 | static long find_entry_disk(const char *filename) | 413 | static 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) | |||
1006 | static bool build_lookup_list(struct tagcache_search *tcs) | 1016 | static 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 | ||
1184 | bool tagcache_is_busy(void) | ||
1185 | { | ||
1186 | return read_lock || write_lock; | ||
1187 | } | ||
1188 | |||
1158 | bool tagcache_search(struct tagcache_search *tcs, int tag) | 1189 | bool 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 | |||
1283 | static bool get_next(struct tagcache_search *tcs) | 1309 | static 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 | ||
118 | enum clause { clause_none, clause_is, clause_is_not, clause_gt, clause_gteq, | 116 | enum 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 | ||
157 | struct tagcache_seeklist_entry { | ||
158 | int32_t seek; | ||
159 | int32_t flag; | ||
160 | int32_t idx_id; | ||
161 | }; | ||
162 | |||
159 | struct tagcache_search { | 163 | struct 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 | ||
190 | void tagcache_build(const char *path); | 194 | void tagcache_build(const char *path); |
@@ -201,6 +205,7 @@ bool tagcache_is_numeric_tag(int type); | |||
201 | bool tagcache_find_index(struct tagcache_search *tcs, const char *filename); | 205 | bool tagcache_find_index(struct tagcache_search *tcs, const char *filename); |
202 | bool tagcache_check_clauses(struct tagcache_search *tcs, | 206 | bool tagcache_check_clauses(struct tagcache_search *tcs, |
203 | struct tagcache_search_clause **clause, int count); | 207 | struct tagcache_search_clause **clause, int count); |
208 | bool tagcache_is_busy(void); | ||
204 | bool tagcache_search(struct tagcache_search *tcs, int tag); | 209 | bool tagcache_search(struct tagcache_search *tcs, int tag); |
205 | void tagcache_search_set_uniqbuf(struct tagcache_search *tcs, | 210 | void 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 | ||
99 | static struct tagcache_search tcs, tcs2; | ||
100 | static bool sort_inverse; | 102 | static bool sort_inverse; |
101 | 103 | ||
102 | /* | 104 | /* |
@@ -642,6 +644,8 @@ static int compare(const void *p1, const void *p2) | |||
642 | 644 | ||
643 | static void tagtree_buffer_event(struct mp3entry *id3) | 645 | static 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 | ||
720 | bool tagtree_export(void) | 724 | bool 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 | ||
1043 | static int retrieve_entries(struct tree_context *c, struct tagcache_search *tcs, | 1049 | static 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 | ||
1550 | int tagtree_get_filename(struct tree_context* c, char *buf, int buflen) | 1558 | int 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 | ||
1570 | static bool insert_all_playlist(struct tree_context *c, int position, bool queue) | 1579 | static 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"); |