|
|
@@ -401,6 +401,33 @@ std::vector<uint8_t> SnapshotManager::serializeStore(const MemoryStore& store,
|
|
|
result.insert(result.end(), verJson.begin(), verJson.end());
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // Write vector data (v3)
|
|
|
+ const auto* vectors = store.getCollectionVectors(name);
|
|
|
+ uint64_t vecCount = (vectors != nullptr) ? static_cast<uint64_t>(vectors->size()) : 0;
|
|
|
+ for (int i = 0; i < 8; ++i) {
|
|
|
+ result.push_back(static_cast<uint8_t>((vecCount >> (i * 8)) & 0xFF));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vectors != nullptr) {
|
|
|
+ for (const auto& [docId, vec] : *vectors) {
|
|
|
+ // Write doc ID
|
|
|
+ uint16_t docIdLen = static_cast<uint16_t>(docId.size());
|
|
|
+ result.push_back(static_cast<uint8_t>(docIdLen & 0xFF));
|
|
|
+ result.push_back(static_cast<uint8_t>((docIdLen >> 8) & 0xFF));
|
|
|
+ result.insert(result.end(), docId.begin(), docId.end());
|
|
|
+
|
|
|
+ // Write vector dimension
|
|
|
+ uint32_t dim = static_cast<uint32_t>(vec.size());
|
|
|
+ for (int i = 0; i < 4; ++i) {
|
|
|
+ result.push_back(static_cast<uint8_t>((dim >> (i * 8)) & 0xFF));
|
|
|
+ }
|
|
|
+
|
|
|
+ // Write raw float data
|
|
|
+ const uint8_t* floatBytes = reinterpret_cast<const uint8_t*>(vec.data());
|
|
|
+ result.insert(result.end(), floatBytes, floatBytes + dim * sizeof(float));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
@@ -521,6 +548,43 @@ void SnapshotManager::deserializeStore(const std::vector<uint8_t>& data, MemoryS
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // Read vector data (v3+)
|
|
|
+ if (snapshotVersion >= 3) {
|
|
|
+ if (offset + 8 > data.size()) break;
|
|
|
+ uint64_t vecCount = 0;
|
|
|
+ for (int i = 0; i < 8; ++i) {
|
|
|
+ vecCount |= static_cast<uint64_t>(data[offset++]) << (i * 8);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (uint64_t v = 0; v < vecCount; ++v) {
|
|
|
+ // Read doc ID
|
|
|
+ if (offset + 2 > data.size()) break;
|
|
|
+ uint16_t docIdLen = static_cast<uint16_t>(data[offset]) |
|
|
|
+ (static_cast<uint16_t>(data[offset + 1]) << 8);
|
|
|
+ offset += 2;
|
|
|
+
|
|
|
+ if (offset + docIdLen > data.size()) break;
|
|
|
+ std::string docId(reinterpret_cast<const char*>(&data[offset]), docIdLen);
|
|
|
+ offset += docIdLen;
|
|
|
+
|
|
|
+ // Read vector dimension
|
|
|
+ if (offset + 4 > data.size()) break;
|
|
|
+ uint32_t dim = 0;
|
|
|
+ for (int i = 0; i < 4; ++i) {
|
|
|
+ dim |= static_cast<uint32_t>(data[offset++]) << (i * 8);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Read raw float data
|
|
|
+ size_t byteCount = static_cast<size_t>(dim) * sizeof(float);
|
|
|
+ if (offset + byteCount > data.size()) break;
|
|
|
+ std::vector<float> vec(dim);
|
|
|
+ std::memcpy(vec.data(), &data[offset], byteCount);
|
|
|
+ offset += byteCount;
|
|
|
+
|
|
|
+ store.loadVector(collName, docId, std::move(vec));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|