| 686 | offset += chunk; |
| 687 | } |
| 688 | } |
| 689 | |
| 690 | std::fclose(f); |
| 691 | return true; |
| 692 | } |
| 693 | |
| 694 | // ─── File I/O: Read ───────────────────────────────────────────────────── |
| 695 | |
| 696 | bool DiskPrefixCache::read_file(const std::string & path, int slot) { |
| 697 | FILE * f = std::fopen(path.c_str(), "rb"); |
| 698 | if (!f) return false; |
| 699 | |
| 700 | DiskCacheHeader hdr{}; |
| 701 | if (!read_header(f, hdr)) { std::fclose(f); return false; } |
| 702 | |
| 703 | // Validate. |
| 704 | if (std::memcmp(hdr.magic, "DKVC", 4) != 0) { std::fclose(f); return false; } |
| 705 | if (hdr.version != DISK_CACHE_VERSION) { std::fclose(f); return false; } |
| 706 | if (std::memcmp(hdr.layout_id, layout_id_.data(), 16) != 0) { std::fclose(f); return false; } |
| 707 | |
| 708 | // Read tensor table. |
| 709 | std::vector<DiskTensorEntry> table; |
| 710 | table.reserve(hdr.n_tensors); |
| 711 | for (uint32_t i = 0; i < hdr.n_tensors; ++i) { |
| 712 | DiskTensorEntry ent; |
| 713 | uint16_t name_len; |
| 714 | if (!read_u16(f, name_len)) { std::fclose(f); return false; } |
| 715 | if (name_len >= GGML_MAX_NAME) { std::fclose(f); return false; } |
| 716 | char name_buf[GGML_MAX_NAME] = {}; |
| 717 | if (std::fread(name_buf, 1, name_len, f) != name_len) { std::fclose(f); return false; } |
| 718 | ent.name = name_buf; |
| 719 | if (!read_u32(f, ent.type)) { std::fclose(f); return false; } |
| 720 | for (int d = 0; d < 4; ++d) { |
| 721 | if (!read_i64(f, ent.ne[d])) { std::fclose(f); return false; } |
| 722 | } |
| 723 | uint64_t nbytes_raw; |
| 724 | if (!read_u64(f, nbytes_raw)) { std::fclose(f); return false; } |
| 725 | ent.nbytes = (size_t)nbytes_raw; |
| 726 | table.push_back(std::move(ent)); |
| 727 | } |
| 728 | |
| 729 | // Allocate ggml context + buffer. |
| 730 | ggml_init_params ip{}; |
| 731 | ip.mem_size = ggml_tensor_overhead() * (size_t)(hdr.n_tensors + 4) + 4096; |
| 732 | ip.no_alloc = true; |
| 733 | ggml_context * ctx = ggml_init(ip); |
| 734 | if (!ctx) { std::fclose(f); return false; } |
| 735 | |
| 736 | // Create tensors. |
| 737 | for (const auto & ent : table) { |
| 738 | ggml_tensor * t = ggml_new_tensor(ctx, (ggml_type)ent.type, 4, ent.ne); |
| 739 | if (!t) { |
| 740 | ggml_free(ctx); |
| 741 | std::fclose(f); |
| 742 | return false; |
| 743 | } |
| 744 | ggml_set_name(t, ent.name.c_str()); |
| 745 | } |