Skip to content

Commit adcd2cb

Browse files
committed
Refactor SVS runtime to support public sources-only build.
* Use `SVS_LVQ_HEADER` and `SVS_LEANVEC_HEADER` as preprocessor flags to enable/disable L/L code * Refactor save()/load() to use `StorageFactory` and cover unsupported storage type cases * Add a separate implementation header for LeanVec Index * Fix `Status` structure copy/move semantics * Modify runtime tests to skip insupported storage kinds
1 parent e643504 commit adcd2cb

File tree

10 files changed

+488
-232
lines changed

10 files changed

+488
-232
lines changed

bindings/cpp/CMakeLists.txt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ set(SVS_RUNTIME_HEADERS
2828
set(SVS_RUNTIME_SOURCES
2929
src/svs_runtime_utils.h
3030
src/dynamic_vamana_index_impl.h
31+
src/dynamic_vamana_index_leanvec_impl.h
32+
src/training_impl.h
3133
src/flat_index_impl.h
3234
src/api_defs.cpp
3335
src/training.cpp
@@ -72,16 +74,16 @@ set_target_properties(${TARGET_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON)
7274
set_target_properties(${TARGET_NAME} PROPERTIES CXX_EXTENSIONS OFF)
7375
set_target_properties(${TARGET_NAME} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} )
7476

75-
if(DEFINED SVS_LVQ_HEADER AND DEFINED SVS_LEANVEC_HEADER)
76-
# expected that pre-defined headers are implementation headers
77-
message(STATUS "Using pre-defined LVQ header: ${SVS_LVQ_HEADER}")
78-
message(STATUS "Using pre-defined LeanVec header: ${SVS_LEANVEC_HEADER}")
79-
else()
80-
set(SVS_LVQ_HEADER "svs/extensions/vamana/lvq.h")
81-
set(SVS_LEANVEC_HEADER "svs/extensions/vamana/leanvec.h")
82-
endif()
83-
8477
if (SVS_RUNTIME_ENABLE_LVQ_LEANVEC)
78+
if(DEFINED SVS_LVQ_HEADER AND DEFINED SVS_LEANVEC_HEADER)
79+
# expected that pre-defined headers are implementation headers
80+
message(STATUS "Using pre-defined LVQ header: ${SVS_LVQ_HEADER}")
81+
message(STATUS "Using pre-defined LeanVec header: ${SVS_LEANVEC_HEADER}")
82+
else()
83+
set(SVS_LVQ_HEADER "svs/extensions/vamana/lvq.h")
84+
set(SVS_LEANVEC_HEADER "svs/extensions/vamana/leanvec.h")
85+
endif()
86+
8587
if(RUNTIME_BINDINGS_PRIVATE_SOURCE_BUILD)
8688
message(STATUS "Building directly from private sources")
8789
target_link_libraries(${TARGET_NAME} PRIVATE
@@ -117,7 +119,7 @@ if (SVS_RUNTIME_ENABLE_LVQ_LEANVEC)
117119
FetchContent_Declare(
118120
svs
119121
URL ${SVS_URL}
120-
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
122+
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
121123
)
122124
FetchContent_MakeAvailable(svs)
123125
list(APPEND CMAKE_PREFIX_PATH "${svs_SOURCE_DIR}")

bindings/cpp/include/svs/runtime/api_defs.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,46 @@ struct SVS_RUNTIME_API Status {
6565
}
6666
}
6767

68+
Status(const Status& other)
69+
: code(other.code)
70+
, message_storage_(nullptr) {
71+
if (other.message_storage_ != nullptr) {
72+
store_message(other.message_storage_);
73+
}
74+
}
75+
76+
Status& operator=(const Status& other) {
77+
if (this != &other) {
78+
code = other.code;
79+
if (message_storage_ != nullptr) {
80+
destroy_message();
81+
}
82+
message_storage_ = nullptr;
83+
if (other.message_storage_ != nullptr) {
84+
store_message(other.message_storage_);
85+
}
86+
}
87+
return *this;
88+
}
89+
90+
Status(Status&& other) noexcept
91+
: code(other.code)
92+
, message_storage_(other.message_storage_) {
93+
other.message_storage_ = nullptr;
94+
}
95+
96+
Status& operator=(Status&& other) noexcept {
97+
if (this != &other) {
98+
code = other.code;
99+
if (message_storage_ != nullptr) {
100+
destroy_message();
101+
}
102+
message_storage_ = other.message_storage_;
103+
other.message_storage_ = nullptr;
104+
}
105+
return *this;
106+
}
107+
68108
constexpr ~Status() noexcept {
69109
if (message_storage_ != nullptr) {
70110
destroy_message();

bindings/cpp/src/dynamic_vamana_index.cpp

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#include "dynamic_vamana_index_impl.h"
2020
#include "svs_runtime_utils.h"
2121

22+
#ifdef SVS_LEANVEC_HEADER
23+
#include "dynamic_vamana_index_leanvec_impl.h"
24+
#endif
25+
2226
#include <algorithm>
2327
#include <memory>
2428
#include <variant>
@@ -27,15 +31,11 @@
2731
#include <svs/core/data.h>
2832
#include <svs/core/distance.h>
2933
#include <svs/core/query_result.h>
30-
#include <svs/cpuid.h>
3134
#include <svs/extensions/vamana/scalar.h>
3235
#include <svs/lib/float16.h>
3336
#include <svs/orchestrators/dynamic_vamana.h>
3437
#include <svs/quantization/scalar/scalar.h>
3538

36-
#include SVS_LVQ_HEADER
37-
#include SVS_LEANVEC_HEADER
38-
3939
namespace svs {
4040
namespace runtime {
4141

@@ -117,11 +117,6 @@ struct DynamicVamanaIndexManagerBase : public DynamicVamanaIndex {
117117
return runtime_error_wrapper([&] { impl_->save(out); });
118118
}
119119
};
120-
121-
using DynamicVamanaIndexManager = DynamicVamanaIndexManagerBase<DynamicVamanaIndexImpl>;
122-
using DynamicVamanaIndexLeanVecImplManager =
123-
DynamicVamanaIndexManagerBase<DynamicVamanaIndexLeanVecImpl>;
124-
125120
} // namespace
126121

127122
// DynamicVamanaIndex interface implementation
@@ -149,12 +144,13 @@ Status DynamicVamanaIndex::build(
149144
const DynamicVamanaIndex::BuildParams& params,
150145
const DynamicVamanaIndex::SearchParams& default_search_params
151146
) noexcept {
147+
using Impl = DynamicVamanaIndexImpl;
152148
*index = nullptr;
153149
return runtime_error_wrapper([&] {
154-
auto impl = std::make_unique<DynamicVamanaIndexImpl>(
150+
auto impl = std::make_unique<Impl>(
155151
dim, metric, storage_kind, params, default_search_params
156152
);
157-
*index = new DynamicVamanaIndexManager{std::move(impl)};
153+
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
158154
});
159155
}
160156

@@ -168,14 +164,15 @@ Status DynamicVamanaIndex::load(
168164
MetricType metric,
169165
StorageKind storage_kind
170166
) noexcept {
167+
using Impl = DynamicVamanaIndexImpl;
171168
*index = nullptr;
172169
return runtime_error_wrapper([&] {
173-
std::unique_ptr<DynamicVamanaIndexImpl> impl{
174-
DynamicVamanaIndexImpl::load(in, metric, storage_kind)};
175-
*index = new DynamicVamanaIndexManager{std::move(impl)};
170+
std::unique_ptr<Impl> impl{Impl::load(in, metric, storage_kind)};
171+
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
176172
});
177173
}
178174

175+
#ifdef SVS_LEANVEC_HEADER
179176
// Specialization to build LeanVec-based Vamana index with specified leanvec dims
180177
Status DynamicVamanaIndexLeanVec::build(
181178
DynamicVamanaIndex** index,
@@ -186,12 +183,13 @@ Status DynamicVamanaIndexLeanVec::build(
186183
const DynamicVamanaIndex::BuildParams& params,
187184
const DynamicVamanaIndex::SearchParams& default_search_params
188185
) noexcept {
186+
using Impl = DynamicVamanaIndexLeanVecImpl;
189187
*index = nullptr;
190188
return runtime_error_wrapper([&] {
191-
auto impl = std::make_unique<DynamicVamanaIndexLeanVecImpl>(
189+
auto impl = std::make_unique<Impl>(
192190
dim, metric, storage_kind, leanvec_dims, params, default_search_params
193191
);
194-
*index = new DynamicVamanaIndexLeanVecImplManager{std::move(impl)};
192+
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
195193
});
196194
}
197195

@@ -205,16 +203,35 @@ Status DynamicVamanaIndexLeanVec::build(
205203
const DynamicVamanaIndex::BuildParams& params,
206204
const DynamicVamanaIndex::SearchParams& default_search_params
207205
) noexcept {
206+
using Impl = DynamicVamanaIndexLeanVecImpl;
208207
*index = nullptr;
209208
return runtime_error_wrapper([&] {
210209
auto training_data_impl =
211210
static_cast<const LeanVecTrainingDataManager*>(training_data)->impl_;
212-
auto impl = std::make_unique<DynamicVamanaIndexLeanVecImpl>(
211+
auto impl = std::make_unique<Impl>(
213212
dim, metric, storage_kind, training_data_impl, params, default_search_params
214213
);
215-
*index = new DynamicVamanaIndexLeanVecImplManager{std::move(impl)};
214+
*index = new DynamicVamanaIndexManagerBase<Impl>{std::move(impl)};
216215
});
217216
}
218217

218+
#else // SVS_LEANVEC_HEADER
219+
// LeanVec storage kind is not supported in this build configuration
220+
Status DynamicVamanaIndexLeanVec::
221+
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, size_t, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&) noexcept {
222+
return Status(
223+
ErrorCode::NOT_IMPLEMENTED,
224+
"DynamicVamanaIndexLeanVec is not supported in this build configuration."
225+
);
226+
}
227+
228+
Status DynamicVamanaIndexLeanVec::
229+
build(DynamicVamanaIndex**, size_t, MetricType, StorageKind, const LeanVecTrainingData*, const DynamicVamanaIndex::BuildParams&, const DynamicVamanaIndex::SearchParams&) noexcept {
230+
return Status(
231+
ErrorCode::NOT_IMPLEMENTED,
232+
"DynamicVamanaIndexLeanVec is not supported in this build configuration."
233+
);
234+
}
235+
#endif // SVS_LEANVEC_HEADER
219236
} // namespace runtime
220237
} // namespace svs

0 commit comments

Comments
 (0)