diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2017-01-18 04:39:35 -0500 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2017-02-10 05:05:23 -0500 |
commit | 7373cf518f4d4c47f49693690c2ab8ec29bb8510 (patch) | |
tree | 0a3c025749be24561e952078e83c5f2e8b838900 | |
parent | abd75a17d18c0779b59f64a612f9226b62af5823 (diff) | |
download | rockbox-7373cf518f4d4c47f49693690c2ab8ec29bb8510.tar.gz rockbox-7373cf518f4d4c47f49693690c2ab8ec29bb8510.zip |
Restore dircache hookup in the database ramcache.
Do a few other changes to dircache and file code flags to
accomodate its demands.
Change-Id: I4742a54e8cfbe4d8b9cffb75faaf920dd907cf8a
-rw-r--r-- | apps/playlist.c | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 837 | ||||
-rw-r--r-- | firmware/common/dir.c | 3 | ||||
-rw-r--r-- | firmware/common/dircache.c | 209 | ||||
-rw-r--r-- | firmware/common/file.c | 10 | ||||
-rw-r--r-- | firmware/common/file_internal.c | 10 | ||||
-rw-r--r-- | firmware/include/dircache.h | 11 | ||||
-rw-r--r-- | firmware/include/file_internal.h | 27 |
8 files changed, 619 insertions, 490 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index 176cfc3af7..e8d9896a01 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -1324,7 +1324,7 @@ static void playlist_thread(void) | |||
1324 | && queue_empty(&playlist_queue); index++) | 1324 | && queue_empty(&playlist_queue); index++) |
1325 | { | 1325 | { |
1326 | /* Process only pointers that are superficially stale. */ | 1326 | /* Process only pointers that are superficially stale. */ |
1327 | if (dircache_search(DCS_FILEREF, &playlist->dcfrefs[index], NULL) == 0) | 1327 | if (dircache_search(DCS_FILEREF, &playlist->dcfrefs[index], NULL) > 0) |
1328 | continue ; | 1328 | continue ; |
1329 | 1329 | ||
1330 | control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; | 1330 | control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; |
diff --git a/apps/tagcache.c b/apps/tagcache.c index 2b3c7212a2..be4686679b 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -82,18 +82,15 @@ | |||
82 | #include "pathfuncs.h" | 82 | #include "pathfuncs.h" |
83 | #include "structec.h" | 83 | #include "structec.h" |
84 | #include "debug.h" | 84 | #include "debug.h" |
85 | #ifdef HAVE_DIRCACHE | ||
86 | #include "dircache.h" | ||
87 | #endif | ||
85 | 88 | ||
86 | #ifndef __PCTOOL__ | 89 | #ifndef __PCTOOL__ |
87 | #include "lang.h" | 90 | #include "lang.h" |
88 | #include "eeprom_settings.h" | 91 | #include "eeprom_settings.h" |
89 | #endif | 92 | #endif |
90 | 93 | ||
91 | #undef HAVE_DIRCACHE | ||
92 | |||
93 | #ifdef HAVE_DIRCACHE | ||
94 | #include "dircache.h" | ||
95 | #endif | ||
96 | |||
97 | #ifdef __PCTOOL__ | 94 | #ifdef __PCTOOL__ |
98 | #define yield() do { } while(0) | 95 | #define yield() do { } while(0) |
99 | #define sim_sleep(timeout) do { } while(0) | 96 | #define sim_sleep(timeout) do { } while(0) |
@@ -213,27 +210,60 @@ static const char * const master_header_ec = "llllll"; | |||
213 | static struct master_header current_tcmh; | 210 | static struct master_header current_tcmh; |
214 | 211 | ||
215 | #ifdef HAVE_TC_RAMCACHE | 212 | #ifdef HAVE_TC_RAMCACHE |
213 | |||
214 | #define TC_ALIGN_PTR(p, gap_out_p) \ | ||
215 | ({ typeof (p) __p = (p); \ | ||
216 | typeof (p) __palgn = ALIGN_UP(__p, sizeof (intptr_t)); \ | ||
217 | *(gap_out_p) = __palgn - __p; \ | ||
218 | __palgn; }) | ||
219 | |||
220 | #define IF_TCRCDC(...) IF_DIRCACHE(__VA_ARGS__) | ||
221 | |||
222 | #ifdef HAVE_DIRCACHE | ||
223 | #define tcrc_dcfrefs \ | ||
224 | ((struct dircache_fileref *)(tcramcache.hdr->tags[tag_filename] + \ | ||
225 | sizeof (struct tagcache_header))) | ||
226 | #endif /* HAVE_DIRCACHE */ | ||
227 | |||
216 | /* Header is created when loading database to ram. */ | 228 | /* Header is created when loading database to ram. */ |
217 | struct ramcache_header { | 229 | struct ramcache_header { |
218 | char *tags[TAG_COUNT]; /* Tag file content (not including filename tag) */ | 230 | char *tags[TAG_COUNT]; /* Tag file content (dcfrefs if tag_filename) */ |
219 | int entry_count[TAG_COUNT]; /* Number of entries in the indices. */ | 231 | int entry_count[TAG_COUNT]; /* Number of entries in the indices. */ |
220 | struct index_entry indices[0]; /* Master index file content */ | 232 | struct index_entry indices[0]; /* Master index file content */ |
221 | }; | 233 | }; |
222 | 234 | ||
223 | # ifdef HAVE_EEPROM_SETTINGS | 235 | #ifdef HAVE_EEPROM_SETTINGS |
224 | struct statefile_header { | 236 | struct statefile_header { |
225 | int32_t magic; /* Statefile version number */ | 237 | int32_t magic; /* Statefile version number */ |
226 | struct master_header mh; /* Header from the master index */ | 238 | struct master_header mh; /* Header from the master index */ |
227 | struct ramcache_header *hdr; /* Old load address of hdr for relocation */ | 239 | struct ramcache_header *hdr; /* Old load address of hdr for relocation */ |
228 | struct tagcache_stat tc_stat; | 240 | struct tagcache_stat tc_stat; |
229 | }; | 241 | }; |
230 | # endif | 242 | #endif /* HAVE_EEPROM_SETTINGS */ |
231 | 243 | ||
232 | /* Pointer to allocated ramcache_header */ | 244 | /* In-RAM ramcache structure (not persisted) */ |
233 | static struct ramcache_header *ramcache_hdr; | 245 | static struct tcramcache |
234 | /* lock entity to temporarily prevent ramcache_hdr from moving */ | 246 | { |
235 | static int move_lock; | 247 | struct ramcache_header *hdr; /* allocated ramcache_header */ |
236 | #endif | 248 | int handle; /* buffer handle */ |
249 | int move_lock; | ||
250 | } tcramcache; | ||
251 | |||
252 | static inline void tcrc_buffer_lock(void) | ||
253 | { | ||
254 | tcramcache.move_lock++; | ||
255 | } | ||
256 | |||
257 | static inline void tcrc_buffer_unlock(void) | ||
258 | { | ||
259 | tcramcache.move_lock--; | ||
260 | } | ||
261 | |||
262 | #else /* ndef HAVE_TC_RAMCACHE */ | ||
263 | |||
264 | #define IF_TCRCDC(...) | ||
265 | |||
266 | #endif /* HAVE_TC_RAMCACHE */ | ||
237 | 267 | ||
238 | /** | 268 | /** |
239 | * Full tag entries stored in a temporary file waiting | 269 | * Full tag entries stored in a temporary file waiting |
@@ -275,6 +305,41 @@ static volatile int read_lock; | |||
275 | 305 | ||
276 | static bool delete_entry(long idx_id); | 306 | static bool delete_entry(long idx_id); |
277 | 307 | ||
308 | static void allocate_tempbuf(void) | ||
309 | { | ||
310 | /* Yeah, malloc would be really nice now :) */ | ||
311 | size_t size; | ||
312 | tempbuf_size = 0; | ||
313 | |||
314 | #ifdef __PCTOOL__ | ||
315 | size = 32*1024*1024; | ||
316 | tempbuf = malloc(size); | ||
317 | if (tempbuf) | ||
318 | tempbuf_size = size; | ||
319 | #else /* !__PCTOOL__ */ | ||
320 | tempbuf_handle = core_alloc_maximum("tc tempbuf", &size, NULL); | ||
321 | if (tempbuf_handle > 0) | ||
322 | { | ||
323 | tempbuf = core_get_data(tempbuf_handle); | ||
324 | tempbuf_size = size; | ||
325 | } | ||
326 | #endif /* __PCTOOL__ */ | ||
327 | } | ||
328 | |||
329 | static void free_tempbuf(void) | ||
330 | { | ||
331 | if (tempbuf_size == 0) | ||
332 | return ; | ||
333 | |||
334 | #ifdef __PCTOOL__ | ||
335 | free(tempbuf); | ||
336 | #else | ||
337 | tempbuf_handle = core_free(tempbuf_handle); | ||
338 | #endif | ||
339 | tempbuf = NULL; | ||
340 | tempbuf_size = 0; | ||
341 | } | ||
342 | |||
278 | const char* tagcache_tag_to_str(int tag) | 343 | const char* tagcache_tag_to_str(int tag) |
279 | { | 344 | { |
280 | return tags_str[tag]; | 345 | return tags_str[tag]; |
@@ -381,51 +446,64 @@ static bool do_timed_yield(void) | |||
381 | } | 446 | } |
382 | return false; | 447 | return false; |
383 | } | 448 | } |
384 | #endif | 449 | #endif /* __PCTOOL__ */ |
385 | 450 | ||
386 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | 451 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
387 | /* find the ramcache entry corresponding to the file indicated by | 452 | /* find the ramcache entry corresponding to the file indicated by |
388 | * filename and dc (it's corresponding dircache id). */ | 453 | * filename and dc (it's corresponding dircache id). */ |
389 | static long find_entry_ram(const char *filename, int dc) | 454 | static long find_entry_ram(const char *filename) |
390 | { | 455 | { |
391 | static long last_pos = 0; | 456 | static long last_pos = 0; |
392 | int i; | 457 | struct dircache_fileref dcfref; |
393 | 458 | ||
394 | /* Check if tagcache is loaded into ram. */ | 459 | /* Check if tagcache is loaded into ram. */ |
395 | if (!tc_stat.ramcache || !is_dircache_intact()) | 460 | if (!tc_stat.ramcache) |
396 | return -1; | 461 | return -1; |
397 | 462 | ||
398 | if (dc < 0) | 463 | if (dircache_search(DCS_CACHED_PATH | DCS_UPDATE_FILEREF, &dcfref, |
399 | dc = dircache_get_entry_id(filename); | 464 | filename) <= 0) |
400 | |||
401 | if (dc < 0) | ||
402 | { | 465 | { |
403 | logf("tagcache: file not found."); | 466 | logf("tagcache: file not found."); |
404 | return -1; | 467 | return -1; |
405 | } | 468 | } |
406 | 469 | ||
407 | try_again: | 470 | /* Search references */ |
408 | 471 | int end_pos = current_tcmh.tch.entry_count; | |
409 | if (last_pos > 0) | 472 | while (1) |
410 | i = last_pos; | ||
411 | else | ||
412 | i = 0; | ||
413 | |||
414 | for (; i < current_tcmh.tch.entry_count; i++) | ||
415 | { | 473 | { |
416 | if (ramcache_hdr->indices[i].tag_seek[tag_filename] == dc) | 474 | for (int i = last_pos; i < end_pos; i++) |
417 | { | 475 | { |
418 | last_pos = MAX(0, i - 3); | 476 | if (tcramcache.hdr->indices[i].flag & FLAG_DIRCACHE) |
419 | return i; | 477 | { |
478 | int cmp = dircache_fileref_cmp(&tcrc_dcfrefs[i], &dcfref); | ||
479 | if (cmp > 0) | ||
480 | { | ||
481 | if (cmp < 3) | ||
482 | { | ||
483 | if (dircache_search(DCS_CACHED_PATH | DCS_UPDATE_FILEREF, | ||
484 | &dcfref, filename) <= 0) | ||
485 | return -1; | ||
486 | |||
487 | if (dircache_fileref_cmp(&tcrc_dcfrefs[i], &dcfref) < 3) | ||
488 | return -1; | ||
489 | } | ||
490 | |||
491 | last_pos = MAX(0, i - 3); | ||
492 | return i; | ||
493 | } | ||
494 | } | ||
495 | |||
496 | do_timed_yield(); | ||
420 | } | 497 | } |
421 | |||
422 | do_timed_yield(); | ||
423 | } | ||
424 | 498 | ||
425 | if (last_pos > 0) | 499 | if (last_pos == 0) |
426 | { | 500 | { |
501 | last_pos = MAX(0, end_pos - 3); | ||
502 | break; | ||
503 | } | ||
504 | |||
505 | end_pos = last_pos; | ||
427 | last_pos = 0; | 506 | last_pos = 0; |
428 | goto try_again; | ||
429 | } | 507 | } |
430 | 508 | ||
431 | return -1; | 509 | return -1; |
@@ -450,7 +528,7 @@ static long find_entry_disk(const char *filename_raw, bool localfd) | |||
450 | char pathbuf[PATH_MAX]; /* Note: Don't use MAX_PATH here, it's too small */ | 528 | char pathbuf[PATH_MAX]; /* Note: Don't use MAX_PATH here, it's too small */ |
451 | if (realpath(filename, pathbuf) == pathbuf) | 529 | if (realpath(filename, pathbuf) == pathbuf) |
452 | filename = pathbuf; | 530 | filename = pathbuf; |
453 | #endif | 531 | #endif /* APPLICATION */ |
454 | 532 | ||
455 | if (!tc_stat.ready) | 533 | if (!tc_stat.ready) |
456 | return -2; | 534 | return -2; |
@@ -540,7 +618,7 @@ static int find_index(const char *filename) | |||
540 | long idx_id = -1; | 618 | long idx_id = -1; |
541 | 619 | ||
542 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | 620 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
543 | idx_id = find_entry_ram(filename, -1); | 621 | idx_id = find_entry_ram(filename); |
544 | #endif | 622 | #endif |
545 | 623 | ||
546 | if (idx_id < 0) | 624 | if (idx_id < 0) |
@@ -583,19 +661,13 @@ static bool get_index(int masterfd, int idxid, | |||
583 | #ifdef HAVE_TC_RAMCACHE | 661 | #ifdef HAVE_TC_RAMCACHE |
584 | if (tc_stat.ramcache && use_ram) | 662 | if (tc_stat.ramcache && use_ram) |
585 | { | 663 | { |
586 | if (ramcache_hdr->indices[idxid].flag & FLAG_DELETED) | 664 | if (tcramcache.hdr->indices[idxid].flag & FLAG_DELETED) |
587 | return false; | 665 | return false; |
588 | 666 | ||
589 | #ifdef HAVE_DIRCACHE | 667 | *idx = tcramcache.hdr->indices[idxid]; |
590 | if (!(ramcache_hdr->indices[idxid].flag & FLAG_DIRCACHE) | 668 | return true; |
591 | || is_dircache_intact()) | ||
592 | #endif | ||
593 | { | ||
594 | memcpy(idx, &ramcache_hdr->indices[idxid], sizeof(struct index_entry)); | ||
595 | return true; | ||
596 | } | ||
597 | } | 669 | } |
598 | #endif | 670 | #endif /* HAVE_TC_RAMCACHE */ |
599 | 671 | ||
600 | if (masterfd < 0) | 672 | if (masterfd < 0) |
601 | { | 673 | { |
@@ -647,10 +719,9 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx) | |||
647 | */ | 719 | */ |
648 | if (tc_stat.ramcache) | 720 | if (tc_stat.ramcache) |
649 | { | 721 | { |
650 | int tag; | 722 | struct index_entry *idx_ram = &tcramcache.hdr->indices[idxid]; |
651 | struct index_entry *idx_ram = &ramcache_hdr->indices[idxid]; | ||
652 | 723 | ||
653 | for (tag = 0; tag < TAG_COUNT; tag++) | 724 | for (int tag = 0; tag < TAG_COUNT; tag++) |
654 | { | 725 | { |
655 | if (TAGCACHE_IS_NUMERIC(tag)) | 726 | if (TAGCACHE_IS_NUMERIC(tag)) |
656 | { | 727 | { |
@@ -662,7 +733,7 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx) | |||
662 | idx_ram->flag = (idx->flag & 0x0000ffff) | 733 | idx_ram->flag = (idx->flag & 0x0000ffff) |
663 | | (idx_ram->flag & (0xffff0000 | FLAG_DIRCACHE)); | 734 | | (idx_ram->flag & (0xffff0000 | FLAG_DIRCACHE)); |
664 | } | 735 | } |
665 | #endif | 736 | #endif /* HAVE_TC_RAMCACHE */ |
666 | 737 | ||
667 | lseek(masterfd, idxid * sizeof(struct index_entry) | 738 | lseek(masterfd, idxid * sizeof(struct index_entry) |
668 | + sizeof(struct master_header), SEEK_SET); | 739 | + sizeof(struct master_header), SEEK_SET); |
@@ -697,8 +768,8 @@ static bool open_files(struct tagcache_search *tcs, int tag) | |||
697 | return true; | 768 | return true; |
698 | } | 769 | } |
699 | 770 | ||
700 | static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, | 771 | static bool retrieve(struct tagcache_search *tcs, int idx_id, |
701 | int tag, char *buf, long size) | 772 | struct index_entry *idx, int tag, char *buf, long size) |
702 | { | 773 | { |
703 | struct tagfile_entry tfe; | 774 | struct tagfile_entry tfe; |
704 | long seek; | 775 | long seek; |
@@ -718,39 +789,24 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, | |||
718 | #ifdef HAVE_TC_RAMCACHE | 789 | #ifdef HAVE_TC_RAMCACHE |
719 | if (tcs->ramsearch) | 790 | if (tcs->ramsearch) |
720 | { | 791 | { |
721 | struct tagfile_entry *ep; | ||
722 | |||
723 | #ifdef HAVE_DIRCACHE | 792 | #ifdef HAVE_DIRCACHE |
724 | if (tag == tag_filename && (idx->flag & FLAG_DIRCACHE)) | 793 | if (tag == tag_filename && (idx->flag & FLAG_DIRCACHE)) |
725 | { | 794 | { |
726 | /* for tag_filename, seek is a dircache index */ | 795 | if (dircache_get_fileref_path(&tcrc_dcfrefs[idx_id], buf, size) >= 0) |
727 | if (is_dircache_intact()) | ||
728 | { | ||
729 | dircache_copy_path(seek, buf, size); | ||
730 | return true; | 796 | return true; |
731 | } | ||
732 | else | ||
733 | { | ||
734 | /* The seek is useless now, there's nothing we can return. */ | ||
735 | logf("retrieve: dircache gone, cannot read file name"); | ||
736 | tagcache_unload_ramcache(); | ||
737 | // XXX do this when there's a way to not trigger an | ||
738 | // update before reloading: | ||
739 | // tagcache_start_scan(); | ||
740 | return false; | ||
741 | } | ||
742 | } | 797 | } |
743 | else | 798 | else |
744 | #endif /* HAVE_DIRCACHE */ | 799 | #endif /* HAVE_DIRCACHE */ |
745 | if (tag != tag_filename) | 800 | if (tag != tag_filename) |
746 | { | 801 | { |
747 | ep = (struct tagfile_entry *)&ramcache_hdr->tags[tag][seek]; | 802 | struct tagfile_entry *ep = |
803 | (struct tagfile_entry *)&tcramcache.hdr->tags[tag][seek]; | ||
748 | strlcpy(buf, ep->tag_data, size); | 804 | strlcpy(buf, ep->tag_data, size); |
749 | 805 | ||
750 | return true; | 806 | return true; |
751 | } | 807 | } |
752 | } | 808 | } |
753 | #endif | 809 | #endif /* HAVE_TC_RAMCACHE */ |
754 | 810 | ||
755 | if (!open_files(tcs, tag)) | 811 | if (!open_files(tcs, tag)) |
756 | return false; | 812 | return false; |
@@ -777,7 +833,7 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx, | |||
777 | } | 833 | } |
778 | 834 | ||
779 | buf[tfe.tag_length] = '\0'; | 835 | buf[tfe.tag_length] = '\0'; |
780 | 836 | ||
781 | return true; | 837 | return true; |
782 | } | 838 | } |
783 | 839 | ||
@@ -1031,12 +1087,13 @@ static bool check_clauses(struct tagcache_search *tcs, | |||
1031 | if (clause->tag == tag_filename | 1087 | if (clause->tag == tag_filename |
1032 | || clause->tag == tag_virt_basename) | 1088 | || clause->tag == tag_virt_basename) |
1033 | { | 1089 | { |
1034 | retrieve(tcs, idx, tag_filename, buf, sizeof buf); | 1090 | retrieve(tcs, tcs->idx_id, idx, tag_filename, buf, |
1091 | sizeof buf); | ||
1035 | } | 1092 | } |
1036 | else | 1093 | else |
1037 | { | 1094 | { |
1038 | tfe = (struct tagfile_entry *) | 1095 | tfe = (struct tagfile_entry *) |
1039 | &ramcache_hdr->tags[clause->tag][seek]; | 1096 | &tcramcache.hdr->tags[clause->tag][seek]; |
1040 | /* str points to movable data, but no locking required here, | 1097 | /* str points to movable data, but no locking required here, |
1041 | * as no yield() is following */ | 1098 | * as no yield() is following */ |
1042 | str = tfe->tag_data; | 1099 | str = tfe->tag_data; |
@@ -1044,7 +1101,7 @@ static bool check_clauses(struct tagcache_search *tcs, | |||
1044 | } | 1101 | } |
1045 | } | 1102 | } |
1046 | else | 1103 | else |
1047 | #endif | 1104 | #endif /* HAVE_TC_RAMCACHE */ |
1048 | { | 1105 | { |
1049 | struct tagfile_entry tfe; | 1106 | struct tagfile_entry tfe; |
1050 | 1107 | ||
@@ -1147,18 +1204,15 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
1147 | tcs->seek_list_count = 0; | 1204 | tcs->seek_list_count = 0; |
1148 | 1205 | ||
1149 | #ifdef HAVE_TC_RAMCACHE | 1206 | #ifdef HAVE_TC_RAMCACHE |
1150 | if (tcs->ramsearch | 1207 | if (tcs->ramsearch) |
1151 | # ifdef HAVE_DIRCACHE | ||
1152 | && (tcs->type != tag_filename || is_dircache_intact()) | ||
1153 | # endif | ||
1154 | ) | ||
1155 | { | 1208 | { |
1156 | move_lock++; /* lock because below makes a pointer to movable data */ | 1209 | tcrc_buffer_lock(); /* lock because below makes a pointer to movable data */ |
1210 | |||
1157 | for (i = tcs->seek_pos; i < current_tcmh.tch.entry_count; i++) | 1211 | for (i = tcs->seek_pos; i < current_tcmh.tch.entry_count; i++) |
1158 | { | 1212 | { |
1159 | struct tagcache_seeklist_entry *seeklist; | 1213 | struct tagcache_seeklist_entry *seeklist; |
1160 | /* idx points to movable data, don't yield or reload */ | 1214 | /* idx points to movable data, don't yield or reload */ |
1161 | struct index_entry *idx = &ramcache_hdr->indices[i]; | 1215 | struct index_entry *idx = &tcramcache.hdr->indices[i]; |
1162 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 1216 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
1163 | break ; | 1217 | break ; |
1164 | 1218 | ||
@@ -1192,13 +1246,14 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
1192 | seeklist->idx_id = i; | 1246 | seeklist->idx_id = i; |
1193 | tcs->seek_list_count++; | 1247 | tcs->seek_list_count++; |
1194 | } | 1248 | } |
1195 | move_lock--; | 1249 | |
1196 | 1250 | tcrc_buffer_unlock(); | |
1251 | |||
1197 | tcs->seek_pos = i; | 1252 | tcs->seek_pos = i; |
1198 | 1253 | ||
1199 | return tcs->seek_list_count > 0; | 1254 | return tcs->seek_list_count > 0; |
1200 | } | 1255 | } |
1201 | #endif | 1256 | #endif /* HAVE_TC_RAMCACHE */ |
1202 | 1257 | ||
1203 | if (tcs->masterfd < 0) | 1258 | if (tcs->masterfd < 0) |
1204 | { | 1259 | { |
@@ -1339,7 +1394,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
1339 | tcs->ramsearch = tc_stat.ramcache; | 1394 | tcs->ramsearch = tc_stat.ramcache; |
1340 | if (tcs->ramsearch) | 1395 | if (tcs->ramsearch) |
1341 | { | 1396 | { |
1342 | tcs->entry_count = ramcache_hdr->entry_count[tcs->type]; | 1397 | tcs->entry_count = tcramcache.hdr->entry_count[tcs->type]; |
1343 | } | 1398 | } |
1344 | else | 1399 | else |
1345 | #endif | 1400 | #endif |
@@ -1510,34 +1565,24 @@ static bool get_next(struct tagcache_search *tcs) | |||
1510 | #ifdef HAVE_DIRCACHE | 1565 | #ifdef HAVE_DIRCACHE |
1511 | if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE)) | 1566 | if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE)) |
1512 | { | 1567 | { |
1513 | if (is_dircache_intact()) | 1568 | ssize_t len = dircache_get_fileref_path(&tcrc_dcfrefs[tcs->idx_id], |
1569 | buf, sizeof (buf)); | ||
1570 | if (len >= 0) | ||
1514 | { | 1571 | { |
1515 | size_t len = dircache_copy_path(tcs->position, buf, sizeof buf); | ||
1516 | tcs->result_len = len + 1; | 1572 | tcs->result_len = len + 1; |
1517 | tcs->result = buf; | 1573 | tcs->result = buf; |
1518 | tcs->ramresult = false; | 1574 | tcs->ramresult = false; |
1519 | |||
1520 | return true; | 1575 | return true; |
1521 | } | 1576 | } |
1522 | else | 1577 | /* else do it the hard way */ |
1523 | { | ||
1524 | /* The seek is useless now, there's nothing we can return. */ | ||
1525 | logf("get_next: dircache gone, cannot read file name"); | ||
1526 | tagcache_unload_ramcache(); | ||
1527 | // XXX do this when there's a way to not trigger an | ||
1528 | // update before reloading: | ||
1529 | // tagcache_start_scan(); | ||
1530 | tcs->valid = false; | ||
1531 | return false; | ||
1532 | } | ||
1533 | } | 1578 | } |
1534 | else | ||
1535 | #endif /* HAVE_DIRCACHE */ | 1579 | #endif /* HAVE_DIRCACHE */ |
1580 | |||
1536 | if (tcs->type != tag_filename) | 1581 | if (tcs->type != tag_filename) |
1537 | { | 1582 | { |
1538 | struct tagfile_entry *ep; | 1583 | struct tagfile_entry *ep; |
1539 | 1584 | ||
1540 | ep = (struct tagfile_entry *)&ramcache_hdr->tags[tcs->type][tcs->position]; | 1585 | ep = (struct tagfile_entry *)&tcramcache.hdr->tags[tcs->type][tcs->position]; |
1541 | /* don't return ep->tag_data directly as it may move */ | 1586 | /* don't return ep->tag_data directly as it may move */ |
1542 | tcs->result_len = strlcpy(buf, ep->tag_data, sizeof(buf)) + 1; | 1587 | tcs->result_len = strlcpy(buf, ep->tag_data, sizeof(buf)) + 1; |
1543 | tcs->result = buf; | 1588 | tcs->result = buf; |
@@ -1550,7 +1595,7 @@ static bool get_next(struct tagcache_search *tcs) | |||
1550 | return true; | 1595 | return true; |
1551 | } | 1596 | } |
1552 | } | 1597 | } |
1553 | #endif | 1598 | #endif /* HAVE_TC_RAMCACHE */ |
1554 | 1599 | ||
1555 | if (!open_files(tcs, tcs->type)) | 1600 | if (!open_files(tcs, tcs->type)) |
1556 | { | 1601 | { |
@@ -1616,7 +1661,7 @@ bool tagcache_retrieve(struct tagcache_search *tcs, int idxid, | |||
1616 | if (!get_index(tcs->masterfd, idxid, &idx, true)) | 1661 | if (!get_index(tcs->masterfd, idxid, &idx, true)) |
1617 | return false; | 1662 | return false; |
1618 | 1663 | ||
1619 | return retrieve(tcs, &idx, tag, buf, size); | 1664 | return retrieve(tcs, idxid, &idx, tag, buf, size); |
1620 | } | 1665 | } |
1621 | 1666 | ||
1622 | static bool update_master_header(void) | 1667 | static bool update_master_header(void) |
@@ -1674,7 +1719,7 @@ void tagcache_search_finish(struct tagcache_search *tcs) | |||
1674 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | 1719 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
1675 | static struct tagfile_entry *get_tag(const struct index_entry *entry, int tag) | 1720 | static struct tagfile_entry *get_tag(const struct index_entry *entry, int tag) |
1676 | { | 1721 | { |
1677 | return (struct tagfile_entry *)&ramcache_hdr->tags[tag][entry->tag_seek[tag]]; | 1722 | return (struct tagfile_entry *)&tcramcache.hdr->tags[tag][entry->tag_seek[tag]]; |
1678 | } | 1723 | } |
1679 | 1724 | ||
1680 | static long get_tag_numeric(const struct index_entry *entry, int tag, int idx_id) | 1725 | static long get_tag_numeric(const struct index_entry *entry, int tag, int idx_id) |
@@ -1697,11 +1742,11 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | |||
1697 | return false; | 1742 | return false; |
1698 | 1743 | ||
1699 | /* Find the corresponding entry in tagcache. */ | 1744 | /* Find the corresponding entry in tagcache. */ |
1700 | idx_id = find_entry_ram(filename, -1); | 1745 | idx_id = find_entry_ram(filename); |
1701 | if (idx_id < 0) | 1746 | if (idx_id < 0) |
1702 | return false; | 1747 | return false; |
1703 | 1748 | ||
1704 | entry = &ramcache_hdr->indices[idx_id]; | 1749 | entry = &tcramcache.hdr->indices[idx_id]; |
1705 | 1750 | ||
1706 | memset(id3, 0, sizeof(struct mp3entry)); | 1751 | memset(id3, 0, sizeof(struct mp3entry)); |
1707 | char* buf = id3->id3v2buf; | 1752 | char* buf = id3->id3v2buf; |
@@ -1761,14 +1806,7 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | |||
1761 | 1806 | ||
1762 | return true; | 1807 | return true; |
1763 | } | 1808 | } |
1764 | #elif defined (HAVE_TC_RAMCACHE) | 1809 | #endif /* defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) */ |
1765 | /* temporary dummy function until integration is sorted out --jethead71 */ | ||
1766 | bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | ||
1767 | { | ||
1768 | return false; | ||
1769 | (void)id3; (void)filename; | ||
1770 | } | ||
1771 | #endif | ||
1772 | 1810 | ||
1773 | static inline void write_item(const char *item) | 1811 | static inline void write_item(const char *item) |
1774 | { | 1812 | { |
@@ -1799,22 +1837,18 @@ static int check_if_empty(char **tag) | |||
1799 | return length + 1; | 1837 | return length + 1; |
1800 | } | 1838 | } |
1801 | 1839 | ||
1802 | #define ADD_TAG(entry,tag,data) \ | ||
1803 | /* Adding tag */ \ | ||
1804 | entry.tag_offset[tag] = offset; \ | ||
1805 | entry.tag_length[tag] = check_if_empty(data); \ | ||
1806 | offset += entry.tag_length[tag] | ||
1807 | /* GCC 3.4.6 for Coldfire can choose to inline this function. Not a good | 1840 | /* GCC 3.4.6 for Coldfire can choose to inline this function. Not a good |
1808 | * idea, as it uses lots of stack and is called from a recursive function | 1841 | * idea, as it uses lots of stack and is called from a recursive function |
1809 | * (check_dir). | 1842 | * (check_dir). |
1810 | */ | 1843 | */ |
1811 | static void __attribute__ ((noinline)) add_tagcache(char *path, | 1844 | static void NO_INLINE add_tagcache(char *path, unsigned long mtime) |
1812 | unsigned long mtime | ||
1813 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | ||
1814 | ,int dc | ||
1815 | #endif | ||
1816 | ) | ||
1817 | { | 1845 | { |
1846 | #define ADD_TAG(entry, tag, data) \ | ||
1847 | /* Adding tag */ \ | ||
1848 | entry.tag_offset[tag] = offset; \ | ||
1849 | entry.tag_length[tag] = check_if_empty(data); \ | ||
1850 | offset += entry.tag_length[tag] | ||
1851 | |||
1818 | struct mp3entry id3; | 1852 | struct mp3entry id3; |
1819 | struct temp_file_entry entry; | 1853 | struct temp_file_entry entry; |
1820 | bool ret; | 1854 | bool ret; |
@@ -1830,12 +1864,13 @@ static void __attribute__ ((noinline)) add_tagcache(char *path, | |||
1830 | /* Crude logging for the sim - to aid in debugging */ | 1864 | /* Crude logging for the sim - to aid in debugging */ |
1831 | int logfd = open(ROCKBOX_DIR "/database.log", | 1865 | int logfd = open(ROCKBOX_DIR "/database.log", |
1832 | O_WRONLY | O_APPEND | O_CREAT, 0666); | 1866 | O_WRONLY | O_APPEND | O_CREAT, 0666); |
1833 | if (logfd >= 0) { | 1867 | if (logfd >= 0) |
1868 | { | ||
1834 | write(logfd, path, strlen(path)); | 1869 | write(logfd, path, strlen(path)); |
1835 | write(logfd, "\n", 1); | 1870 | write(logfd, "\n", 1); |
1836 | close(logfd); | 1871 | close(logfd); |
1837 | } | 1872 | } |
1838 | #endif | 1873 | #endif /* SIMULATOR */ |
1839 | 1874 | ||
1840 | if (cachefd < 0) | 1875 | if (cachefd < 0) |
1841 | return ; | 1876 | return ; |
@@ -1854,7 +1889,7 @@ static void __attribute__ ((noinline)) add_tagcache(char *path, | |||
1854 | 1889 | ||
1855 | /* Check if the file is already cached. */ | 1890 | /* Check if the file is already cached. */ |
1856 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | 1891 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
1857 | idx_id = find_entry_ram(path, dc); | 1892 | idx_id = find_entry_ram(path); |
1858 | #endif | 1893 | #endif |
1859 | 1894 | ||
1860 | /* Be sure the entry doesn't exist. */ | 1895 | /* Be sure the entry doesn't exist. */ |
@@ -1979,7 +2014,10 @@ static void __attribute__ ((noinline)) add_tagcache(char *path, | |||
1979 | { | 2014 | { |
1980 | write_item(id3.title); | 2015 | write_item(id3.title); |
1981 | } | 2016 | } |
1982 | total_entry_count++; | 2017 | |
2018 | total_entry_count++; | ||
2019 | |||
2020 | #undef ADD_TAG | ||
1983 | } | 2021 | } |
1984 | 2022 | ||
1985 | static bool tempbuf_insert(char *str, int id, int idx_id, bool unique) | 2023 | static bool tempbuf_insert(char *str, int id, int idx_id, bool unique) |
@@ -2302,7 +2340,7 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd) | |||
2302 | * Skip unless the entry is marked as being deleted | 2340 | * Skip unless the entry is marked as being deleted |
2303 | * or the data has already been resurrected. | 2341 | * or the data has already been resurrected. |
2304 | */ | 2342 | */ |
2305 | if (!(idx.flag & FLAG_DELETED) || idx.flag & FLAG_RESURRECTED) | 2343 | if (!(idx.flag & FLAG_DELETED) || (idx.flag & FLAG_RESURRECTED)) |
2306 | continue; | 2344 | continue; |
2307 | 2345 | ||
2308 | /* Now try to match the entry. */ | 2346 | /* Now try to match the entry. */ |
@@ -2938,8 +2976,6 @@ static bool commit(void) | |||
2938 | #ifdef HAVE_TC_RAMCACHE | 2976 | #ifdef HAVE_TC_RAMCACHE |
2939 | bool ramcache_buffer_stolen = false; | 2977 | bool ramcache_buffer_stolen = false; |
2940 | #endif | 2978 | #endif |
2941 | bool local_allocation = false; | ||
2942 | |||
2943 | logf("committing tagcache"); | 2979 | logf("committing tagcache"); |
2944 | 2980 | ||
2945 | while (write_lock) | 2981 | while (write_lock) |
@@ -2990,9 +3026,6 @@ static bool commit(void) | |||
2990 | read_lock++; | 3026 | read_lock++; |
2991 | 3027 | ||
2992 | /* Try to steal every buffer we can :) */ | 3028 | /* Try to steal every buffer we can :) */ |
2993 | if (tempbuf_size == 0) | ||
2994 | local_allocation = true; | ||
2995 | |||
2996 | #ifdef HAVE_DIRCACHE | 3029 | #ifdef HAVE_DIRCACHE |
2997 | if (tempbuf_size == 0) | 3030 | if (tempbuf_size == 0) |
2998 | { | 3031 | { |
@@ -3007,13 +3040,13 @@ static bool commit(void) | |||
3007 | #ifdef HAVE_TC_RAMCACHE | 3040 | #ifdef HAVE_TC_RAMCACHE |
3008 | if (tempbuf_size == 0 && tc_stat.ramcache_allocated > 0) | 3041 | if (tempbuf_size == 0 && tc_stat.ramcache_allocated > 0) |
3009 | { | 3042 | { |
3010 | tempbuf = (char *)(ramcache_hdr + 1); | 3043 | tcrc_buffer_lock(); |
3044 | tempbuf = (char *)(tcramcache.hdr + 1); | ||
3011 | tempbuf_size = tc_stat.ramcache_allocated - sizeof(struct ramcache_header) - 128; | 3045 | tempbuf_size = tc_stat.ramcache_allocated - sizeof(struct ramcache_header) - 128; |
3012 | tempbuf_size &= ~0x03; | 3046 | tempbuf_size &= ~0x03; |
3013 | move_lock++; | ||
3014 | ramcache_buffer_stolen = true; | 3047 | ramcache_buffer_stolen = true; |
3015 | } | 3048 | } |
3016 | #endif | 3049 | #endif /* HAVE_TC_RAMCACHE */ |
3017 | 3050 | ||
3018 | /* And finally fail if there are no buffers available. */ | 3051 | /* And finally fail if there are no buffers available. */ |
3019 | if (tempbuf_size == 0) | 3052 | if (tempbuf_size == 0) |
@@ -3089,75 +3122,46 @@ static bool commit(void) | |||
3089 | tc_stat.ready = check_all_headers(); | 3122 | tc_stat.ready = check_all_headers(); |
3090 | tc_stat.readyvalid = true; | 3123 | tc_stat.readyvalid = true; |
3091 | 3124 | ||
3092 | if (local_allocation) | ||
3093 | { | ||
3094 | tempbuf = NULL; | ||
3095 | tempbuf_size = 0; | ||
3096 | } | ||
3097 | |||
3098 | #ifdef HAVE_TC_RAMCACHE | 3125 | #ifdef HAVE_TC_RAMCACHE |
3099 | if (ramcache_buffer_stolen) | 3126 | if (ramcache_buffer_stolen) |
3100 | { | 3127 | { |
3128 | tempbuf = NULL; | ||
3129 | tempbuf_size = 0; | ||
3101 | ramcache_buffer_stolen = false; | 3130 | ramcache_buffer_stolen = false; |
3102 | move_lock--; | 3131 | tcrc_buffer_unlock(); |
3103 | } | 3132 | } |
3104 | 3133 | ||
3105 | /* Reload tagcache. */ | 3134 | /* Reload tagcache. */ |
3106 | if (tc_stat.ramcache_allocated > 0) | 3135 | if (tc_stat.ramcache_allocated > 0) |
3107 | tagcache_start_scan(); | 3136 | tagcache_start_scan(); |
3108 | #endif | 3137 | #endif /* HAVE_TC_RAMCACHE */ |
3109 | 3138 | ||
3110 | rc = true; | 3139 | rc = true; |
3111 | 3140 | ||
3112 | commit_error: | 3141 | commit_error: |
3113 | #ifdef HAVE_TC_RAMCACHE | 3142 | #ifdef HAVE_TC_RAMCACHE |
3114 | if (ramcache_buffer_stolen) | 3143 | if (ramcache_buffer_stolen) |
3115 | move_lock--; | 3144 | { |
3116 | #endif | 3145 | tempbuf = NULL; |
3146 | tempbuf_size = 0; | ||
3147 | tcrc_buffer_unlock(); | ||
3148 | } | ||
3149 | #endif /* HAVE_TC_RAMCACHE */ | ||
3117 | 3150 | ||
3118 | read_lock--; | 3151 | read_lock--; |
3119 | 3152 | ||
3120 | #ifdef HAVE_DIRCACHE | 3153 | #ifdef HAVE_DIRCACHE |
3121 | /* Resume the dircache, if we stole the buffer. */ | 3154 | /* Resume the dircache, if we stole the buffer. */ |
3122 | if (dircache_buffer_stolen) | 3155 | if (dircache_buffer_stolen) |
3156 | { | ||
3157 | free_tempbuf(); | ||
3123 | dircache_resume(); | 3158 | dircache_resume(); |
3124 | #endif | 3159 | } |
3160 | #endif /* HAVE_DIRCACHE */ | ||
3125 | 3161 | ||
3126 | return rc; | 3162 | return rc; |
3127 | } | 3163 | } |
3128 | 3164 | ||
3129 | static void allocate_tempbuf(void) | ||
3130 | { | ||
3131 | /* Yeah, malloc would be really nice now :) */ | ||
3132 | size_t size; | ||
3133 | tempbuf_size = 0; | ||
3134 | |||
3135 | #ifdef __PCTOOL__ | ||
3136 | size = 32*1024*1024; | ||
3137 | tempbuf = malloc(size); | ||
3138 | #else | ||
3139 | tempbuf_handle = core_alloc_maximum("tc tempbuf", &size, NULL); | ||
3140 | tempbuf = core_get_data(tempbuf_handle); | ||
3141 | #endif | ||
3142 | |||
3143 | if (tempbuf) | ||
3144 | tempbuf_size = size; | ||
3145 | } | ||
3146 | |||
3147 | static void free_tempbuf(void) | ||
3148 | { | ||
3149 | if (tempbuf_size == 0) | ||
3150 | return ; | ||
3151 | |||
3152 | #ifdef __PCTOOL__ | ||
3153 | free(tempbuf); | ||
3154 | #else | ||
3155 | tempbuf_handle = core_free(tempbuf_handle); | ||
3156 | #endif | ||
3157 | tempbuf = NULL; | ||
3158 | tempbuf_size = 0; | ||
3159 | } | ||
3160 | |||
3161 | #ifndef __PCTOOL__ | 3165 | #ifndef __PCTOOL__ |
3162 | 3166 | ||
3163 | static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) | 3167 | static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data) |
@@ -3645,7 +3649,7 @@ static bool delete_entry(long idx_id) | |||
3645 | #ifdef HAVE_TC_RAMCACHE | 3649 | #ifdef HAVE_TC_RAMCACHE |
3646 | /* At first mark the entry removed from ram cache. */ | 3650 | /* At first mark the entry removed from ram cache. */ |
3647 | if (tc_stat.ramcache) | 3651 | if (tc_stat.ramcache) |
3648 | ramcache_hdr->indices[idx_id].flag |= FLAG_DELETED; | 3652 | tcramcache.hdr->indices[idx_id].flag |= FLAG_DELETED; |
3649 | #endif | 3653 | #endif |
3650 | 3654 | ||
3651 | if ( (masterfd = open_master_fd(&myhdr, true) ) < 0) | 3655 | if ( (masterfd = open_master_fd(&myhdr, true) ) < 0) |
@@ -3684,7 +3688,7 @@ static bool delete_entry(long idx_id) | |||
3684 | #ifdef HAVE_TC_RAMCACHE | 3688 | #ifdef HAVE_TC_RAMCACHE |
3685 | /* Use RAM DB if available for greater speed */ | 3689 | /* Use RAM DB if available for greater speed */ |
3686 | if (tc_stat.ramcache) | 3690 | if (tc_stat.ramcache) |
3687 | idxp = &ramcache_hdr->indices[i]; | 3691 | idxp = &tcramcache.hdr->indices[i]; |
3688 | else | 3692 | else |
3689 | #endif | 3693 | #endif |
3690 | { | 3694 | { |
@@ -3727,16 +3731,16 @@ static bool delete_entry(long idx_id) | |||
3727 | if (tc_stat.ramcache && tag != tag_filename) | 3731 | if (tc_stat.ramcache && tag != tag_filename) |
3728 | { | 3732 | { |
3729 | struct tagfile_entry *tfe; | 3733 | struct tagfile_entry *tfe; |
3730 | int32_t *seek = &ramcache_hdr->indices[idx_id].tag_seek[tag]; | 3734 | int32_t *seek = &tcramcache.hdr->indices[idx_id].tag_seek[tag]; |
3731 | 3735 | ||
3732 | tfe = (struct tagfile_entry *)&ramcache_hdr->tags[tag][*seek]; | 3736 | tfe = (struct tagfile_entry *)&tcramcache.hdr->tags[tag][*seek]; |
3733 | move_lock++; /* protect tfe and seek if crc_32() yield()s */ | 3737 | tcrc_buffer_lock(); /* protect tfe and seek if crc_32() yield()s */ |
3734 | *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff); | 3738 | *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff); |
3735 | move_lock--; | 3739 | tcrc_buffer_unlock(); |
3736 | myidx.tag_seek[tag] = *seek; | 3740 | myidx.tag_seek[tag] = *seek; |
3737 | } | 3741 | } |
3738 | else | 3742 | else |
3739 | #endif | 3743 | #endif /* HAVE_TC_RAMCACHE */ |
3740 | { | 3744 | { |
3741 | struct tagfile_entry tfe; | 3745 | struct tagfile_entry tfe; |
3742 | 3746 | ||
@@ -3777,10 +3781,10 @@ static bool delete_entry(long idx_id) | |||
3777 | if (tc_stat.ramcache && tag != tag_filename) | 3781 | if (tc_stat.ramcache && tag != tag_filename) |
3778 | { | 3782 | { |
3779 | struct tagfile_entry *tagentry = | 3783 | struct tagfile_entry *tagentry = |
3780 | (struct tagfile_entry *)&ramcache_hdr->tags[tag][oldseek]; | 3784 | (struct tagfile_entry *)&tcramcache.hdr->tags[tag][oldseek]; |
3781 | tagentry->tag_data[0] = '\0'; | 3785 | tagentry->tag_data[0] = '\0'; |
3782 | } | 3786 | } |
3783 | #endif | 3787 | #endif /* HAVE_TC_RAMCACHE */ |
3784 | 3788 | ||
3785 | /* Open the index file, which contains the tag names. */ | 3789 | /* Open the index file, which contains the tag names. */ |
3786 | if (fd < 0) | 3790 | if (fd < 0) |
@@ -3829,13 +3833,13 @@ static bool delete_entry(long idx_id) | |||
3829 | return false; | 3833 | return false; |
3830 | } | 3834 | } |
3831 | 3835 | ||
3832 | #ifndef __PCTOOL__ | ||
3833 | /** | 3836 | /** |
3834 | * Returns true if there is an event waiting in the queue | 3837 | * Returns true if there is an event waiting in the queue |
3835 | * that requires the current operation to be aborted. | 3838 | * that requires the current operation to be aborted. |
3836 | */ | 3839 | */ |
3837 | static bool check_event_queue(void) | 3840 | static bool check_event_queue(void) |
3838 | { | 3841 | { |
3842 | #ifndef __PCTOOL__ | ||
3839 | struct queue_event ev; | 3843 | struct queue_event ev; |
3840 | 3844 | ||
3841 | if(!queue_peek(&tagcache_queue, &ev)) | 3845 | if(!queue_peek(&tagcache_queue, &ev)) |
@@ -3848,10 +3852,10 @@ static bool check_event_queue(void) | |||
3848 | case SYS_USB_CONNECTED: | 3852 | case SYS_USB_CONNECTED: |
3849 | return true; | 3853 | return true; |
3850 | } | 3854 | } |
3855 | #endif /* __PCTOOL__ */ | ||
3851 | 3856 | ||
3852 | return false; | 3857 | return false; |
3853 | } | 3858 | } |
3854 | #endif | ||
3855 | 3859 | ||
3856 | #ifdef HAVE_TC_RAMCACHE | 3860 | #ifdef HAVE_TC_RAMCACHE |
3857 | 3861 | ||
@@ -3859,18 +3863,18 @@ static void fix_ramcache(void* old_addr, void* new_addr) | |||
3859 | { | 3863 | { |
3860 | ptrdiff_t offpos = new_addr - old_addr; | 3864 | ptrdiff_t offpos = new_addr - old_addr; |
3861 | for (int i = 0; i < TAG_COUNT; i++) | 3865 | for (int i = 0; i < TAG_COUNT; i++) |
3862 | ramcache_hdr->tags[i] += offpos; | 3866 | tcramcache.hdr->tags[i] += offpos; |
3863 | } | 3867 | } |
3864 | 3868 | ||
3865 | static int move_cb(int handle, void* current, void* new) | 3869 | static int move_cb(int handle, void* current, void* new) |
3866 | { | 3870 | { |
3867 | (void)handle; | 3871 | if (tcramcache.move_lock > 0) |
3868 | if (move_lock > 0) | ||
3869 | return BUFLIB_CB_CANNOT_MOVE; | 3872 | return BUFLIB_CB_CANNOT_MOVE; |
3870 | 3873 | ||
3871 | fix_ramcache(current, new); | 3874 | fix_ramcache(current, new); |
3872 | ramcache_hdr = new; | 3875 | tcramcache.hdr = new; |
3873 | return BUFLIB_CB_OK; | 3876 | return BUFLIB_CB_OK; |
3877 | (void)handle; | ||
3874 | } | 3878 | } |
3875 | 3879 | ||
3876 | static struct buflib_callbacks ops = { | 3880 | static struct buflib_callbacks ops = { |
@@ -3880,13 +3884,12 @@ static struct buflib_callbacks ops = { | |||
3880 | 3884 | ||
3881 | static bool allocate_tagcache(void) | 3885 | static bool allocate_tagcache(void) |
3882 | { | 3886 | { |
3883 | struct master_header tcmh; | ||
3884 | int fd; | ||
3885 | |||
3886 | /* Load the header. */ | 3887 | /* Load the header. */ |
3887 | if ( (fd = open_master_fd(&tcmh, false)) < 0) | 3888 | struct master_header tcmh; |
3889 | int fd = open_master_fd(&tcmh, false); | ||
3890 | if (fd < 0) | ||
3888 | { | 3891 | { |
3889 | ramcache_hdr = NULL; | 3892 | tcramcache.hdr = NULL; |
3890 | return false; | 3893 | return false; |
3891 | } | 3894 | } |
3892 | 3895 | ||
@@ -3896,22 +3899,37 @@ static bool allocate_tagcache(void) | |||
3896 | * Now calculate the required cache size plus | 3899 | * Now calculate the required cache size plus |
3897 | * some extra space for alignment fixes. | 3900 | * some extra space for alignment fixes. |
3898 | */ | 3901 | */ |
3899 | tc_stat.ramcache_allocated = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + | 3902 | tc_stat.ramcache_allocated = 0; |
3903 | |||
3904 | size_t alloc_size = tcmh.tch.datasize + 256 + TAGCACHE_RESERVE + | ||
3900 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); | 3905 | sizeof(struct ramcache_header) + TAG_COUNT*sizeof(void *); |
3901 | int handle = core_alloc_ex("tc ramcache", tc_stat.ramcache_allocated, &ops); | 3906 | #ifdef HAVE_DIRCACHE |
3902 | ramcache_hdr = core_get_data(handle); | 3907 | alloc_size += tcmh.tch.entry_count*sizeof(struct dircache_fileref); |
3903 | memset(ramcache_hdr, 0, sizeof(struct ramcache_header)); | 3908 | #endif |
3909 | |||
3910 | int handle = core_alloc_ex("tc ramcache", alloc_size, &ops); | ||
3911 | if (handle <= 0) | ||
3912 | return false; | ||
3913 | |||
3914 | void *data = core_get_data(handle); | ||
3915 | |||
3916 | tcramcache.hdr = data; | ||
3917 | tc_stat.ramcache_allocated = alloc_size; | ||
3918 | |||
3919 | memset(tcramcache.hdr, 0, sizeof(struct ramcache_header)); | ||
3904 | memcpy(¤t_tcmh, &tcmh, sizeof current_tcmh); | 3920 | memcpy(¤t_tcmh, &tcmh, sizeof current_tcmh); |
3905 | logf("tagcache: %d bytes allocated.", tc_stat.ramcache_allocated); | 3921 | logf("tagcache: %lu bytes allocated.", tc_stat.ramcache_allocated); |
3906 | 3922 | ||
3907 | return true; | 3923 | return true; |
3908 | } | 3924 | } |
3909 | 3925 | ||
3910 | # ifdef HAVE_EEPROM_SETTINGS | 3926 | #ifdef HAVE_EEPROM_SETTINGS |
3911 | static bool tagcache_dumpload(void) | 3927 | static bool tagcache_dumpload(void) |
3912 | { | 3928 | { |
3913 | struct statefile_header shdr; | 3929 | struct statefile_header shdr; |
3914 | int fd, rc, handle; | 3930 | int fd, rc, handle; |
3931 | |||
3932 | tcramcache.hdr = NULL; | ||
3915 | 3933 | ||
3916 | fd = open(TAGCACHE_STATEFILE, O_RDONLY); | 3934 | fd = open(TAGCACHE_STATEFILE, O_RDONLY); |
3917 | if (fd < 0) | 3935 | if (fd < 0) |
@@ -3927,31 +3945,36 @@ static bool tagcache_dumpload(void) | |||
3927 | || shdr.mh.tch.magic != TAGCACHE_MAGIC) | 3945 | || shdr.mh.tch.magic != TAGCACHE_MAGIC) |
3928 | { | 3946 | { |
3929 | logf("incorrect statefile"); | 3947 | logf("incorrect statefile"); |
3930 | ramcache_hdr = NULL; | ||
3931 | close(fd); | 3948 | close(fd); |
3932 | return false; | 3949 | return false; |
3933 | } | 3950 | } |
3934 | 3951 | ||
3935 | |||
3936 | /* Lets allocate real memory and load it */ | 3952 | /* Lets allocate real memory and load it */ |
3937 | handle = core_alloc_ex("tc ramcache", shdr.tc_stat.ramcache_allocated, &ops); | 3953 | handle = core_alloc_ex("tc ramcache", shdr.tc_stat.ramcache_allocated, &ops); |
3938 | ramcache_hdr = core_get_data(handle); | 3954 | if (handle <= 0) |
3939 | move_lock++; | 3955 | { |
3940 | rc = read(fd, ramcache_hdr, shdr.tc_stat.ramcache_allocated); | 3956 | logf("alloc failure"); |
3941 | move_lock--; | 3957 | return false; |
3958 | } | ||
3959 | |||
3960 | tcrc_buffer_lock(); | ||
3961 | tcramcache.hdr = core_get_data(handle); | ||
3962 | rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated); | ||
3963 | tcrc_buffer_unlock(); | ||
3964 | |||
3942 | close(fd); | 3965 | close(fd); |
3943 | 3966 | ||
3944 | if (rc != shdr.tc_stat.ramcache_allocated) | 3967 | if (rc != shdr.tc_stat.ramcache_allocated) |
3945 | { | 3968 | { |
3946 | logf("read failure!"); | 3969 | logf("read failure!"); |
3947 | ramcache_hdr = NULL; | 3970 | core_free(handle); |
3948 | return false; | 3971 | return false; |
3949 | } | 3972 | } |
3950 | 3973 | ||
3951 | memcpy(&tc_stat, &shdr.tc_stat, sizeof(struct tagcache_stat)); | 3974 | tc_stat = shdr.tc_stat; |
3952 | 3975 | ||
3953 | /* Now fix the pointers */ | 3976 | /* Now fix the pointers */ |
3954 | fix_ramcache(shdr.hdr, ramcache_hdr); | 3977 | fix_ramcache(shdr.hdr, tcramcache.hdr); |
3955 | 3978 | ||
3956 | /* Load the tagcache master header (should match the actual DB file header). */ | 3979 | /* Load the tagcache master header (should match the actual DB file header). */ |
3957 | memcpy(¤t_tcmh, &shdr.mh, sizeof current_tcmh); | 3980 | memcpy(¤t_tcmh, &shdr.mh, sizeof current_tcmh); |
@@ -3976,63 +3999,62 @@ static bool tagcache_dumpsave(void) | |||
3976 | 3999 | ||
3977 | /* Create the header */ | 4000 | /* Create the header */ |
3978 | shdr.magic = TAGCACHE_STATEFILE_MAGIC; | 4001 | shdr.magic = TAGCACHE_STATEFILE_MAGIC; |
3979 | shdr.hdr = ramcache_hdr; | 4002 | shdr.hdr = tcramcache.hdr; |
3980 | memcpy(&shdr.mh, ¤t_tcmh, sizeof current_tcmh); | 4003 | memcpy(&shdr.mh, ¤t_tcmh, sizeof current_tcmh); |
3981 | memcpy(&shdr.tc_stat, &tc_stat, sizeof tc_stat); | 4004 | memcpy(&shdr.tc_stat, &tc_stat, sizeof tc_stat); |
3982 | write(fd, &shdr, sizeof shdr); | 4005 | write(fd, &shdr, sizeof shdr); |
3983 | 4006 | ||
3984 | /* And dump the data too */ | 4007 | /* And dump the data too */ |
3985 | move_lock++; | 4008 | tcrc_buffer_lock(); |
3986 | write(fd, ramcache_hdr, tc_stat.ramcache_allocated); | 4009 | write(fd, tcramcache.hdr, tc_stat.ramcache_allocated); |
3987 | move_lock--; | 4010 | tcrc_buffer_unlock(); |
3988 | close(fd); | 4011 | close(fd); |
3989 | 4012 | ||
3990 | return true; | 4013 | return true; |
3991 | } | 4014 | } |
3992 | # endif | 4015 | #endif /* HAVE_EEPROM_SETTINGS */ |
3993 | 4016 | ||
3994 | static bool load_tagcache(void) | 4017 | static bool load_tagcache(void) |
3995 | { | 4018 | { |
3996 | struct tagcache_header *tch; | 4019 | /* DEBUG: After tagcache commit and dircache rebuild, hdr-sturcture |
3997 | struct master_header tcmh; | 4020 | * may become corrupt. */ |
3998 | long bytesleft = tc_stat.ramcache_allocated - sizeof(struct ramcache_header); | 4021 | |
3999 | struct index_entry *idx; | 4022 | bool const auto_update = global_settings.tagcache_autoupdate; |
4000 | int rc, fd; | 4023 | |
4001 | char *p; | 4024 | bool ok = false; |
4002 | int i, tag; | 4025 | ssize_t bytesleft = tc_stat.ramcache_allocated - sizeof(struct ramcache_header); |
4003 | 4026 | int fd; | |
4004 | # ifdef HAVE_DIRCACHE | 4027 | |
4005 | while (dircache_is_initializing()) | 4028 | #ifdef HAVE_DIRCACHE |
4006 | sleep(1); | 4029 | /* Wait for any in-progress dircache build to complete */ |
4030 | dircache_wait(); | ||
4031 | #endif /* HAVE_DIRCACHE */ | ||
4007 | 4032 | ||
4008 | dircache_set_appflag(DIRCACHE_APPFLAG_TAGCACHE); | ||
4009 | # endif | ||
4010 | |||
4011 | logf("loading tagcache to ram..."); | 4033 | logf("loading tagcache to ram..."); |
4012 | 4034 | ||
4013 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); | 4035 | fd = open(TAGCACHE_FILE_MASTER, O_RDONLY); |
4014 | if (fd < 0) | 4036 | if (fd < 0) |
4015 | { | 4037 | { |
4016 | logf("tagcache open failed"); | 4038 | logf("tagcache open failed"); |
4017 | return false; | 4039 | goto failure; |
4018 | } | 4040 | } |
4019 | 4041 | ||
4042 | tcrc_buffer_lock(); /* lock for the rest of the scan, simpler to handle */ | ||
4043 | |||
4044 | struct master_header tcmh; | ||
4020 | if (ecread(fd, &tcmh, 1, master_header_ec, tc_stat.econ) | 4045 | if (ecread(fd, &tcmh, 1, master_header_ec, tc_stat.econ) |
4021 | != sizeof(struct master_header) | 4046 | != sizeof(struct master_header) |
4022 | || tcmh.tch.magic != TAGCACHE_MAGIC) | 4047 | || tcmh.tch.magic != TAGCACHE_MAGIC) |
4023 | { | 4048 | { |
4024 | logf("incorrect header"); | 4049 | logf("incorrect header"); |
4025 | return false; | 4050 | goto failure; |
4026 | } | 4051 | } |
4027 | 4052 | ||
4028 | /* Master header copy should already match, this can be redundant to do. */ | 4053 | /* Master header copy should already match, this can be redundant to do. */ |
4029 | memcpy(¤t_tcmh, &tcmh, sizeof current_tcmh); | 4054 | current_tcmh = tcmh; |
4030 | |||
4031 | move_lock++; /* lock for the reset of the scan, simpler to handle */ | ||
4032 | idx = ramcache_hdr->indices; | ||
4033 | 4055 | ||
4034 | /* Load the master index table. */ | 4056 | /* Load the master index table. */ |
4035 | for (i = 0; i < tcmh.tch.entry_count; i++) | 4057 | for (int i = 0; i < tcmh.tch.entry_count; i++) |
4036 | { | 4058 | { |
4037 | bytesleft -= sizeof(struct index_entry); | 4059 | bytesleft -= sizeof(struct index_entry); |
4038 | if (bytesleft < 0) | 4060 | if (bytesleft < 0) |
@@ -4041,142 +4063,157 @@ static bool load_tagcache(void) | |||
4041 | goto failure; | 4063 | goto failure; |
4042 | } | 4064 | } |
4043 | 4065 | ||
4044 | /* DEBUG: After tagcache commit and dircache rebuild, hdr-sturcture | 4066 | int rc = ecread_index_entry(fd, &tcramcache.hdr->indices[i]); |
4045 | * may become corrupt. */ | 4067 | if (rc != sizeof (struct index_entry)) |
4046 | rc = ecread_index_entry(fd, idx); | ||
4047 | if (rc != sizeof(struct index_entry)) | ||
4048 | { | 4068 | { |
4049 | logf("read error #10"); | 4069 | logf("read error #10"); |
4050 | goto failure; | 4070 | goto failure; |
4051 | } | 4071 | } |
4052 | |||
4053 | idx++; | ||
4054 | } | 4072 | } |
4055 | 4073 | ||
4056 | close(fd); | 4074 | close(fd); |
4075 | fd = -1; | ||
4057 | 4076 | ||
4058 | /* Load the tags. */ | 4077 | /* Load the tags right after the index entries */ |
4059 | p = (char *)idx; | 4078 | char *p = (char *)&tcramcache.hdr->indices[tcmh.tch.entry_count]; |
4060 | for (tag = 0; tag < TAG_COUNT; tag++) | 4079 | |
4080 | for (int tag = 0; tag < TAG_COUNT; tag++) | ||
4061 | { | 4081 | { |
4062 | struct tagfile_entry *fe; | 4082 | ssize_t rc; |
4063 | char buf[TAG_MAXLEN+32]; | ||
4064 | 4083 | ||
4065 | if (TAGCACHE_IS_NUMERIC(tag)) | 4084 | if (TAGCACHE_IS_NUMERIC(tag)) |
4066 | continue ; | 4085 | continue; |
4067 | 4086 | ||
4068 | //p = ((void *)p+1); | 4087 | p = TC_ALIGN_PTR(p, &rc); |
4069 | p = (char *)((long)p & ~0x03) + 0x04; | 4088 | bytesleft -= rc; |
4070 | ramcache_hdr->tags[tag] = p; | 4089 | if (bytesleft <= 0) |
4090 | { | ||
4091 | logf("Too big tagcache #10.5"); | ||
4092 | goto failure; | ||
4093 | } | ||
4094 | |||
4095 | tcramcache.hdr->tags[tag] = p; | ||
4071 | 4096 | ||
4072 | /* Check the header. */ | 4097 | /* Load the header */ |
4073 | tch = (struct tagcache_header *)p; | 4098 | struct tagcache_header *tch = (struct tagcache_header *)p; |
4074 | p += sizeof(struct tagcache_header); | 4099 | p += sizeof(struct tagcache_header); |
4075 | 4100 | bytesleft -= sizeof (struct tagcache_header); | |
4076 | if ( (fd = open_tag_fd(tch, tag, false)) < 0) | 4101 | |
4077 | goto failure_nofd; | 4102 | fd = open_tag_fd(tch, tag, false); |
4078 | 4103 | if (rc < 0) | |
4079 | for (ramcache_hdr->entry_count[tag] = 0; | 4104 | goto failure; |
4080 | ramcache_hdr->entry_count[tag] < tch->entry_count; | 4105 | |
4081 | ramcache_hdr->entry_count[tag]++) | 4106 | /* Load the entries for this tag */ |
4107 | for (tcramcache.hdr->entry_count[tag] = 0; | ||
4108 | tcramcache.hdr->entry_count[tag] < tch->entry_count; | ||
4109 | tcramcache.hdr->entry_count[tag]++) | ||
4082 | { | 4110 | { |
4083 | long pos; | 4111 | /* Abort if we got a critical event in queue */ |
4084 | 4112 | if (do_timed_yield() && check_event_queue()) | |
4085 | if (do_timed_yield()) | 4113 | goto failure; |
4114 | |||
4115 | p = TC_ALIGN_PTR(p, &rc); | ||
4116 | bytesleft -= rc; | ||
4117 | if (bytesleft <= 0) | ||
4086 | { | 4118 | { |
4087 | /* Abort if we got a critical event in queue */ | 4119 | logf("Too big tagcache #10.75"); |
4088 | if (check_event_queue()) | 4120 | goto failure; |
4089 | goto failure; | 4121 | } |
4122 | |||
4123 | if (bytesleft < (ssize_t)sizeof (struct tagfile_entry)) | ||
4124 | { | ||
4125 | logf("Too big tagcache #10.875"); | ||
4126 | goto failure; | ||
4090 | } | 4127 | } |
4091 | 4128 | ||
4092 | fe = (struct tagfile_entry *)p; | 4129 | struct tagfile_entry *fe = (struct tagfile_entry *)p; |
4093 | pos = lseek(fd, 0, SEEK_CUR); | 4130 | off_t pos = lseek(fd, 0, SEEK_CUR); |
4094 | rc = ecread_tagfile_entry(fd, fe); | 4131 | |
4095 | if (rc != sizeof(struct tagfile_entry)) | 4132 | /* Load the header for the tag itself */ |
4133 | if (ecread_tagfile_entry(fd, fe) != sizeof(struct tagfile_entry)) | ||
4096 | { | 4134 | { |
4097 | /* End of lookup table. */ | 4135 | /* End of lookup table. */ |
4098 | logf("read error #11"); | 4136 | logf("read error #11"); |
4099 | goto failure; | 4137 | goto failure; |
4100 | } | 4138 | } |
4101 | 4139 | ||
4102 | /* We have a special handling for the filename tags. */ | 4140 | /* We have a special handling for the filename tags; neither the |
4141 | paths nor the entry headers are stored; only the tagcache header | ||
4142 | and dircache references are. */ | ||
4103 | if (tag == tag_filename) | 4143 | if (tag == tag_filename) |
4104 | { | 4144 | { |
4105 | # ifdef HAVE_DIRCACHE | 4145 | int idx_id = fe->idx_id; /* gonna clobber tagfile entry */ |
4106 | int dc; | 4146 | struct index_entry *idx = &tcramcache.hdr->indices[idx_id]; |
4107 | # endif | 4147 | |
4108 | 4148 | #ifdef HAVE_DIRCACHE | |
4109 | idx = &ramcache_hdr->indices[fe->idx_id]; | ||
4110 | |||
4111 | if (fe->tag_length >= (long)sizeof(buf)-1) | ||
4112 | { | ||
4113 | read(fd, buf, 10); | ||
4114 | buf[10] = '\0'; | ||
4115 | logf("TAG:%s", buf); | ||
4116 | logf("too long filename"); | ||
4117 | goto failure; | ||
4118 | } | ||
4119 | |||
4120 | rc = read(fd, buf, fe->tag_length); | ||
4121 | if (rc != fe->tag_length) | ||
4122 | { | ||
4123 | logf("read error #12"); | ||
4124 | goto failure; | ||
4125 | } | ||
4126 | |||
4127 | /* Check if the entry has already been removed */ | ||
4128 | if (idx->flag & FLAG_DELETED) | ||
4129 | continue; | ||
4130 | |||
4131 | /* This flag must not be used yet. */ | ||
4132 | if (idx->flag & FLAG_DIRCACHE) | 4149 | if (idx->flag & FLAG_DIRCACHE) |
4133 | { | 4150 | { |
4151 | /* This flag must not be used yet. */ | ||
4134 | logf("internal error!"); | 4152 | logf("internal error!"); |
4135 | goto failure; | 4153 | goto failure; |
4136 | } | 4154 | } |
4137 | 4155 | ||
4156 | p += sizeof (struct dircache_fileref); | ||
4157 | bytesleft -= sizeof (struct dircache_fileref); | ||
4158 | #endif /* HAVE_DIRCACHE */ | ||
4159 | |||
4138 | if (idx->tag_seek[tag] != pos) | 4160 | if (idx->tag_seek[tag] != pos) |
4139 | { | 4161 | { |
4140 | logf("corrupt data structures!"); | 4162 | logf("corrupt data structures!"); |
4141 | goto failure; | 4163 | goto failure; |
4142 | } | 4164 | } |
4143 | 4165 | ||
4144 | if (global_settings.tagcache_autoupdate) | 4166 | char filename[TAG_MAXLEN+32]; |
4167 | if (fe->tag_length >= (long)sizeof(filename)-1) | ||
4145 | { | 4168 | { |
4146 | /* Check if entry has been removed. */ | 4169 | read(fd, filename, 10); |
4147 | #ifdef HAVE_DIRCACHE | 4170 | filename[10] = '\0'; |
4148 | /* This will be very slow unless dircache is enabled | 4171 | logf("TAG:%s", filename); |
4149 | or target is flash based. */ | 4172 | logf("too long filename"); |
4150 | ################## | 4173 | goto failure; |
4151 | if (dircache_search( /* will get this! -- jethead71 */ | 4174 | } |
4152 | dc = dircache_get_entry_id(buf); | 4175 | |
4153 | if (dc < 0) | 4176 | if ((idx->flag & FLAG_DELETED) IFN_DIRCACHE( || !auto_update )) |
4177 | { | ||
4178 | if (lseek(fd, fe->tag_length, SEEK_CUR) < 0) | ||
4154 | { | 4179 | { |
4155 | logf("Entry no longer valid."); | 4180 | logf("read error #11.5"); |
4156 | logf("-> %s", buf); | 4181 | goto failure; |
4157 | if (global_settings.tagcache_autoupdate) | ||
4158 | delete_entry(fe->idx_id); | ||
4159 | continue ; | ||
4160 | } | 4182 | } |
4183 | } | ||
4184 | |||
4185 | if (read(fd, filename, fe->tag_length) != fe->tag_length) | ||
4186 | { | ||
4187 | logf("read error #12"); | ||
4188 | goto failure; | ||
4189 | } | ||
4190 | |||
4191 | #ifdef HAVE_DIRCACHE | ||
4192 | /* If auto updating, check storage too, otherwise simply | ||
4193 | attempt to load cache references */ | ||
4194 | unsigned int searchflag = auto_update ? DCS_STORAGE_PATH : | ||
4195 | DCS_CACHED_PATH; | ||
4161 | 4196 | ||
4197 | int rc = dircache_search(searchflag | DCS_UPDATE_FILEREF, | ||
4198 | &tcrc_dcfrefs[idx_id], filename); | ||
4199 | if (rc > 0) /* in cache and we have fileref */ | ||
4162 | idx->flag |= FLAG_DIRCACHE; | 4200 | idx->flag |= FLAG_DIRCACHE; |
4163 | idx->tag_seek[tag_filename] = dc; | 4201 | else if (rc == 0) /* not in cache but okay */ |
4164 | #else /* ndef HAVE_DIRCACHE */ | 4202 | ; |
4165 | /* This will be very slow unless target is flash based; | 4203 | else if (auto_update) |
4166 | do it anyway for consistency. */ | 4204 | #else /* ndef HAVE_DIRCACHE */ |
4167 | if (!file_exists(buf)) | 4205 | /* Check if path is no longer valid */ |
4168 | { | 4206 | if (auto_update && !file_exists(filename)) |
4169 | logf("Entry no longer valid."); | 4207 | #endif /* HAVE_DIRCACHE */ |
4170 | logf("-> %s", buf); | 4208 | { |
4171 | delete_entry(fe->idx_id); | 4209 | logf("Entry no longer valid."); |
4172 | continue; | 4210 | logf("-> %s", filename); |
4173 | } | 4211 | delete_entry(idx_id); |
4174 | #endif /* HAVE_DIRCACHE */ | ||
4175 | } | 4212 | } |
4176 | 4213 | ||
4177 | continue ; | 4214 | continue; |
4178 | } | 4215 | } |
4179 | 4216 | ||
4180 | bytesleft -= sizeof(struct tagfile_entry) + fe->tag_length; | 4217 | bytesleft -= sizeof(struct tagfile_entry) + fe->tag_length; |
4181 | if (bytesleft < 0) | 4218 | if (bytesleft < 0) |
4182 | { | 4219 | { |
@@ -4187,7 +4224,7 @@ static bool load_tagcache(void) | |||
4187 | } | 4224 | } |
4188 | 4225 | ||
4189 | p = fe->tag_data; | 4226 | p = fe->tag_data; |
4190 | rc = read(fd, fe->tag_data, fe->tag_length); | 4227 | rc = read(fd, p, fe->tag_length); |
4191 | p += rc; | 4228 | p += rc; |
4192 | 4229 | ||
4193 | if (rc != fe->tag_length) | 4230 | if (rc != fe->tag_length) |
@@ -4200,20 +4237,27 @@ static bool load_tagcache(void) | |||
4200 | goto failure; | 4237 | goto failure; |
4201 | } | 4238 | } |
4202 | } | 4239 | } |
4240 | |||
4241 | #ifdef HAVE_DIRCACHE | ||
4242 | if (tag == tag_filename) | ||
4243 | p = (char *)&tcrc_dcfrefs[tcmh.tch.entry_count]; | ||
4244 | #endif /* HAVE_DIRCACHE */ | ||
4245 | |||
4203 | close(fd); | 4246 | close(fd); |
4204 | } | 4247 | } |
4205 | 4248 | ||
4206 | tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft; | 4249 | tc_stat.ramcache_used = tc_stat.ramcache_allocated - bytesleft; |
4207 | logf("tagcache loaded into ram!"); | 4250 | logf("tagcache loaded into ram!"); |
4251 | logf("utilization: %d%%", 100*tc_stat.ramcache_used / tc_stat.ramcache_allocated); | ||
4208 | 4252 | ||
4209 | move_lock--; | 4253 | ok = true; |
4210 | return true; | ||
4211 | 4254 | ||
4212 | failure: | 4255 | failure: |
4213 | close(fd); | 4256 | if (fd >= 0) |
4214 | failure_nofd: | 4257 | close(fd); |
4215 | move_lock--; | 4258 | |
4216 | return false; | 4259 | tcrc_buffer_unlock(); |
4260 | return ok; | ||
4217 | } | 4261 | } |
4218 | #endif /* HAVE_TC_RAMCACHE */ | 4262 | #endif /* HAVE_TC_RAMCACHE */ |
4219 | 4263 | ||
@@ -4235,10 +4279,7 @@ static bool check_deleted_files(void) | |||
4235 | 4279 | ||
4236 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | 4280 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); |
4237 | while (ecread_tagfile_entry(fd, &tfe) == sizeof(struct tagfile_entry) | 4281 | while (ecread_tagfile_entry(fd, &tfe) == sizeof(struct tagfile_entry) |
4238 | #ifndef __PCTOOL__ | 4282 | && !check_event_queue()) |
4239 | && !check_event_queue() | ||
4240 | #endif | ||
4241 | ) | ||
4242 | { | 4283 | { |
4243 | if (tfe.tag_length >= (long)sizeof(buf)-1) | 4284 | if (tfe.tag_length >= (long)sizeof(buf)-1) |
4244 | { | 4285 | { |
@@ -4278,7 +4319,7 @@ static bool check_deleted_files(void) | |||
4278 | /* Note that this function must not be inlined, otherwise the whole point | 4319 | /* Note that this function must not be inlined, otherwise the whole point |
4279 | * of having the code in a separate function is lost. | 4320 | * of having the code in a separate function is lost. |
4280 | */ | 4321 | */ |
4281 | static void __attribute__ ((noinline)) check_ignore(const char *dirname, | 4322 | static void NO_INLINE check_ignore(const char *dirname, |
4282 | int *ignore, int *unignore) | 4323 | int *ignore, int *unignore) |
4283 | { | 4324 | { |
4284 | char newpath[MAX_PATH]; | 4325 | char newpath[MAX_PATH]; |
@@ -4408,18 +4449,17 @@ static int free_search_roots(struct search_roots_ll * start) | |||
4408 | 4449 | ||
4409 | static bool check_dir(const char *dirname, int add_files) | 4450 | static bool check_dir(const char *dirname, int add_files) |
4410 | { | 4451 | { |
4411 | DIR *dir; | ||
4412 | int len; | ||
4413 | int success = false; | 4452 | int success = false; |
4414 | int ignore, unignore; | ||
4415 | 4453 | ||
4416 | dir = opendir(dirname); | 4454 | DIR *dir = opendir(dirname); |
4417 | if (!dir) | 4455 | if (!dir) |
4418 | { | 4456 | { |
4419 | logf("tagcache: opendir(%s) failed", dirname); | 4457 | logf("tagcache: opendir(%s) failed", dirname); |
4420 | return false; | 4458 | return false; |
4421 | } | 4459 | } |
4460 | |||
4422 | /* check for a database.ignore and database.unignore */ | 4461 | /* check for a database.ignore and database.unignore */ |
4462 | int ignore, unignore; | ||
4423 | check_ignore(dirname, &ignore, &unignore); | 4463 | check_ignore(dirname, &ignore, &unignore); |
4424 | 4464 | ||
4425 | /* don't do anything if both ignore and unignore are there */ | 4465 | /* don't do anything if both ignore and unignore are there */ |
@@ -4427,11 +4467,7 @@ static bool check_dir(const char *dirname, int add_files) | |||
4427 | add_files = unignore; | 4467 | add_files = unignore; |
4428 | 4468 | ||
4429 | /* Recursively scan the dir. */ | 4469 | /* Recursively scan the dir. */ |
4430 | #ifdef __PCTOOL__ | ||
4431 | while (1) | ||
4432 | #else | ||
4433 | while (!check_event_queue()) | 4470 | while (!check_event_queue()) |
4434 | #endif | ||
4435 | { | 4471 | { |
4436 | struct dirent *entry = readdir(dir); | 4472 | struct dirent *entry = readdir(dir); |
4437 | if (entry == NULL) | 4473 | if (entry == NULL) |
@@ -4440,42 +4476,32 @@ static bool check_dir(const char *dirname, int add_files) | |||
4440 | break; | 4476 | break; |
4441 | } | 4477 | } |
4442 | 4478 | ||
4443 | if (!strcmp((char *)entry->d_name, ".") || | 4479 | if (is_dotdir_name(entry->d_name)) |
4444 | !strcmp((char *)entry->d_name, "..")) | ||
4445 | continue; | 4480 | continue; |
4446 | 4481 | ||
4447 | struct dirinfo info = dir_get_info(dir, entry); | 4482 | struct dirinfo info = dir_get_info(dir, entry); |
4448 | 4483 | size_t len = strlen(curpath); | |
4449 | yield(); | 4484 | path_append(&curpath[len], PA_SEP_HARD, entry->d_name, |
4450 | 4485 | sizeof (curpath) - len); | |
4451 | len = strlen(curpath); | ||
4452 | /* don't add an extra / for curpath == / */ | ||
4453 | if (len <= 1) len = 0; | ||
4454 | snprintf(&curpath[len], sizeof(curpath) - len, "/%s", entry->d_name); | ||
4455 | 4486 | ||
4456 | processed_dir_count++; | 4487 | processed_dir_count++; |
4457 | if (info.attribute & ATTR_DIRECTORY) | 4488 | if (info.attribute & ATTR_DIRECTORY) |
4489 | { | ||
4458 | #ifndef SIMULATOR | 4490 | #ifndef SIMULATOR |
4459 | { /* don't follow symlinks to dirs, but try to add it as a search root | 4491 | /* don't follow symlinks to dirs, but try to add it as a search root |
4460 | * this makes able to avoid looping in recursive symlinks */ | 4492 | * this makes able to avoid looping in recursive symlinks */ |
4461 | if (info.attribute & ATTR_LINK) | 4493 | if (info.attribute & ATTR_LINK) |
4462 | add_search_root(curpath); | 4494 | add_search_root(curpath); |
4463 | else | 4495 | else |
4496 | #endif /* SIMULATOR */ | ||
4464 | check_dir(curpath, add_files); | 4497 | check_dir(curpath, add_files); |
4465 | } | 4498 | } |
4466 | #else | ||
4467 | check_dir(curpath, add_files); | ||
4468 | #endif | ||
4469 | else if (add_files) | 4499 | else if (add_files) |
4470 | { | 4500 | { |
4471 | tc_stat.curentry = curpath; | 4501 | tc_stat.curentry = curpath; |
4472 | 4502 | ||
4473 | /* Add a new entry to the temporary db file. */ | 4503 | /* Add a new entry to the temporary db file. */ |
4474 | add_tagcache(curpath, info.mtime | 4504 | add_tagcache(curpath, info.mtime); |
4475 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | ||
4476 | , dir->internal_entry | ||
4477 | #endif | ||
4478 | ); | ||
4479 | 4505 | ||
4480 | /* Wait until current path for debug screen is read and unset. */ | 4506 | /* Wait until current path for debug screen is read and unset. */ |
4481 | while (tc_stat.syncscreen && tc_stat.curentry != NULL) | 4507 | while (tc_stat.syncscreen && tc_stat.curentry != NULL) |
@@ -4517,8 +4543,7 @@ void do_tagcache_build(const char *path[]) | |||
4517 | processed_dir_count = 0; | 4543 | processed_dir_count = 0; |
4518 | 4544 | ||
4519 | #ifdef HAVE_DIRCACHE | 4545 | #ifdef HAVE_DIRCACHE |
4520 | while (dircache_is_initializing()) | 4546 | dircache_wait(); |
4521 | sleep(1); | ||
4522 | #endif | 4547 | #endif |
4523 | 4548 | ||
4524 | logf("updating tagcache"); | 4549 | logf("updating tagcache"); |
@@ -4606,7 +4631,7 @@ void do_tagcache_build(const char *path[]) | |||
4606 | #endif | 4631 | #endif |
4607 | 4632 | ||
4608 | #ifdef HAVE_TC_RAMCACHE | 4633 | #ifdef HAVE_TC_RAMCACHE |
4609 | if (ramcache_hdr) | 4634 | if (tcramcache.hdr) |
4610 | { | 4635 | { |
4611 | /* Import runtime statistics if we just initialized the db. */ | 4636 | /* Import runtime statistics if we just initialized the db. */ |
4612 | if (current_tcmh.serial == 0) | 4637 | if (current_tcmh.serial == 0) |
@@ -4629,12 +4654,12 @@ void tagcache_build(void) | |||
4629 | 4654 | ||
4630 | do_tagcache_build((const char**)vect); | 4655 | do_tagcache_build((const char**)vect); |
4631 | } | 4656 | } |
4632 | #endif | 4657 | #endif /* __PCTOOL__ */ |
4633 | 4658 | ||
4634 | #ifdef HAVE_TC_RAMCACHE | 4659 | #ifdef HAVE_TC_RAMCACHE |
4635 | static void load_ramcache(void) | 4660 | static void load_ramcache(void) |
4636 | { | 4661 | { |
4637 | if (!ramcache_hdr) | 4662 | if (!tcramcache.hdr) |
4638 | return ; | 4663 | return ; |
4639 | 4664 | ||
4640 | cpu_boost(true); | 4665 | cpu_boost(true); |
@@ -4647,7 +4672,7 @@ static void load_ramcache(void) | |||
4647 | /* If loading failed, it must indicate some problem with the db | 4672 | /* If loading failed, it must indicate some problem with the db |
4648 | * so disable it entirely to prevent further issues. */ | 4673 | * so disable it entirely to prevent further issues. */ |
4649 | tc_stat.ready = false; | 4674 | tc_stat.ready = false; |
4650 | ramcache_hdr = NULL; | 4675 | tcramcache.hdr = NULL; |
4651 | } | 4676 | } |
4652 | 4677 | ||
4653 | cpu_boost(false); | 4678 | cpu_boost(false); |
@@ -4659,7 +4684,7 @@ void tagcache_unload_ramcache(void) | |||
4659 | /* Just to make sure there is no statefile present. */ | 4684 | /* Just to make sure there is no statefile present. */ |
4660 | // remove(TAGCACHE_STATEFILE); | 4685 | // remove(TAGCACHE_STATEFILE); |
4661 | } | 4686 | } |
4662 | #endif | 4687 | #endif /* HAVE_TC_RAMCACHE */ |
4663 | 4688 | ||
4664 | #ifndef __PCTOOL__ | 4689 | #ifndef __PCTOOL__ |
4665 | static void tagcache_thread(void) | 4690 | static void tagcache_thread(void) |
@@ -4675,7 +4700,7 @@ static void tagcache_thread(void) | |||
4675 | free_tempbuf(); | 4700 | free_tempbuf(); |
4676 | 4701 | ||
4677 | #ifdef HAVE_TC_RAMCACHE | 4702 | #ifdef HAVE_TC_RAMCACHE |
4678 | # ifdef HAVE_EEPROM_SETTINGS | 4703 | #ifdef HAVE_EEPROM_SETTINGS |
4679 | if (firmware_settings.initialized && firmware_settings.disk_clean | 4704 | if (firmware_settings.initialized && firmware_settings.disk_clean |
4680 | && global_settings.tagcache_ram) | 4705 | && global_settings.tagcache_ram) |
4681 | { | 4706 | { |
@@ -4683,12 +4708,12 @@ static void tagcache_thread(void) | |||
4683 | } | 4708 | } |
4684 | 4709 | ||
4685 | remove(TAGCACHE_STATEFILE); | 4710 | remove(TAGCACHE_STATEFILE); |
4686 | # endif | 4711 | #endif /* HAVE_EEPROM_SETTINGS */ |
4687 | 4712 | ||
4688 | /* Allocate space for the tagcache if found on disk. */ | 4713 | /* Allocate space for the tagcache if found on disk. */ |
4689 | if (global_settings.tagcache_ram && !tc_stat.ramcache) | 4714 | if (global_settings.tagcache_ram && !tc_stat.ramcache) |
4690 | allocate_tagcache(); | 4715 | allocate_tagcache(); |
4691 | #endif | 4716 | #endif /* HAVE_TC_RAMCACHE */ |
4692 | 4717 | ||
4693 | cpu_boost(false); | 4718 | cpu_boost(false); |
4694 | tc_stat.initialized = true; | 4719 | tc_stat.initialized = true; |
@@ -4741,7 +4766,7 @@ static void tagcache_thread(void) | |||
4741 | tagcache_build(); | 4766 | tagcache_build(); |
4742 | } | 4767 | } |
4743 | else | 4768 | else |
4744 | #endif | 4769 | #endif /* HAVE_RC_RAMCACHE */ |
4745 | if (global_settings.tagcache_autoupdate) | 4770 | if (global_settings.tagcache_autoupdate) |
4746 | { | 4771 | { |
4747 | tagcache_build(); | 4772 | tagcache_build(); |
@@ -4800,23 +4825,29 @@ static int get_progress(void) | |||
4800 | int total_count = -1; | 4825 | int total_count = -1; |
4801 | 4826 | ||
4802 | #ifdef HAVE_DIRCACHE | 4827 | #ifdef HAVE_DIRCACHE |
4803 | if (dircache_is_enabled()) | 4828 | struct dircache_info dcinfo; |
4829 | dircache_get_info(&dcinfo); | ||
4830 | if (dcinfo.status != DIRCACHE_IDLE) | ||
4804 | { | 4831 | { |
4805 | total_count = dircache_get_entry_count(); | 4832 | total_count = dcinfo.entry_count; |
4806 | } | 4833 | } |
4807 | else | 4834 | else |
4808 | #endif | 4835 | #endif /* HAVE_DIRCACHE */ |
4809 | #ifdef HAVE_TC_RAMCACHE | 4836 | #ifdef HAVE_TC_RAMCACHE |
4810 | { | 4837 | { |
4811 | if (ramcache_hdr && tc_stat.ramcache) | 4838 | if (tcramcache.hdr && tc_stat.ramcache) |
4812 | total_count = current_tcmh.tch.entry_count; | 4839 | total_count = current_tcmh.tch.entry_count; |
4813 | } | 4840 | } |
4814 | #endif | 4841 | #endif /* HAVE_TC_RAMCACHE */ |
4815 | 4842 | ||
4816 | if (total_count < 0) | 4843 | if (total_count < 0) |
4817 | return -1; | 4844 | return -1; |
4818 | 4845 | else if (total_count == 0) | |
4819 | return processed_dir_count * 100 / total_count; | 4846 | return 0; |
4847 | else if (processed_dir_count > total_count) | ||
4848 | return 100; | ||
4849 | else | ||
4850 | return processed_dir_count * 100 / total_count; | ||
4820 | } | 4851 | } |
4821 | 4852 | ||
4822 | struct tagcache_stat* tagcache_get_stat(void) | 4853 | struct tagcache_stat* tagcache_get_stat(void) |
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index 59f7bd747a..f89129ae34 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -311,7 +311,8 @@ int mkdir(const char *path) | |||
311 | 311 | ||
312 | struct filestr_base stream; | 312 | struct filestr_base stream; |
313 | struct path_component_info compinfo; | 313 | struct path_component_info compinfo; |
314 | rc = open_stream_internal(path, FF_DIR, &stream, &compinfo); | 314 | rc = open_stream_internal(path, FF_DIR | FF_PARENTINFO, &stream, |
315 | &compinfo); | ||
315 | if (rc < 0) | 316 | if (rc < 0) |
316 | { | 317 | { |
317 | DEBUGF("Can't open parent dir or path is not a directory\n"); | 318 | DEBUGF("Can't open parent dir or path is not a directory\n"); |
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 0761f837e1..8a75f3bbad 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c | |||
@@ -610,6 +610,19 @@ static int get_index(const struct dircache_entry *ce) | |||
610 | } | 610 | } |
611 | 611 | ||
612 | /** | 612 | /** |
613 | * return the frontier flags for the index | ||
614 | */ | ||
615 | static uint32_t get_frontier(int idx) | ||
616 | { | ||
617 | if (idx == 0) | ||
618 | return UINT32_MAX; | ||
619 | else if (idx > 0) | ||
620 | return get_entry(idx)->frontier; | ||
621 | else /* idx < 0 */ | ||
622 | return get_idx_dcvolp(idx)->frontier; | ||
623 | } | ||
624 | |||
625 | /** | ||
613 | * return the sublist down pointer for the sublist that contains entry 'idx' | 626 | * return the sublist down pointer for the sublist that contains entry 'idx' |
614 | */ | 627 | */ |
615 | static int * get_downidxp(int idx) | 628 | static int * get_downidxp(int idx) |
@@ -2515,30 +2528,41 @@ static ssize_t get_path_sub(int idx, struct get_path_sub_data *data) | |||
2515 | } | 2528 | } |
2516 | 2529 | ||
2517 | /** | 2530 | /** |
2518 | * retrieve and validate the file's entry/binding serial number | 2531 | * validate the file's entry/binding serial number |
2519 | * the dircache file's serial number must match the indexed entry's or the | 2532 | * the dircache file's serial number must match the indexed entry's or the |
2520 | * file reference is stale | 2533 | * file reference is stale |
2521 | */ | 2534 | */ |
2522 | static dc_serial_t get_file_serialnum(const struct dircache_file *dcfilep) | 2535 | static int check_file_serialnum(const struct dircache_file *dcfilep) |
2523 | { | 2536 | { |
2524 | int idx = dcfilep->idx; | 2537 | int idx = dcfilep->idx; |
2525 | 2538 | ||
2526 | if (idx == 0 || idx < -NUM_VOLUMES) | 2539 | if (idx == 0 || idx < -NUM_VOLUMES) |
2527 | return 0; | 2540 | return -EBADF; |
2541 | |||
2542 | dc_serial_t serialnum = dcfilep->serialnum; | ||
2528 | 2543 | ||
2529 | dc_serial_t serialnum; | 2544 | if (serialnum == 0) |
2545 | return -EBADF; | ||
2546 | |||
2547 | dc_serial_t s; | ||
2530 | 2548 | ||
2531 | if (idx > 0) | 2549 | if (idx > 0) |
2532 | { | 2550 | { |
2533 | struct dircache_entry *ce = get_entry(idx); | 2551 | struct dircache_entry *ce = get_entry(idx); |
2534 | serialnum = ce ? ce->serialnum : 0; | 2552 | if (!ce || !(s = ce->serialnum)) |
2553 | return -EBADF; | ||
2535 | } | 2554 | } |
2536 | else | 2555 | else /* idx < 0 */ |
2537 | { | 2556 | { |
2538 | serialnum = get_idx_dcvolp(idx)->serialnum; | 2557 | struct dircache_volume *dcvolp = get_idx_dcvolp(idx); |
2558 | if (!(s = dcvolp->serialnum)) | ||
2559 | return -EBADF; | ||
2539 | } | 2560 | } |
2540 | 2561 | ||
2541 | return serialnum == dcfilep->serialnum ? serialnum : 0; | 2562 | if (serialnum != s) |
2563 | return -EBADF; | ||
2564 | |||
2565 | return 0; | ||
2542 | } | 2566 | } |
2543 | 2567 | ||
2544 | /** | 2568 | /** |
@@ -2582,6 +2606,8 @@ void dircache_fileref_init(struct dircache_fileref *dcfrefp) | |||
2582 | * failure - a negative value | 2606 | * failure - a negative value |
2583 | * | 2607 | * |
2584 | * errors: | 2608 | * errors: |
2609 | * EBADF - Bad file number | ||
2610 | * EFAULT - Bad address | ||
2585 | * ENOENT - No such file or directory | 2611 | * ENOENT - No such file or directory |
2586 | */ | 2612 | */ |
2587 | ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, char *buf, | 2613 | ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, char *buf, |
@@ -2589,6 +2615,9 @@ ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, char * | |||
2589 | { | 2615 | { |
2590 | ssize_t rc; | 2616 | ssize_t rc; |
2591 | 2617 | ||
2618 | if (!dcfrefp) | ||
2619 | FILE_ERROR_RETURN(EFAULT, -1); | ||
2620 | |||
2592 | /* if missing buffer space, still return what's needed a la strlcpy */ | 2621 | /* if missing buffer space, still return what's needed a la strlcpy */ |
2593 | if (!buf) | 2622 | if (!buf) |
2594 | size = 0; | 2623 | size = 0; |
@@ -2600,10 +2629,11 @@ ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, char * | |||
2600 | /* first and foremost, there must be a cache and the serial number must | 2629 | /* first and foremost, there must be a cache and the serial number must |
2601 | check out */ | 2630 | check out */ |
2602 | if (!dircache_runinfo.handle) | 2631 | if (!dircache_runinfo.handle) |
2603 | FILE_ERROR(ENOENT, -1); | 2632 | FILE_ERROR(EBADF, -2); |
2604 | 2633 | ||
2605 | if (get_file_serialnum(&dcfrefp->dcfile) == 0) | 2634 | rc = check_file_serialnum(&dcfrefp->dcfile); |
2606 | FILE_ERROR(ENOENT, -2); | 2635 | if (rc < 0) |
2636 | FILE_ERROR(-rc, -3); | ||
2607 | 2637 | ||
2608 | struct get_path_sub_data data = | 2638 | struct get_path_sub_data data = |
2609 | { | 2639 | { |
@@ -2614,10 +2644,10 @@ ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, char * | |||
2614 | 2644 | ||
2615 | rc = get_path_sub(dcfrefp->dcfile.idx, &data); | 2645 | rc = get_path_sub(dcfrefp->dcfile.idx, &data); |
2616 | if (rc < 0) | 2646 | if (rc < 0) |
2617 | FILE_ERROR(ENOENT, rc * 10 - 3); | 2647 | FILE_ERROR(ENOENT, rc * 10 - 4); |
2618 | 2648 | ||
2619 | if (data.serialhash != dcfrefp->serialhash) | 2649 | if (data.serialhash != dcfrefp->serialhash) |
2620 | FILE_ERROR(ENOENT, -4); | 2650 | FILE_ERROR(ENOENT, -5); |
2621 | 2651 | ||
2622 | file_error: | 2652 | file_error: |
2623 | dircache_unlock(); | 2653 | dircache_unlock(); |
@@ -2626,11 +2656,19 @@ file_error: | |||
2626 | 2656 | ||
2627 | /** | 2657 | /** |
2628 | * Test a path to various levels of rigor and optionally return dircache file | 2658 | * Test a path to various levels of rigor and optionally return dircache file |
2629 | * info for the given path | 2659 | * info for the given path. |
2660 | * | ||
2661 | * If the file reference is used, it is checked first and the path is checked | ||
2662 | * only if all specified file reference checks fail. | ||
2630 | * | 2663 | * |
2631 | * returns: | 2664 | * returns: |
2632 | * success: 0 | 2665 | * success: 0 = not cached (very weak) |
2666 | * 1 = serial number checks out for the reference (weak) | ||
2667 | * 2 = serial number and hash check out for the reference (medium) | ||
2668 | * 3 = path is valid; reference updated if specified (strong) | ||
2633 | * failure: a negative value | 2669 | * failure: a negative value |
2670 | * if file definitely doesn't exist (errno = ENOENT) | ||
2671 | * other error | ||
2634 | * | 2672 | * |
2635 | * errors (including but not limited to): | 2673 | * errors (including but not limited to): |
2636 | * EFAULT - Bad address | 2674 | * EFAULT - Bad address |
@@ -2638,78 +2676,121 @@ file_error: | |||
2638 | * ENAMETOOLONG - File or path name too long | 2676 | * ENAMETOOLONG - File or path name too long |
2639 | * ENOENT - No such file or directory | 2677 | * ENOENT - No such file or directory |
2640 | * ENOTDIR - Not a directory | 2678 | * ENOTDIR - Not a directory |
2641 | * ENXIO - No such device or address | ||
2642 | */ | 2679 | */ |
2643 | int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp, const char *path) | 2680 | int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp, |
2681 | const char *path) | ||
2644 | { | 2682 | { |
2645 | int rc; | ||
2646 | |||
2647 | if (!(flags & (DCS_FILEREF | DCS_CACHED_PATH))) | 2683 | if (!(flags & (DCS_FILEREF | DCS_CACHED_PATH))) |
2648 | FILE_ERROR_RETURN(EINVAL, -1); /* search nothing? */ | 2684 | FILE_ERROR_RETURN(EINVAL, -1); /* search nothing? */ |
2649 | 2685 | ||
2650 | dircache_lock(); | 2686 | if (!dcfrefp && (flags & (DCS_FILEREF | DCS_UPDATE_FILEREF))) |
2687 | FILE_ERROR_RETURN(EFAULT, -2); /* bad! */ | ||
2651 | 2688 | ||
2652 | if (!dircache_runinfo.handle) | 2689 | int rc = 0; |
2653 | FILE_ERROR(ENOENT, -2); | ||
2654 | 2690 | ||
2655 | if (flags & DCS_FILEREF) | 2691 | dircache_lock(); |
2656 | { | ||
2657 | if (!dcfrefp) | ||
2658 | FILE_ERROR(EFAULT, -3); | ||
2659 | 2692 | ||
2660 | if (get_file_serialnum(&dcfrefp->dcfile) != 0) | 2693 | /* -- File reference search -- */ |
2694 | if (!dircache_runinfo.handle) | ||
2695 | ; /* cache not enabled; not cached */ | ||
2696 | else if (!(flags & DCS_FILEREF)) | ||
2697 | ; /* don't use fileref */ | ||
2698 | else if (check_file_serialnum(&dcfrefp->dcfile) < 0) | ||
2699 | ; /* serial number bad */ | ||
2700 | else if (!(flags & _DCS_VERIFY_FLAG)) | ||
2701 | rc = 1; /* only check idx and serialnum */ | ||
2702 | else if (get_file_serialhash(&dcfrefp->dcfile) == dcfrefp->serialhash) | ||
2703 | rc = 2; /* reference is most likely still valid */ | ||
2704 | |||
2705 | /* -- Path cache and storage search -- */ | ||
2706 | if (rc > 0) | ||
2707 | ; /* rc > 0 */ /* found by file reference */ | ||
2708 | else if (!(flags & DCS_CACHED_PATH)) | ||
2709 | ; /* rc = 0 */ /* reference bad/unused and no path */ | ||
2710 | else | ||
2711 | { /* rc = 0 */ /* check path with cache and/or storage */ | ||
2712 | struct path_component_info compinfo; | ||
2713 | struct filestr_base stream; | ||
2714 | unsigned int ffcache = (flags & _DCS_STORAGE_FLAG) ? 0 : FF_CACHEONLY; | ||
2715 | int err = errno; | ||
2716 | int rc2 = open_stream_internal(path, ffcache | FF_ANYTYPE | FF_PROBE | | ||
2717 | FF_INFO | FF_PARENTINFO, &stream, | ||
2718 | &compinfo); | ||
2719 | if (rc2 <= 0) | ||
2661 | { | 2720 | { |
2662 | if (!(flags & _DCS_VERIFY_FLAG)) | 2721 | if (ffcache == 0) |
2663 | goto file_success; /* no robust verification wanted */ | 2722 | { |
2664 | 2723 | /* checked storage too: absent for sure */ | |
2665 | if (get_file_serialhash(&dcfrefp->dcfile) == dcfrefp->serialhash) | 2724 | FILE_ERROR(rc2 ? ERRNO : ENOENT, rc2 * 10 - 5); |
2666 | goto file_success; /* reference is most likely still valid */ | 2725 | } |
2667 | } | ||
2668 | |||
2669 | if (!(flags & DCS_CACHED_PATH)) | ||
2670 | FILE_ERROR(ENOENT, -4); /* no path search wanted */ | ||
2671 | } | ||
2672 | 2726 | ||
2673 | if (flags & DCS_CACHED_PATH) | 2727 | if (rc2 < 0) |
2674 | { | 2728 | { |
2675 | const bool update = flags & DCS_UPDATE_FILEREF; | 2729 | /* no base info available */ |
2676 | struct path_component_info *compinfop = NULL; | 2730 | if (errno != ENOENT) |
2731 | FILE_ERROR(ERRNO, rc2 * 10 - 6); | ||
2677 | 2732 | ||
2678 | if (update) | 2733 | /* only cache; something didn't exist: indecisive */ |
2679 | { | 2734 | errno = err; |
2680 | if (!dcfrefp) | 2735 | FILE_ERROR(ERRNO, RC); /* rc = 0 */ |
2681 | FILE_ERROR(EFAULT, -5); | 2736 | } |
2682 | 2737 | ||
2683 | compinfop = alloca(sizeof (*compinfop)); | 2738 | struct dircache_file *dcfp = &compinfo.parentinfo.dcfile; |
2739 | if (get_frontier(dcfp->idx) == FRONTIER_SETTLED) | ||
2740 | FILE_ERROR(ENOENT, -7); /* parent not a frontier; absent */ | ||
2741 | /* else checked only cache; parent is incomplete: indecisive */ | ||
2684 | } | 2742 | } |
2685 | 2743 | else | |
2686 | struct filestr_base stream; | ||
2687 | rc = open_stream_internal(path, FF_ANYTYPE | FF_PROBE | FF_SELFINFO | | ||
2688 | ((flags & _DCS_STORAGE_FLAG) ? 0 : FF_CACHEONLY), | ||
2689 | &stream, compinfop); | ||
2690 | if (rc <= 0) | ||
2691 | { | 2744 | { |
2692 | if (update) | 2745 | struct dircache_file *dcfp = &compinfo.info.dcfile; |
2693 | dircache_fileref_init(dcfrefp); | 2746 | if (dcfp->serialnum != 0) |
2694 | 2747 | { | |
2695 | FILE_ERROR(rc ? ERRNO : ENOENT, rc * 10 - 6); | 2748 | /* found by path in the cache afterall */ |
2696 | } | 2749 | if (flags & DCS_UPDATE_FILEREF) |
2750 | { | ||
2751 | dcfrefp->dcfile = *dcfp; | ||
2752 | dcfrefp->serialhash = get_file_serialhash(dcfp); | ||
2753 | } | ||
2697 | 2754 | ||
2698 | if (update) | 2755 | rc = 3; |
2699 | { | 2756 | } |
2700 | dcfrefp->dcfile = compinfop->info.dcfile; | ||
2701 | dcfrefp->serialhash = get_file_serialhash(&compinfop->info.dcfile); | ||
2702 | } | 2757 | } |
2703 | } | 2758 | } |
2704 | 2759 | ||
2705 | file_success: | ||
2706 | rc = 0; | ||
2707 | |||
2708 | file_error: | 2760 | file_error: |
2761 | if (rc <= 0 && (flags & DCS_UPDATE_FILEREF)) | ||
2762 | dircache_fileref_init(dcfrefp); | ||
2763 | |||
2709 | dircache_unlock(); | 2764 | dircache_unlock(); |
2710 | return rc; | 2765 | return rc; |
2711 | } | 2766 | } |
2712 | 2767 | ||
2768 | /** | ||
2769 | * Compare dircache file references (no validity check is made) | ||
2770 | * | ||
2771 | * returns: 0 - no match | ||
2772 | * 1 - indexes match | ||
2773 | * 2 - serial numbers match | ||
2774 | * 3 - serial and hashes match | ||
2775 | */ | ||
2776 | int dircache_fileref_cmp(const struct dircache_fileref *dcfrefp1, | ||
2777 | const struct dircache_fileref *dcfrefp2) | ||
2778 | { | ||
2779 | int cmp = 0; | ||
2780 | |||
2781 | if (dcfrefp1->dcfile.idx == dcfrefp2->dcfile.idx) | ||
2782 | { | ||
2783 | cmp++; | ||
2784 | if (dcfrefp1->dcfile.serialnum == dcfrefp2->dcfile.serialnum) | ||
2785 | { | ||
2786 | cmp++; | ||
2787 | if (dcfrefp1->serialhash == dcfrefp2->serialhash) | ||
2788 | cmp++; | ||
2789 | } | ||
2790 | } | ||
2791 | |||
2792 | return cmp; | ||
2793 | } | ||
2713 | 2794 | ||
2714 | /** Debug screen/info stuff **/ | 2795 | /** Debug screen/info stuff **/ |
2715 | 2796 | ||
diff --git a/firmware/common/file.c b/firmware/common/file.c index 1f93824dc8..028bdbe9f0 100644 --- a/firmware/common/file.c +++ b/firmware/common/file.c | |||
@@ -354,6 +354,10 @@ static int open_internal_inner2(const char *path, | |||
354 | int rc; | 354 | int rc; |
355 | 355 | ||
356 | struct path_component_info compinfo; | 356 | struct path_component_info compinfo; |
357 | |||
358 | if (callflags & FF_CREAT) | ||
359 | callflags |= FF_PARENTINFO; | ||
360 | |||
357 | rc = open_stream_internal(path, callflags, &file->stream, &compinfo); | 361 | rc = open_stream_internal(path, callflags, &file->stream, &compinfo); |
358 | if (rc < 0) | 362 | if (rc < 0) |
359 | { | 363 | { |
@@ -989,7 +993,8 @@ int rename(const char *old, const char *new) | |||
989 | file_internal_lock_WRITER(); | 993 | file_internal_lock_WRITER(); |
990 | 994 | ||
991 | /* open 'old'; it must exist */ | 995 | /* open 'old'; it must exist */ |
992 | open1rc = open_stream_internal(old, FF_ANYTYPE, &oldstr, &oldinfo); | 996 | open1rc = open_stream_internal(old, FF_ANYTYPE | FF_PARENTINFO, &oldstr, |
997 | &oldinfo); | ||
993 | if (open1rc <= 0) | 998 | if (open1rc <= 0) |
994 | { | 999 | { |
995 | DEBUGF("Failed opening old: %d\n", open1rc); | 1000 | DEBUGF("Failed opening old: %d\n", open1rc); |
@@ -1014,7 +1019,8 @@ int rename(const char *old, const char *new) | |||
1014 | newinfo.prefixp = oldstr.infop; | 1019 | newinfo.prefixp = oldstr.infop; |
1015 | } | 1020 | } |
1016 | 1021 | ||
1017 | open2rc = open_stream_internal(new, callflags, &newstr, &newinfo); | 1022 | open2rc = open_stream_internal(new, callflags | FF_PARENTINFO, &newstr, |
1023 | &newinfo); | ||
1018 | if (open2rc < 0) | 1024 | if (open2rc < 0) |
1019 | { | 1025 | { |
1020 | DEBUGF("Failed opening new file: %d\n", open2rc); | 1026 | DEBUGF("Failed opening new file: %d\n", open2rc); |
diff --git a/firmware/common/file_internal.c b/firmware/common/file_internal.c index 75fb21e8a6..8fee802f6f 100644 --- a/firmware/common/file_internal.c +++ b/firmware/common/file_internal.c | |||
@@ -351,10 +351,10 @@ static int fill_path_compinfo(struct pathwalk *walkp, | |||
351 | compinfo->length = compp->length; | 351 | compinfo->length = compp->length; |
352 | compinfo->attr = compp->attr; | 352 | compinfo->attr = compp->attr; |
353 | compinfo->filesize = walkp->filesize; | 353 | compinfo->filesize = walkp->filesize; |
354 | if (!(walkp->callflags & FF_SELFINFO)) | 354 | if (walkp->callflags & FF_INFO) |
355 | compinfo->parentinfo = (compp->nextp ?: compp)->info; | ||
356 | else | ||
357 | compinfo->info = compp->info; | 355 | compinfo->info = compp->info; |
356 | if (walkp->callflags & FF_PARENTINFO) | ||
357 | compinfo->parentinfo = (compp->nextp ?: compp)->info; | ||
358 | } | 358 | } |
359 | 359 | ||
360 | return rc; | 360 | return rc; |
@@ -571,9 +571,9 @@ int open_stream_internal(const char *path, unsigned int callflags, | |||
571 | FILE_ERROR(path ? ENOENT : EFAULT, -1); | 571 | FILE_ERROR(path ? ENOENT : EFAULT, -1); |
572 | } | 572 | } |
573 | 573 | ||
574 | /* if !compinfo, then the result of this check is not visible anyway */ | 574 | /* if !compinfo then these cannot be returned anyway */ |
575 | if (!compinfo) | 575 | if (!compinfo) |
576 | callflags &= ~FF_CHECKPREFIX; | 576 | callflags &= ~(FF_INFO | FF_PARENTINFO | FF_CHECKPREFIX); |
577 | 577 | ||
578 | /* This lets it be passed quietly to directory scanning */ | 578 | /* This lets it be passed quietly to directory scanning */ |
579 | stream->flags = callflags & FF_MASK; | 579 | stream->flags = callflags & FF_MASK; |
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index d73c6f6e81..2cf838e539 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h | |||
@@ -69,6 +69,9 @@ typedef uint32_t dc_serial_t; | |||
69 | /** | 69 | /** |
70 | ****************************************************************************/ | 70 | ****************************************************************************/ |
71 | 71 | ||
72 | #define IF_DIRCACHE(...) __VA_ARGS__ | ||
73 | #define IFN_DIRCACHE(...) | ||
74 | |||
72 | #if CONFIG_PLATFORM & PLATFORM_NATIVE | 75 | #if CONFIG_PLATFORM & PLATFORM_NATIVE |
73 | /* native dircache is lower-level than on a hosted target */ | 76 | /* native dircache is lower-level than on a hosted target */ |
74 | #define DIRCACHE_NATIVE | 77 | #define DIRCACHE_NATIVE |
@@ -169,6 +172,9 @@ enum dircache_search_flags | |||
169 | int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp, | 172 | int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp, |
170 | const char *path); | 173 | const char *path); |
171 | 174 | ||
175 | int dircache_fileref_cmp(const struct dircache_fileref *dcfrefp1, | ||
176 | const struct dircache_fileref *dcfrefp2); | ||
177 | |||
172 | 178 | ||
173 | /** Debug screen/info stuff **/ | 179 | /** Debug screen/info stuff **/ |
174 | 180 | ||
@@ -202,6 +208,11 @@ int dircache_save(void); | |||
202 | 208 | ||
203 | void dircache_init(size_t last_size) INIT_ATTR; | 209 | void dircache_init(size_t last_size) INIT_ATTR; |
204 | 210 | ||
211 | #else /* !HAVE_DIRCACHE */ | ||
212 | |||
213 | #define IF_DIRCACHE(...) | ||
214 | #define IFN_DIRCACHE(...) __VA_ARGS__ | ||
215 | |||
205 | #endif /* HAVE_DIRCACHE */ | 216 | #endif /* HAVE_DIRCACHE */ |
206 | 217 | ||
207 | #endif /* _DIRCACHE_H */ | 218 | #endif /* _DIRCACHE_H */ |
diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h index acec81206e..e7edb3a441 100644 --- a/firmware/include/file_internal.h +++ b/firmware/include/file_internal.h | |||
@@ -136,8 +136,9 @@ enum fildes_and_obj_flags | |||
136 | FF_NOISO = 0x00200000, /* do not decode ISO filenames to UTF-8 */ | 136 | FF_NOISO = 0x00200000, /* do not decode ISO filenames to UTF-8 */ |
137 | FF_PROBE = 0x00400000, /* only test existence; don't open */ | 137 | FF_PROBE = 0x00400000, /* only test existence; don't open */ |
138 | FF_CACHEONLY = 0x00800000, /* succeed only if in dircache */ | 138 | FF_CACHEONLY = 0x00800000, /* succeed only if in dircache */ |
139 | FF_SELFINFO = 0x01000000, /* return info on self as well */ | 139 | FF_INFO = 0x01000000, /* return info on self */ |
140 | FF_MASK = 0x01ff0000, | 140 | FF_PARENTINFO = 0x02000000, /* return info on parent */ |
141 | FF_MASK = 0x03ff0000, | ||
141 | }; | 142 | }; |
142 | 143 | ||
143 | /** Common data structures used throughout **/ | 144 | /** Common data structures used throughout **/ |
@@ -244,18 +245,16 @@ static inline void filestr_unlock(struct filestr_base *stream) | |||
244 | /* structure to return detailed information about what you opened */ | 245 | /* structure to return detailed information about what you opened */ |
245 | struct path_component_info | 246 | struct path_component_info |
246 | { | 247 | { |
247 | const char *name; /* pointer to name within 'path' (OUT) */ | 248 | const char *name; /* OUT: pointer to name within 'path' */ |
248 | size_t length; /* length of component within 'path' */ | 249 | size_t length; /* OUT: length of component within 'path' */ |
249 | file_size_t filesize; /* size of the opened file (0 if dir) */ | 250 | file_size_t filesize; /* OUT: size of the opened file (0 if dir) */ |
250 | unsigned int attr; /* attributes of this component */ | 251 | unsigned int attr; /* OUT: attributes of this component */ |
251 | struct file_base_info *prefixp; /* base info to check as prefix | 252 | struct file_base_info info; /* OUT: base info on file |
252 | (IN if FF_CHECKPREFIX) */ | 253 | (FF_INFO) */ |
253 | union { | 254 | struct file_base_info parentinfo; /* OUT: base parent directory info |
254 | struct file_base_info parentinfo; /* parent directory base info of file | 255 | (FF_PARENTINFO) */ |
255 | (if not FF_SELFINFO) */ | 256 | struct file_base_info *prefixp; /* IN: base info to check as prefix |
256 | struct file_base_info info; /* base info of file itself | 257 | (FF_CHECKPREFIX) */ |
257 | (if FF_SELFINFO) */ | ||
258 | }; | ||
259 | }; | 258 | }; |
260 | 259 | ||
261 | int open_stream_internal(const char *path, unsigned int callflags, | 260 | int open_stream_internal(const char *path, unsigned int callflags, |