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 Implementation of forward searcher
19 */
20
21#include "simple_forward_reader.h"
22#include "common/error_code.h"
23
24namespace proxima {
25namespace be {
26namespace index {
27
28SimpleForwardReader::~SimpleForwardReader() {
29 // TODO can't call virtual function
30 if (opened_) {
31 close();
32 }
33}
34
35int SimpleForwardReader::open(const ReadOptions &read_options) {
36 CHECK_STATUS(opened_, false);
37
38 int ret = open_proxima_container(read_options);
39 CHECK_RETURN(ret, 0);
40
41 ret = open_forward_searcher();
42 CHECK_RETURN(ret, 0);
43
44 opened_ = true;
45 return 0;
46}
47
48int SimpleForwardReader::close() {
49 CHECK_STATUS(opened_, true);
50
51 forward_searcher_->unload();
52 opened_ = false;
53 return 0;
54}
55
56int SimpleForwardReader::seek(idx_t doc_id, ForwardData *forward) {
57 CHECK_STATUS(opened_, true);
58
59 uint64_t index = doc_id - this->start_doc_id();
60 std::string buffer;
61 int ret = forward_searcher_->fetch(index, &buffer);
62 CHECK_RETURN_WITH_SLOG(ret, 0, "Forward searcher fetch failed.");
63
64 forward->deserialize(buffer);
65 return 0;
66}
67
68int SimpleForwardReader::open_proxima_container(
69 const ReadOptions &read_options) {
70 index_file_path_ = FileHelper::MakeFilePath(
71 this->collection_path(), FileID::SEGMENT_FILE, this->segment_id());
72
73 if (read_options.use_mmap) {
74 container_ = aitheta2::IndexFactory::CreateContainer("MMapFileContainer");
75 } else {
76 container_ = aitheta2::IndexFactory::CreateContainer("MemoryContainer");
77 }
78
79 // Default set warmup flag
80 IndexParams container_params;
81 container_params.set("proxima.mmap_file.container.memory_warmup", true);
82
83 int ret = container_->init(container_params);
84 CHECK_RETURN_WITH_LLOG(ret, 0, "Container init failed. ret[%d]", ret);
85
86 ret = container_->load(index_file_path_);
87 CHECK_RETURN_WITH_LLOG(ret, 0, "Container load failed. ret[%d] file[%s]", ret,
88 index_file_path_.c_str());
89
90 return 0;
91}
92
93int SimpleForwardReader::open_forward_searcher() {
94 forward_searcher_ =
95 aitheta2::IndexFactory::CreateImmutableCloset("ChainImmutableCloset");
96 if (!forward_searcher_) {
97 SLOG_ERROR("Create proxima forward searcher failed.");
98 return ErrorCode_RuntimeError;
99 }
100
101 auto forward_block = container_->get(FORWARD_DUMP_BLOCK);
102 if (!forward_block) {
103 LLOG_ERROR("Can't find forward block in index file");
104 return ErrorCode_InvalidSegment;
105 }
106
107 auto block_container =
108 std::make_shared<aitheta2::IndexSegmentContainer>(forward_block);
109 int ret = block_container->load();
110 CHECK_RETURN_WITH_SLOG(ret, 0, "Load forward container failed.");
111
112
113 ret = forward_searcher_->load(block_container);
114 CHECK_RETURN_WITH_SLOG(ret, 0,
115 "Load proxima forward searcher failed. ret[%d]", ret);
116
117 return 0;
118}
119
120
121} // end namespace index
122} // namespace be
123} // end namespace proxima
124