milvus-io--milvus
498b235461
Build and test / Build and test AMD64 Ubuntu 22.04 (push) Failing after 0s
Publish Builder / amazonlinux2023 (push) Failing after 1s
Build and test / UT for Go (push) Has been skipped
Publish KRTE Images / KRTE (push) Failing after 1s
Build and test / Integration Test (push) Has been skipped
Build and test / Upload Code Coverage (push) Has been skipped
Publish Builder / rockylinux9 (push) Failing after 1s
Publish Builder / ubuntu22.04 (push) Failing after 0s
Publish Builder / ubuntu24.04 (push) Failing after 0s
Publish Gpu Builder / publish-gpu-builder (push) Failing after 1s
Publish Test Images / PyTest (push) Failing after 0s
Build and test / UT for Cpp (push) Has been cancelled
755 行
28 KiB
C++
755 行
28 KiB
C++
// Licensed to the LF AI & Data foundation under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
#pragma once
|
|
|
|
#include <folly/io/IOBuf.h>
|
|
#include <sys/mman.h>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <cmath>
|
|
|
|
#include "cachinglayer/CacheSlot.h"
|
|
#include "cachinglayer/Manager.h"
|
|
#include "cachinglayer/Translator.h"
|
|
#include "cachinglayer/Utils.h"
|
|
|
|
#include "common/Chunk.h"
|
|
#include "common/GroupChunk.h"
|
|
#include "common/EasyAssert.h"
|
|
#include "common/FastMem.h"
|
|
#include "common/OpContext.h"
|
|
#include "common/Span.h"
|
|
#include "mmap/ChunkedColumnInterface.h"
|
|
#include "segcore/storagev2translator/GroupCTMeta.h"
|
|
|
|
namespace milvus {
|
|
|
|
using GroupChunkVector = std::vector<std::shared_ptr<GroupChunk>>;
|
|
|
|
using namespace milvus::cachinglayer;
|
|
|
|
// ChunkedColumnGroup represents a collection of group chunks
|
|
class ChunkedColumnGroup {
|
|
public:
|
|
explicit ChunkedColumnGroup(
|
|
std::unique_ptr<Translator<GroupChunk>> translator)
|
|
: slot_(Manager::GetInstance().CreateCacheSlot(std::move(translator))) {
|
|
num_chunks_ = slot_->num_cells();
|
|
num_rows_ = GetNumRowsUntilChunk().back();
|
|
}
|
|
|
|
virtual ~ChunkedColumnGroup() {
|
|
slot_->CancelWarmup();
|
|
}
|
|
|
|
void
|
|
ManualEvictCache() const {
|
|
slot_->ManualEvictAll();
|
|
}
|
|
|
|
void
|
|
CancelWarmup() {
|
|
slot_->CancelWarmup();
|
|
}
|
|
|
|
// Get the number of group chunks
|
|
size_t
|
|
num_chunks() const {
|
|
return num_chunks_;
|
|
}
|
|
|
|
PinWrapper<GroupChunk*>
|
|
GetGroupChunk(milvus::OpContext* op_ctx, int64_t chunk_id) const {
|
|
AssertInfo(
|
|
chunk_id >= 0 && chunk_id < num_chunks_,
|
|
"[StorageV2] chunk_id out of range: " + std::to_string(chunk_id) +
|
|
", num_chunks: " + std::to_string(num_chunks_));
|
|
auto ca = SemiInlineGet(slot_->PinCells(op_ctx, {chunk_id}));
|
|
auto chunk = ca->get_cell_of(chunk_id);
|
|
return PinWrapper<GroupChunk*>(std::move(ca), chunk);
|
|
}
|
|
|
|
std::shared_ptr<CellAccessor<GroupChunk>>
|
|
GetGroupChunks(milvus::OpContext* op_ctx,
|
|
const std::vector<int64_t>& chunk_ids) {
|
|
for (auto chunk_id : chunk_ids) {
|
|
AssertInfo(chunk_id >= 0 && chunk_id < num_chunks_,
|
|
"[StorageV2] chunk_id out of range: " +
|
|
std::to_string(chunk_id) +
|
|
", num_chunks: " + std::to_string(num_chunks_));
|
|
}
|
|
return SemiInlineGet(slot_->PinCells(op_ctx, chunk_ids));
|
|
}
|
|
|
|
bool
|
|
CellsLoaded(const std::vector<cachinglayer::cid_t>& cids) const {
|
|
return std::all_of(cids.begin(), cids.end(), [this](cid_t cid) {
|
|
return slot_->IsCached(cid);
|
|
});
|
|
}
|
|
|
|
std::vector<PinWrapper<GroupChunk*>>
|
|
GetAllGroupChunks(milvus::OpContext* op_ctx) {
|
|
auto ca = SemiInlineGet(slot_->PinAllCells(op_ctx));
|
|
std::vector<PinWrapper<GroupChunk*>> ret;
|
|
ret.reserve(num_chunks_);
|
|
for (size_t i = 0; i < num_chunks_; i++) {
|
|
auto chunk = ca->get_cell_of(i);
|
|
ret.emplace_back(ca, chunk);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t
|
|
NumRows() const {
|
|
return num_rows_;
|
|
}
|
|
|
|
int64_t
|
|
GetNumRowsUntilChunk(int64_t chunk_id) const {
|
|
AssertInfo(
|
|
chunk_id >= 0 && chunk_id <= num_chunks_,
|
|
"[StorageV2] chunk_id out of range: " + std::to_string(chunk_id));
|
|
return GetNumRowsUntilChunk()[chunk_id];
|
|
}
|
|
|
|
const std::vector<int64_t>&
|
|
GetNumRowsUntilChunk() const {
|
|
auto meta =
|
|
static_cast<milvus::segcore::storagev2translator::GroupCTMeta*>(
|
|
slot_->meta());
|
|
return meta->num_rows_until_chunk_;
|
|
}
|
|
|
|
std::pair<size_t, size_t>
|
|
GetChunkIDByOffset(int64_t offset) const {
|
|
const auto& num_rows_until_chunk = GetNumRowsUntilChunk();
|
|
auto iter = std::lower_bound(num_rows_until_chunk.begin(),
|
|
num_rows_until_chunk.end(),
|
|
offset + 1);
|
|
size_t chunk_idx =
|
|
std::distance(num_rows_until_chunk.begin(), iter) - 1;
|
|
size_t offset_in_chunk = offset - num_rows_until_chunk[chunk_idx];
|
|
return {chunk_idx, offset_in_chunk};
|
|
}
|
|
|
|
std::pair<std::vector<milvus::cachinglayer::cid_t>, std::vector<int64_t>>
|
|
GetChunkIDsByOffsets(const int64_t* offsets, int64_t count) {
|
|
const auto& num_rows_until_chunk = GetNumRowsUntilChunk();
|
|
std::vector<milvus::cachinglayer::cid_t> cids(count, 1);
|
|
std::vector<int64_t> offsets_in_chunk(count);
|
|
int64_t len = num_rows_until_chunk.size() - 1;
|
|
while (len > 1) {
|
|
const int64_t half = len / 2;
|
|
len -= half;
|
|
for (size_t i = 0; i < count; ++i) {
|
|
const bool cmp =
|
|
num_rows_until_chunk[cids[i] + half - 1] < offsets[i] + 1;
|
|
cids[i] += static_cast<int64_t>(cmp) * half;
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < count; ++i) {
|
|
offsets_in_chunk[i] = offsets[i] - num_rows_until_chunk[--cids[i]];
|
|
}
|
|
|
|
return std::make_pair(std::move(cids), std::move(offsets_in_chunk));
|
|
}
|
|
|
|
size_t
|
|
NumFieldsInGroup() const {
|
|
auto meta =
|
|
static_cast<milvus::segcore::storagev2translator::GroupCTMeta*>(
|
|
slot_->meta());
|
|
return meta->num_fields_;
|
|
}
|
|
|
|
size_t
|
|
memory_size() const {
|
|
auto meta =
|
|
static_cast<milvus::segcore::storagev2translator::GroupCTMeta*>(
|
|
slot_->meta());
|
|
size_t memory_size = 0;
|
|
for (auto& size : meta->chunk_memory_size_) {
|
|
memory_size += size;
|
|
}
|
|
return memory_size;
|
|
}
|
|
|
|
protected:
|
|
mutable std::shared_ptr<CacheSlot<GroupChunk>> slot_;
|
|
size_t num_chunks_{0};
|
|
size_t num_rows_{0};
|
|
};
|
|
|
|
class ProxyChunkColumn : public ChunkedColumnInterface {
|
|
public:
|
|
explicit ProxyChunkColumn(std::shared_ptr<ChunkedColumnGroup> group,
|
|
FieldId field_id,
|
|
const FieldMeta& field_meta)
|
|
: group_(group),
|
|
field_id_(field_id),
|
|
field_meta_(field_meta),
|
|
data_type_(field_meta.get_data_type()) {
|
|
}
|
|
|
|
~ProxyChunkColumn() override {
|
|
CancelWarmup();
|
|
}
|
|
|
|
bool
|
|
IsInMultiFieldColumnGroup() const override {
|
|
return group_->NumFieldsInGroup() > 1;
|
|
}
|
|
|
|
void
|
|
ManualEvictCache() const override {
|
|
if (group_->NumFieldsInGroup() == 1) {
|
|
group_->ManualEvictCache();
|
|
}
|
|
}
|
|
|
|
void
|
|
CancelWarmup() override {
|
|
if (group_->NumFieldsInGroup() == 1) {
|
|
group_->CancelWarmup();
|
|
}
|
|
}
|
|
|
|
PinWrapper<const char*>
|
|
DataOfChunk(milvus::OpContext* op_ctx, int chunk_id) const override {
|
|
auto group_chunk = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = group_chunk.get()->GetChunk(field_id_);
|
|
return PinWrapper<const char*>(std::move(group_chunk), chunk->Data());
|
|
}
|
|
|
|
bool
|
|
IsValid(milvus::OpContext* op_ctx, size_t offset) const override {
|
|
auto [chunk_id, offset_in_chunk] = group_->GetChunkIDByOffset(offset);
|
|
auto group_chunk = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = group_chunk.get()->GetChunk(field_id_);
|
|
return chunk->isValid(offset_in_chunk);
|
|
}
|
|
|
|
void
|
|
BulkIsValid(milvus::OpContext* op_ctx,
|
|
std::function<void(bool, size_t)> fn,
|
|
const int64_t* offsets = nullptr,
|
|
int64_t count = 0) const override {
|
|
if (!field_meta_.is_nullable()) {
|
|
if (offsets == nullptr) {
|
|
for (int64_t i = 0; i < group_->NumRows(); i++) {
|
|
fn(true, i);
|
|
}
|
|
} else {
|
|
for (int64_t i = 0; i < count; i++) {
|
|
fn(true, i);
|
|
}
|
|
}
|
|
}
|
|
// nullable:
|
|
if (count == 0) {
|
|
return;
|
|
}
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto valid = chunk->isValid(offsets_in_chunk[i]);
|
|
fn(valid, i);
|
|
}
|
|
}
|
|
|
|
bool
|
|
IsNullable() const override {
|
|
return field_meta_.is_nullable();
|
|
}
|
|
|
|
size_t
|
|
NumRows() const override {
|
|
return group_->NumRows();
|
|
}
|
|
|
|
int64_t
|
|
num_chunks() const override {
|
|
return group_->num_chunks();
|
|
}
|
|
|
|
size_t
|
|
DataByteSize() const override {
|
|
return group_->memory_size();
|
|
}
|
|
|
|
int64_t
|
|
chunk_row_nums(int64_t chunk_id) const override {
|
|
return group_->GetNumRowsUntilChunk(chunk_id + 1) -
|
|
group_->GetNumRowsUntilChunk(chunk_id);
|
|
}
|
|
|
|
// TODO(tiered storage): make it async
|
|
void
|
|
PrefetchChunks(milvus::OpContext* op_ctx,
|
|
const std::vector<int64_t>& chunk_ids) const override {
|
|
group_->GetGroupChunks(op_ctx, chunk_ids);
|
|
}
|
|
|
|
bool
|
|
CellsLoaded(const int64_t* offsets, int64_t count) const override {
|
|
if (count == 0) {
|
|
return true;
|
|
}
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
return group_->CellsLoaded(cids);
|
|
}
|
|
|
|
PinWrapper<SpanBase>
|
|
Span(milvus::OpContext* op_ctx, int64_t chunk_id) const override {
|
|
if (!IsChunkedColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] Span only supported for ChunkedColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<SpanBase>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<FixedWidthChunk*>(chunk.get())->Span());
|
|
}
|
|
|
|
PinWrapper<std::pair<std::vector<std::string_view>, FixedVector<bool>>>
|
|
StringViews(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id,
|
|
std::optional<std::pair<int64_t, int64_t>> offset_len =
|
|
std::nullopt) const override {
|
|
if (!IsChunkedVariableColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] StringViews only supported for "
|
|
"ChunkedVariableColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<
|
|
std::pair<std::vector<std::string_view>, FixedVector<bool>>>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<StringChunk*>(chunk.get())->StringViews(offset_len));
|
|
}
|
|
|
|
PinWrapper<std::pair<std::vector<ArrayView>, FixedVector<bool>>>
|
|
ArrayViews(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id,
|
|
std::optional<std::pair<int64_t, int64_t>> offset_len =
|
|
std::nullopt) const override {
|
|
if (!IsChunkedArrayColumnDataType(data_type_)) {
|
|
ThrowInfo(
|
|
ErrorCode::Unsupported,
|
|
"[StorageV2] ArrayViews only supported for ChunkedArrayColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<std::pair<std::vector<ArrayView>, FixedVector<bool>>>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<ArrayChunk*>(chunk.get())->Views(offset_len));
|
|
}
|
|
|
|
PinWrapper<std::pair<std::vector<VectorArrayView>, FixedVector<bool>>>
|
|
VectorArrayViews(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id,
|
|
std::optional<std::pair<int64_t, int64_t>> offset_len =
|
|
std::nullopt) const override {
|
|
if (!IsChunkedVectorArrayColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] VectorArrayViews only supported for "
|
|
"ChunkedVectorArrayColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<
|
|
std::pair<std::vector<VectorArrayView>, FixedVector<bool>>>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<VectorArrayChunk*>(chunk.get())->Views(offset_len));
|
|
}
|
|
|
|
PinWrapper<const size_t*>
|
|
VectorArrayOffsets(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id) const override {
|
|
if (!IsChunkedVectorArrayColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"VectorArrayOffsets only supported for "
|
|
"ChunkedVectorArrayColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<const size_t*>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<VectorArrayChunk*>(chunk.get())->Offsets());
|
|
}
|
|
|
|
PinWrapper<std::pair<std::vector<std::string_view>, FixedVector<bool>>>
|
|
StringViewsByOffsets(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id,
|
|
const FixedVector<int32_t>& offsets) const override {
|
|
if (!IsChunkedVariableColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] ViewsByOffsets only supported for "
|
|
"ChunkedVariableColumn");
|
|
}
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<
|
|
std::pair<std::vector<std::string_view>, FixedVector<bool>>>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<StringChunk*>(chunk.get())->ViewsByOffsets(offsets));
|
|
}
|
|
|
|
PinWrapper<std::pair<std::vector<ArrayView>, FixedVector<bool>>>
|
|
ArrayViewsByOffsets(milvus::OpContext* op_ctx,
|
|
int64_t chunk_id,
|
|
const FixedVector<int32_t>& offsets) const override {
|
|
auto chunk_wrapper = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = chunk_wrapper.get()->GetChunk(field_id_);
|
|
return PinWrapper<std::pair<std::vector<ArrayView>, FixedVector<bool>>>(
|
|
std::move(chunk_wrapper),
|
|
static_cast<ArrayChunk*>(chunk.get())->ViewsByOffsets(offsets));
|
|
}
|
|
|
|
std::pair<size_t, size_t>
|
|
GetChunkIDByOffset(int64_t offset) const override {
|
|
return group_->GetChunkIDByOffset(offset);
|
|
}
|
|
|
|
std::pair<std::vector<milvus::cachinglayer::cid_t>, std::vector<int64_t>>
|
|
GetChunkIDsByOffsets(const int64_t* offsets, int64_t count) const override {
|
|
return group_->GetChunkIDsByOffsets(offsets, count);
|
|
}
|
|
|
|
PinWrapper<Chunk*>
|
|
GetChunk(milvus::OpContext* op_ctx, int64_t chunk_id) const override {
|
|
auto group_chunk = group_->GetGroupChunk(op_ctx, chunk_id);
|
|
auto chunk = group_chunk.get()->GetChunk(field_id_);
|
|
return PinWrapper<Chunk*>(std::move(group_chunk), chunk.get());
|
|
}
|
|
|
|
std::vector<PinWrapper<Chunk*>>
|
|
GetAllChunks(milvus::OpContext* op_ctx) const override {
|
|
std::vector<PinWrapper<Chunk*>> ret;
|
|
auto group_chunks = group_->GetAllGroupChunks(op_ctx);
|
|
ret.reserve(group_chunks.size());
|
|
|
|
for (auto& group_chunk : group_chunks) {
|
|
auto chunk = group_chunk.get()->GetChunk(field_id_);
|
|
ret.emplace_back(std::move(group_chunk), chunk.get());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int64_t
|
|
GetNumRowsUntilChunk(int64_t chunk_id) const override {
|
|
return group_->GetNumRowsUntilChunk(chunk_id);
|
|
}
|
|
|
|
const std::vector<int64_t>&
|
|
GetNumRowsUntilChunk() const override {
|
|
return group_->GetNumRowsUntilChunk();
|
|
}
|
|
|
|
void
|
|
BulkValueAt(milvus::OpContext* op_ctx,
|
|
std::function<void(const char*, size_t)> fn,
|
|
const int64_t* offsets,
|
|
int64_t count) override {
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto offset = offsets_in_chunk[i];
|
|
if (field_meta_.is_nullable() && IsVectorDataType(data_type_)) {
|
|
offset = chunk->PhysicalOffsetOf(offset);
|
|
}
|
|
fn(chunk->ValueAt(offset), i);
|
|
}
|
|
}
|
|
|
|
template <typename S, typename T>
|
|
void
|
|
BulkPrimitiveValueAtImpl(milvus::OpContext* op_ctx,
|
|
void* dst,
|
|
const int64_t* offsets,
|
|
int64_t count) {
|
|
static_assert(std::is_fundamental_v<S> && std::is_fundamental_v<T>);
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
auto typed_dst = static_cast<T*>(dst);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto value = chunk->ValueAt(offsets_in_chunk[i]);
|
|
typed_dst[i] =
|
|
*static_cast<const S*>(static_cast<const void*>(value));
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkPrimitiveValueAt(milvus::OpContext* op_ctx,
|
|
void* dst,
|
|
const int64_t* offsets,
|
|
int64_t count,
|
|
bool small_int_raw_type) override {
|
|
switch (data_type_) {
|
|
case DataType::INT8: {
|
|
if (small_int_raw_type) {
|
|
BulkPrimitiveValueAtImpl<int8_t, int8_t>(
|
|
op_ctx, dst, offsets, count);
|
|
} else {
|
|
BulkPrimitiveValueAtImpl<int8_t, int32_t>(
|
|
op_ctx, dst, offsets, count);
|
|
}
|
|
break;
|
|
}
|
|
case DataType::INT16: {
|
|
if (small_int_raw_type) {
|
|
BulkPrimitiveValueAtImpl<int16_t, int16_t>(
|
|
op_ctx, dst, offsets, count);
|
|
} else {
|
|
BulkPrimitiveValueAtImpl<int16_t, int32_t>(
|
|
op_ctx, dst, offsets, count);
|
|
}
|
|
break;
|
|
}
|
|
case DataType::INT32: {
|
|
BulkPrimitiveValueAtImpl<int32_t, int32_t>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
case DataType::INT64: {
|
|
BulkPrimitiveValueAtImpl<int64_t, int64_t>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
case DataType::TIMESTAMPTZ: {
|
|
BulkPrimitiveValueAtImpl<int64_t, int64_t>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
case DataType::FLOAT: {
|
|
BulkPrimitiveValueAtImpl<float, float>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
case DataType::DOUBLE: {
|
|
BulkPrimitiveValueAtImpl<double, double>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
case DataType::BOOL: {
|
|
BulkPrimitiveValueAtImpl<bool, bool>(
|
|
op_ctx, dst, offsets, count);
|
|
break;
|
|
}
|
|
default: {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] BulkScalarValueAt is not supported for "
|
|
"unknown scalar "
|
|
"data type: {}",
|
|
data_type_);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkVectorValueAt(milvus::OpContext* op_ctx,
|
|
void* dst,
|
|
const int64_t* offsets,
|
|
int64_t element_sizeof,
|
|
int64_t count) override {
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
auto dst_vec = reinterpret_cast<char*>(dst);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto offset = offsets_in_chunk[i];
|
|
if (field_meta_.is_nullable()) {
|
|
offset = chunk->PhysicalOffsetOf(offset);
|
|
}
|
|
auto value = chunk->ValueAt(offset);
|
|
milvus::fastmem::FastMemcpy(
|
|
dst_vec + i * element_sizeof, value, element_sizeof);
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkRawStringAt(milvus::OpContext* op_ctx,
|
|
std::function<void(std::string_view, size_t, bool)> fn,
|
|
const int64_t* offsets = nullptr,
|
|
int64_t count = 0) const override {
|
|
if (!IsChunkedVariableColumnDataType(data_type_) ||
|
|
data_type_ == DataType::JSON) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] BulkRawStringAt only supported for "
|
|
"ProxyChunkColumn of "
|
|
"variable length type(except Json)");
|
|
}
|
|
if (offsets == nullptr) {
|
|
int64_t current_offset = 0;
|
|
for (cid_t cid = 0; cid < num_chunks(); ++cid) {
|
|
auto group_chunk = group_->GetGroupChunk(op_ctx, cid);
|
|
auto chunk = group_chunk.get()->GetChunk(field_id_);
|
|
auto chunk_rows = chunk->RowNums();
|
|
for (int64_t i = 0; i < chunk_rows; ++i) {
|
|
auto valid = chunk->isValid(i);
|
|
auto value =
|
|
static_cast<StringChunk*>(chunk.get())->operator[](i);
|
|
fn(value, current_offset + i, valid);
|
|
}
|
|
current_offset += chunk_rows;
|
|
}
|
|
} else {
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
std::vector<std::shared_ptr<Chunk>> chunks(num_chunks());
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto cid = cids[i];
|
|
auto& chunk = chunks[cid];
|
|
if (chunk == nullptr) {
|
|
auto* group_chunk = ca->get_cell_of(cid);
|
|
chunk = group_chunk->GetChunk(field_id_);
|
|
}
|
|
auto valid = chunk->isValid(offsets_in_chunk[i]);
|
|
auto value = static_cast<StringChunk*>(chunk.get())
|
|
->
|
|
operator[](offsets_in_chunk[i]);
|
|
fn(value, i, valid);
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO(tiered storage 2): replace with Bulk version
|
|
void
|
|
BulkRawJsonAt(milvus::OpContext* op_ctx,
|
|
std::function<void(Json, size_t, bool)> fn,
|
|
const int64_t* offsets,
|
|
int64_t count) const override {
|
|
if (data_type_ != DataType::JSON) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] RawJsonAt only supported for "
|
|
"ProxyChunkColumn of Json type");
|
|
}
|
|
if (count == 0) {
|
|
return;
|
|
}
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto valid = chunk->isValid(offsets_in_chunk[i]);
|
|
auto str_view = static_cast<StringChunk*>(chunk.get())
|
|
->
|
|
operator[](offsets_in_chunk[i]);
|
|
fn(Json(str_view.data(), str_view.size()), i, valid);
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkRawBsonAt(milvus::OpContext* op_ctx,
|
|
std::function<void(BsonView, uint32_t, uint32_t)> fn,
|
|
const uint32_t* row_offsets,
|
|
const uint32_t* value_offsets,
|
|
int64_t count) const override {
|
|
if (data_type_ != DataType::STRING) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"BulkRawBsonAt only supported for ProxyChunkColumn of "
|
|
"Bson type");
|
|
}
|
|
if (count == 0) {
|
|
return;
|
|
}
|
|
|
|
AssertInfo(row_offsets != nullptr, "row_offsets is nullptr");
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(row_offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto str_view = static_cast<StringChunk*>(chunk.get())
|
|
->
|
|
operator[](offsets_in_chunk[i]);
|
|
fn(BsonView(reinterpret_cast<const uint8_t*>(str_view.data()),
|
|
str_view.size()),
|
|
row_offsets[i],
|
|
value_offsets[i]);
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkArrayAt(milvus::OpContext* op_ctx,
|
|
std::function<void(const ArrayView&, size_t)> fn,
|
|
const int64_t* offsets,
|
|
int64_t count) const override {
|
|
if (!IsChunkedArrayColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] BulkArrayAt only supported for "
|
|
"ChunkedArrayColumn");
|
|
}
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto view = static_cast<ArrayChunk*>(chunk.get())
|
|
->View(offsets_in_chunk[i]);
|
|
fn(view, i);
|
|
}
|
|
}
|
|
|
|
void
|
|
BulkVectorArrayAt(milvus::OpContext* op_ctx,
|
|
std::function<void(VectorFieldProto&&, size_t)> fn,
|
|
const int64_t* offsets,
|
|
int64_t count) const override {
|
|
if (!IsChunkedVectorArrayColumnDataType(data_type_)) {
|
|
ThrowInfo(ErrorCode::Unsupported,
|
|
"[StorageV2] BulkVectorArrayAt only supported for "
|
|
"ChunkedVectorArrayColumn");
|
|
}
|
|
auto [cids, offsets_in_chunk] = ToChunkIdAndOffset(offsets, count);
|
|
auto ca = group_->GetGroupChunks(op_ctx, cids);
|
|
for (int64_t i = 0; i < count; i++) {
|
|
auto* group_chunk = ca->get_cell_of(cids[i]);
|
|
auto chunk = group_chunk->GetChunk(field_id_);
|
|
auto offset = offsets_in_chunk[i];
|
|
auto array = static_cast<VectorArrayChunk*>(chunk.get())
|
|
->View(offset)
|
|
.output_data();
|
|
fn(std::move(array), i);
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<ChunkedColumnGroup> group_;
|
|
FieldId field_id_;
|
|
const FieldMeta field_meta_;
|
|
DataType data_type_;
|
|
};
|
|
|
|
} // namespace milvus
|