|
|
@@ -122,6 +122,19 @@ std::vector<uint8_t> WalEntry::serialize() const {
|
|
|
result.push_back(0);
|
|
|
}
|
|
|
|
|
|
+ // Write vectorData flag and data (1 byte flag + 4 bytes dim + dim * sizeof(float) bytes)
|
|
|
+ if (vectorData) {
|
|
|
+ result.push_back(1);
|
|
|
+ uint32_t dim = static_cast<uint32_t>(vectorData->size());
|
|
|
+ for (int i = 0; i < 4; ++i) {
|
|
|
+ result.push_back(static_cast<uint8_t>((dim >> (i * 8)) & 0xFF));
|
|
|
+ }
|
|
|
+ const uint8_t* floatBytes = reinterpret_cast<const uint8_t*>(vectorData->data());
|
|
|
+ result.insert(result.end(), floatBytes, floatBytes + dim * sizeof(float));
|
|
|
+ } else {
|
|
|
+ result.push_back(0);
|
|
|
+ }
|
|
|
+
|
|
|
// Calculate and append checksum (excluding length prefix and checksum itself)
|
|
|
uint32_t crc = crc32::calculate(result.data() + 4, result.size() - 4);
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
@@ -218,6 +231,7 @@ std::optional<WalEntry> WalEntry::deserialize(const std::vector<uint8_t>& data)
|
|
|
optsLen |= static_cast<uint32_t>(data[offset++]) << (i * 8);
|
|
|
}
|
|
|
std::string optsStr(reinterpret_cast<const char*>(&data[offset]), optsLen);
|
|
|
+ offset += optsLen;
|
|
|
try {
|
|
|
entry.collectionOptions = CollectionOptions::fromJson(nlohmann::json::parse(optsStr));
|
|
|
} catch (const nlohmann::json::exception&) {
|
|
|
@@ -225,6 +239,24 @@ std::optional<WalEntry> WalEntry::deserialize(const std::vector<uint8_t>& data)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Read vectorData (present for VEC_PUT, but flag byte always written)
|
|
|
+ if (offset < data.size() - 4) { // at least 1 flag byte + 4 checksum bytes remain
|
|
|
+ uint8_t hasVec = data[offset++];
|
|
|
+ if (hasVec) {
|
|
|
+ uint32_t dim = 0;
|
|
|
+ for (int i = 0; i < 4; ++i) {
|
|
|
+ dim |= static_cast<uint32_t>(data[offset++]) << (i * 8);
|
|
|
+ }
|
|
|
+ if (offset + dim * sizeof(float) > data.size() - 4) {
|
|
|
+ return std::nullopt; // Truncated vector data
|
|
|
+ }
|
|
|
+ std::vector<float> vec(dim);
|
|
|
+ std::memcpy(vec.data(), &data[offset], dim * sizeof(float));
|
|
|
+ offset += dim * sizeof(float);
|
|
|
+ entry.vectorData = std::move(vec);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
entry.checksum = storedCrc;
|
|
|
return entry;
|
|
|
}
|
|
|
@@ -486,6 +518,25 @@ WalEntry WriteAheadLog::makeDropCollectionEntry(const std::string& collection) {
|
|
|
return entry;
|
|
|
}
|
|
|
|
|
|
+WalEntry WriteAheadLog::makeVecPutEntry(const std::string& collection,
|
|
|
+ const std::string& docId, const std::vector<float>& vec) {
|
|
|
+ WalEntry entry;
|
|
|
+ entry.opType = WalOpType::VEC_PUT;
|
|
|
+ entry.collection = collection;
|
|
|
+ entry.documentId = docId;
|
|
|
+ entry.vectorData = vec;
|
|
|
+ return entry;
|
|
|
+}
|
|
|
+
|
|
|
+WalEntry WriteAheadLog::makeVecDeleteEntry(const std::string& collection,
|
|
|
+ const std::string& docId) {
|
|
|
+ WalEntry entry;
|
|
|
+ entry.opType = WalOpType::VEC_DELETE;
|
|
|
+ entry.collection = collection;
|
|
|
+ entry.documentId = docId;
|
|
|
+ return entry;
|
|
|
+}
|
|
|
+
|
|
|
std::filesystem::path WriteAheadLog::currentFilePath() const {
|
|
|
return config_.walDir / "wal-current.log";
|
|
|
}
|