1/**
2 * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15
16 * \author Haichao.chc
17 * \date Oct 2020
18 * \brief Format of collection version meta info
19 */
20
21#pragma once
22
23#include <mutex>
24#include <aitheta2/index_storage.h>
25#include "common/macro_define.h"
26#include "common/types.h"
27#include "segment/segment.h"
28#include "typedef.h"
29
30namespace proxima {
31namespace be {
32namespace index {
33
34/**
35 * | SummaryBlock | VersionBlock | SegmentBlock |
36 * |----------------------|----------------------------|------------------|
37 * | CollectionSummary | VersionHeader + VersionSet | SegmentMeta... |
38 * |----------------------|----------------------------|------------------|
39 **/
40
41struct CollectionSummary {
42 uint64_t schema_revision{0U};
43 uint64_t total_doc_count{0U};
44 uint64_t delete_doc_count{0U};
45 uint64_t reserved_[5];
46};
47
48static_assert(sizeof(CollectionSummary) % 64 == 0,
49 "CollectionSummary must be aligned with 64 bytes");
50
51/*
52 * Version info header
53 */
54struct VersionHeader {
55 uint64_t total_version_count{0U};
56 uint64_t current_version_offset{0U};
57 uint64_t total_segment_count{0U};
58 uint64_t reserved_[5];
59};
60
61static_assert(sizeof(VersionHeader) % 64 == 0,
62 "VersionHeader must be aligned with 64 bytes");
63
64/*
65 * A VersionSet includes serveral segment metas
66 */
67struct VersionSet {
68 uint64_t segment_count{0};
69 uint64_t reserved_[7];
70 uint32_t segment_ids[1024];
71
72 VersionSet() {
73 memset(this->segment_ids, 0, sizeof(this->segment_ids));
74 }
75};
76
77static_assert(sizeof(VersionSet) % 64 == 0,
78 "VersionSet must be aligned with 64 bytes");
79
80/*
81 * VersionStore describes the struct of version info storage
82 */
83class VersionStore {
84 public:
85 PROXIMA_DISALLOW_COPY_AND_ASSIGN(VersionStore);
86
87 //! Constructor
88 VersionStore() = default;
89
90 //! Destructor
91 ~VersionStore() = default;
92
93 public:
94 //! Mount persist storage
95 int mount(const IndexStoragePtr &storage);
96
97 //! Unmount persist storage
98 void unmount();
99
100 //! Alloc new segment meta
101 int alloc_segment_meta(SegmentMeta *segment_meta);
102
103 //! Get segment meta
104 int get_segment_meta(SegmentID segment_id, SegmentMeta *segment_meta) const;
105
106 //! Update segment meta
107 int update_segment_meta(const SegmentMeta &segment_meta);
108
109 //! Get specified version set
110 int get_version_set(VersionSet *version_set) const;
111
112 //! Update new version set
113 int update_version_set(const VersionSet &version_set);
114
115 //! Get summary
116 int get_collection_summary(CollectionSummary *summary) const;
117
118 //! Update summary
119 int update_collection_summary(const CollectionSummary &summary);
120
121 public:
122 //! Return total version count
123 uint32_t total_version_count() const {
124 return header_.total_version_count;
125 }
126
127 //! Return total segment count
128 uint32_t total_segment_count() const {
129 return header_.total_segment_count;
130 }
131
132 private:
133 int init_storage();
134
135 int load_storage();
136
137 private:
138 int get_segment_meta_impl(SegmentID segment_id,
139 SegmentMeta *segment_meta) const {
140 size_t offset = segment_id * sizeof(SegmentMeta);
141 size_t read_len = segment_block_->fetch(offset, (void *)segment_meta,
142 sizeof(SegmentMeta));
143 if (read_len != sizeof(SegmentMeta)) {
144 return ErrorCode_ReadData;
145 }
146 return 0;
147 }
148
149 int update_segment_meta_impl(SegmentID segment_id,
150 const SegmentMeta &segment_meta) {
151 size_t offset = segment_id * sizeof(SegmentMeta);
152 size_t write_len =
153 segment_block_->write(offset, &segment_meta, sizeof(SegmentMeta));
154 if (write_len != sizeof(SegmentMeta)) {
155 return ErrorCode_WriteData;
156 }
157 return 0;
158 }
159
160 int update_header_impl(const VersionHeader &header) {
161 size_t write_len =
162 version_block_->write(0U, &header, sizeof(VersionHeader));
163 if (write_len != sizeof(VersionHeader)) {
164 return ErrorCode_WriteData;
165 }
166 return 0;
167 }
168
169 private:
170 constexpr static uint32_t kMaxVersionCount = 5;
171 constexpr static uint32_t kMaxSegmentCount = 1024;
172
173 private:
174 IndexStoragePtr storage_{};
175 IndexBlockPtr summary_block_{};
176 IndexBlockPtr version_block_{};
177 IndexBlockPtr segment_block_{};
178 VersionHeader header_;
179
180 std::mutex mutex_{};
181};
182
183
184} // end namespace index
185} // namespace be
186} // end namespace proxima
187