소스 검색

feat: WAL entries for vector storage (VEC_PUT/VEC_DELETE)

fszontagh 4 달 전
부모
커밋
3fe13e7778
2개의 변경된 파일59개의 추가작업 그리고 1개의 파일을 삭제
  1. 51 0
      service/src/persistence/wal.cpp
  2. 8 1
      service/src/persistence/wal.hpp

+ 51 - 0
service/src/persistence/wal.cpp

@@ -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";
 }

+ 8 - 1
service/src/persistence/wal.hpp

@@ -25,7 +25,9 @@ enum class WalOpType : uint8_t {
     CREATE_COLLECTION = 5,
     DROP_COLLECTION = 6,
     SET_ADD = 7,
-    SET_REMOVE = 8
+    SET_REMOVE = 8,
+    VEC_PUT = 9,
+    VEC_DELETE = 10
 };
 
 /**
@@ -40,6 +42,7 @@ struct WalEntry {
     std::string documentId;
     std::optional<nlohmann::json> data;  // For INSERT/UPDATE/UPSERT
     std::optional<CollectionOptions> collectionOptions;  // For CREATE_COLLECTION
+    std::optional<std::vector<float>> vectorData;  // For VEC_PUT
     uint32_t checksum = 0;           // CRC32 for integrity
 
     // Serialize entry to binary
@@ -138,6 +141,10 @@ public:
     static WalEntry makeUpsertEntry(const std::string& collection, const Document& doc);
     static WalEntry makeCreateCollectionEntry(const std::string& collection, const CollectionOptions& options);
     static WalEntry makeDropCollectionEntry(const std::string& collection);
+    static WalEntry makeVecPutEntry(const std::string& collection,
+        const std::string& docId, const std::vector<float>& vec);
+    static WalEntry makeVecDeleteEntry(const std::string& collection,
+        const std::string& docId);
 
 private:
     // WAL file header