be/src/storage/segment/rle_page.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | #pragma once |
19 | | |
20 | | #include "common/cast_set.h" |
21 | | #include "storage/field_type.h" // for FieldType |
22 | | #include "storage/segment/options.h" // for PageBuilderOptions/PageDecoderOptions |
23 | | #include "storage/segment/page_builder.h" // for PageBuilder |
24 | | #include "storage/segment/page_decoder.h" // for PageDecoder |
25 | | #include "storage/types.h" // for TypeTraits |
26 | | #include "util/coding.h" // for encode_fixed32_le/decode_fixed32_le |
27 | | #include "util/rle_encoding.h" // for RleEncoder/RleDecoder |
28 | | #include "util/slice.h" // for OwnedSlice |
29 | | |
30 | | namespace doris { |
31 | | namespace segment_v2 { |
32 | | |
33 | | enum { RLE_PAGE_HEADER_SIZE = 4 }; |
34 | | |
35 | | // RLE builder for generic integer and bool types. What is missing is some way |
36 | | // to enforce that this can only be instantiated for INT and BOOL types. |
37 | | // |
38 | | // The page format is as follows: |
39 | | // |
40 | | // 1. Header: (4 bytes total) |
41 | | // |
42 | | // <num_elements> [32-bit] |
43 | | // The number of elements encoded in the page. |
44 | | // |
45 | | // NOTE: all on-disk ints are encoded little-endian |
46 | | // |
47 | | // 2. Element data |
48 | | // |
49 | | // The header is followed by the rle-encoded element data. |
50 | | // |
51 | | // This Rle encoding algorithm is only effective for repeated INT type and bool type, |
52 | | // It is not good for sequence number or random number. BitshufflePage is recommended |
53 | | // for these case. |
54 | | // |
55 | | // TODO(hkp): optimize rle algorithm |
56 | | template <FieldType Type> |
57 | | class RlePageBuilder : public PageBuilderHelper<RlePageBuilder<Type> > { |
58 | | public: |
59 | | using Self = RlePageBuilder<Type>; |
60 | | friend class PageBuilderHelper<Self>; |
61 | | |
62 | 205 | Status init() override { |
63 | 205 | switch (Type) { |
64 | 201 | case FieldType::OLAP_FIELD_TYPE_BOOL: { |
65 | 201 | _bit_width = 1; |
66 | 201 | break; |
67 | 0 | } |
68 | 4 | default: { |
69 | 4 | _bit_width = SIZE_OF_TYPE * 8; |
70 | 4 | break; |
71 | 0 | } |
72 | 205 | } |
73 | 205 | _rle_encoder = new RleEncoder<CppType>(&_buf, _bit_width); |
74 | 205 | return reset(); |
75 | 205 | } _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE4initEv Line | Count | Source | 62 | 4 | Status init() override { | 63 | 4 | switch (Type) { | 64 | 0 | case FieldType::OLAP_FIELD_TYPE_BOOL: { | 65 | 0 | _bit_width = 1; | 66 | 0 | break; | 67 | 0 | } | 68 | 4 | default: { | 69 | 4 | _bit_width = SIZE_OF_TYPE * 8; | 70 | 4 | break; | 71 | 0 | } | 72 | 4 | } | 73 | 4 | _rle_encoder = new RleEncoder<CppType>(&_buf, _bit_width); | 74 | 4 | return reset(); | 75 | 4 | } |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE4initEv Line | Count | Source | 62 | 201 | Status init() override { | 63 | 201 | switch (Type) { | 64 | 201 | case FieldType::OLAP_FIELD_TYPE_BOOL: { | 65 | 201 | _bit_width = 1; | 66 | 201 | break; | 67 | 0 | } | 68 | 0 | default: { | 69 | 0 | _bit_width = SIZE_OF_TYPE * 8; | 70 | 0 | break; | 71 | 0 | } | 72 | 201 | } | 73 | 201 | _rle_encoder = new RleEncoder<CppType>(&_buf, _bit_width); | 74 | 201 | return reset(); | 75 | 201 | } |
|
76 | | |
77 | 205 | ~RlePageBuilder() { delete _rle_encoder; }_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EED2Ev Line | Count | Source | 77 | 4 | ~RlePageBuilder() { delete _rle_encoder; } |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EED2Ev Line | Count | Source | 77 | 201 | ~RlePageBuilder() { delete _rle_encoder; } |
|
78 | | |
79 | 392 | bool is_page_full() override { return _rle_encoder->len() >= _options.data_page_size; }Unexecuted instantiation: _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE12is_page_fullEv _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE12is_page_fullEv Line | Count | Source | 79 | 392 | bool is_page_full() override { return _rle_encoder->len() >= _options.data_page_size; } |
|
80 | | |
81 | 398 | Status add(const uint8_t* vals, size_t* count) override { |
82 | 398 | DCHECK(!_finished); |
83 | 398 | auto new_vals = reinterpret_cast<const CppType*>(vals); |
84 | 43.5k | for (int i = 0; i < *count; ++i) { |
85 | | // note: vals is not guaranteed to be aligned for now, thus memcpy here |
86 | 43.1k | CppType value; |
87 | 43.1k | memcpy(&value, &new_vals[i], SIZE_OF_TYPE); |
88 | 43.1k | _rle_encoder->Put(value); |
89 | 43.1k | } |
90 | | |
91 | 398 | _count += *count; |
92 | 398 | _raw_data_size += *count * SIZE_OF_TYPE; |
93 | 398 | return Status::OK(); |
94 | 398 | } _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE3addEPKhPm Line | Count | Source | 81 | 4 | Status add(const uint8_t* vals, size_t* count) override { | 82 | 4 | DCHECK(!_finished); | 83 | 4 | auto new_vals = reinterpret_cast<const CppType*>(vals); | 84 | 30.1k | for (int i = 0; i < *count; ++i) { | 85 | | // note: vals is not guaranteed to be aligned for now, thus memcpy here | 86 | 30.1k | CppType value; | 87 | 30.1k | memcpy(&value, &new_vals[i], SIZE_OF_TYPE); | 88 | 30.1k | _rle_encoder->Put(value); | 89 | 30.1k | } | 90 | | | 91 | 4 | _count += *count; | 92 | 4 | _raw_data_size += *count * SIZE_OF_TYPE; | 93 | 4 | return Status::OK(); | 94 | 4 | } |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE3addEPKhPm Line | Count | Source | 81 | 394 | Status add(const uint8_t* vals, size_t* count) override { | 82 | 394 | DCHECK(!_finished); | 83 | 394 | auto new_vals = reinterpret_cast<const CppType*>(vals); | 84 | 13.4k | for (int i = 0; i < *count; ++i) { | 85 | | // note: vals is not guaranteed to be aligned for now, thus memcpy here | 86 | 13.0k | CppType value; | 87 | 13.0k | memcpy(&value, &new_vals[i], SIZE_OF_TYPE); | 88 | 13.0k | _rle_encoder->Put(value); | 89 | 13.0k | } | 90 | | | 91 | 394 | _count += *count; | 92 | 394 | _raw_data_size += *count * SIZE_OF_TYPE; | 93 | 394 | return Status::OK(); | 94 | 394 | } |
|
95 | | |
96 | 214 | Status finish(OwnedSlice* slice) override { |
97 | 214 | DCHECK(!_finished); |
98 | 214 | _finished = true; |
99 | | // here should Flush first and then encode the count header |
100 | | // or it will lead to a bug if the header is less than 8 byte and the data is small |
101 | 214 | _rle_encoder->Flush(); |
102 | 214 | encode_fixed32_le(&_buf[0], cast_set<uint32_t>(_count)); |
103 | 214 | *slice = _buf.build(); |
104 | 214 | return Status::OK(); |
105 | 214 | } _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE6finishEPNS_10OwnedSliceE Line | Count | Source | 96 | 4 | Status finish(OwnedSlice* slice) override { | 97 | 4 | DCHECK(!_finished); | 98 | 4 | _finished = true; | 99 | | // here should Flush first and then encode the count header | 100 | | // or it will lead to a bug if the header is less than 8 byte and the data is small | 101 | 4 | _rle_encoder->Flush(); | 102 | 4 | encode_fixed32_le(&_buf[0], cast_set<uint32_t>(_count)); | 103 | 4 | *slice = _buf.build(); | 104 | 4 | return Status::OK(); | 105 | 4 | } |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE6finishEPNS_10OwnedSliceE Line | Count | Source | 96 | 210 | Status finish(OwnedSlice* slice) override { | 97 | 210 | DCHECK(!_finished); | 98 | 210 | _finished = true; | 99 | | // here should Flush first and then encode the count header | 100 | | // or it will lead to a bug if the header is less than 8 byte and the data is small | 101 | 210 | _rle_encoder->Flush(); | 102 | 210 | encode_fixed32_le(&_buf[0], cast_set<uint32_t>(_count)); | 103 | 210 | *slice = _buf.build(); | 104 | 210 | return Status::OK(); | 105 | 210 | } |
|
106 | | |
107 | 413 | Status reset() override { |
108 | 413 | RETURN_IF_CATCH_EXCEPTION({ |
109 | 413 | _count = 0; |
110 | 413 | _finished = false; |
111 | 413 | _raw_data_size = 0; |
112 | 413 | _rle_encoder->Clear(); |
113 | 413 | _rle_encoder->Reserve(RLE_PAGE_HEADER_SIZE, 0); |
114 | 413 | }); |
115 | 413 | return Status::OK(); |
116 | 413 | } _ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE5resetEv Line | Count | Source | 107 | 4 | Status reset() override { | 108 | 4 | RETURN_IF_CATCH_EXCEPTION({ | 109 | 4 | _count = 0; | 110 | 4 | _finished = false; | 111 | 4 | _raw_data_size = 0; | 112 | 4 | _rle_encoder->Clear(); | 113 | 4 | _rle_encoder->Reserve(RLE_PAGE_HEADER_SIZE, 0); | 114 | 4 | }); | 115 | 4 | return Status::OK(); | 116 | 4 | } |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE5resetEv Line | Count | Source | 107 | 409 | Status reset() override { | 108 | 409 | RETURN_IF_CATCH_EXCEPTION({ | 109 | 409 | _count = 0; | 110 | 409 | _finished = false; | 111 | 409 | _raw_data_size = 0; | 112 | 409 | _rle_encoder->Clear(); | 113 | 409 | _rle_encoder->Reserve(RLE_PAGE_HEADER_SIZE, 0); | 114 | 409 | }); | 115 | 409 | return Status::OK(); | 116 | 409 | } |
|
117 | | |
118 | 4 | size_t count() const override { return _count; }_ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE5countEv Line | Count | Source | 118 | 3 | size_t count() const override { return _count; } |
_ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE5countEv Line | Count | Source | 118 | 1 | size_t count() const override { return _count; } |
|
119 | | |
120 | 104 | uint64_t size() const override { return _rle_encoder->len(); }Unexecuted instantiation: _ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE4sizeEv _ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE4sizeEv Line | Count | Source | 120 | 104 | uint64_t size() const override { return _rle_encoder->len(); } |
|
121 | | |
122 | 208 | uint64_t get_raw_data_size() const override { return _raw_data_size; }Unexecuted instantiation: _ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EE17get_raw_data_sizeEv _ZNK5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EE17get_raw_data_sizeEv Line | Count | Source | 122 | 208 | uint64_t get_raw_data_size() const override { return _raw_data_size; } |
|
123 | | |
124 | | private: |
125 | | RlePageBuilder(const PageBuilderOptions& options) |
126 | 205 | : _options(options), |
127 | 205 | _count(0), |
128 | 205 | _finished(false), |
129 | 205 | _bit_width(0), |
130 | 205 | _rle_encoder(nullptr) {}_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE5EEC2ERKNS0_18PageBuilderOptionsE Line | Count | Source | 126 | 4 | : _options(options), | 127 | 4 | _count(0), | 128 | 4 | _finished(false), | 129 | 4 | _bit_width(0), | 130 | 4 | _rle_encoder(nullptr) {} |
_ZN5doris10segment_v214RlePageBuilderILNS_9FieldTypeE24EEC2ERKNS0_18PageBuilderOptionsE Line | Count | Source | 126 | 201 | : _options(options), | 127 | 201 | _count(0), | 128 | 201 | _finished(false), | 129 | 201 | _bit_width(0), | 130 | 201 | _rle_encoder(nullptr) {} |
|
131 | | |
132 | | typedef typename TypeTraits<Type>::CppType CppType; |
133 | | enum { SIZE_OF_TYPE = TypeTraits<Type>::size }; |
134 | | |
135 | | PageBuilderOptions _options; |
136 | | size_t _count; |
137 | | bool _finished; |
138 | | int _bit_width; |
139 | | RleEncoder<CppType>* _rle_encoder = nullptr; |
140 | | faststring _buf; |
141 | | uint64_t _raw_data_size = 0; |
142 | | }; |
143 | | |
144 | | template <FieldType Type> |
145 | | class RlePageDecoder : public PageDecoder { |
146 | | public: |
147 | | RlePageDecoder(Slice slice, const PageDecoderOptions& options) |
148 | 47 | : _data(slice), |
149 | 47 | _options(options), |
150 | 47 | _parsed(false), |
151 | 47 | _num_elements(0), |
152 | 47 | _cur_index(0), |
153 | 47 | _bit_width(0) {}_ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EEC2ENS_5SliceERKNS0_18PageDecoderOptionsE Line | Count | Source | 148 | 3 | : _data(slice), | 149 | 3 | _options(options), | 150 | 3 | _parsed(false), | 151 | 3 | _num_elements(0), | 152 | 3 | _cur_index(0), | 153 | 3 | _bit_width(0) {} |
_ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EEC2ENS_5SliceERKNS0_18PageDecoderOptionsE Line | Count | Source | 148 | 44 | : _data(slice), | 149 | 44 | _options(options), | 150 | 44 | _parsed(false), | 151 | 44 | _num_elements(0), | 152 | 44 | _cur_index(0), | 153 | 44 | _bit_width(0) {} |
|
154 | | |
155 | 47 | Status init() override { |
156 | 47 | CHECK(!_parsed); |
157 | | |
158 | 47 | if (_data.size < RLE_PAGE_HEADER_SIZE) { |
159 | 0 | return Status::Corruption("not enough bytes for header in RleBitMapBlockDecoder"); |
160 | 0 | } |
161 | 47 | _num_elements = decode_fixed32_le((const uint8_t*)&_data[0]); |
162 | | |
163 | 47 | _parsed = true; |
164 | | |
165 | 47 | switch (Type) { |
166 | 44 | case FieldType::OLAP_FIELD_TYPE_BOOL: { |
167 | 44 | _bit_width = 1; |
168 | 44 | break; |
169 | 0 | } |
170 | 3 | default: { |
171 | 3 | _bit_width = SIZE_OF_TYPE * 8; |
172 | 3 | break; |
173 | 0 | } |
174 | 47 | } |
175 | | |
176 | 47 | _rle_decoder = |
177 | 47 | RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, |
178 | 47 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), _bit_width); |
179 | | |
180 | 47 | RETURN_IF_ERROR(seek_to_position_in_page(0)); |
181 | 47 | return Status::OK(); |
182 | 47 | } _ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE4initEv Line | Count | Source | 155 | 3 | Status init() override { | 156 | 3 | CHECK(!_parsed); | 157 | | | 158 | 3 | if (_data.size < RLE_PAGE_HEADER_SIZE) { | 159 | 0 | return Status::Corruption("not enough bytes for header in RleBitMapBlockDecoder"); | 160 | 0 | } | 161 | 3 | _num_elements = decode_fixed32_le((const uint8_t*)&_data[0]); | 162 | | | 163 | 3 | _parsed = true; | 164 | | | 165 | 3 | switch (Type) { | 166 | 0 | case FieldType::OLAP_FIELD_TYPE_BOOL: { | 167 | 0 | _bit_width = 1; | 168 | 0 | break; | 169 | 0 | } | 170 | 3 | default: { | 171 | 3 | _bit_width = SIZE_OF_TYPE * 8; | 172 | 3 | break; | 173 | 0 | } | 174 | 3 | } | 175 | | | 176 | 3 | _rle_decoder = | 177 | 3 | RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, | 178 | 3 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), _bit_width); | 179 | | | 180 | 3 | RETURN_IF_ERROR(seek_to_position_in_page(0)); | 181 | 3 | return Status::OK(); | 182 | 3 | } |
_ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE4initEv Line | Count | Source | 155 | 44 | Status init() override { | 156 | 44 | CHECK(!_parsed); | 157 | | | 158 | 44 | if (_data.size < RLE_PAGE_HEADER_SIZE) { | 159 | 0 | return Status::Corruption("not enough bytes for header in RleBitMapBlockDecoder"); | 160 | 0 | } | 161 | 44 | _num_elements = decode_fixed32_le((const uint8_t*)&_data[0]); | 162 | | | 163 | 44 | _parsed = true; | 164 | | | 165 | 44 | switch (Type) { | 166 | 44 | case FieldType::OLAP_FIELD_TYPE_BOOL: { | 167 | 44 | _bit_width = 1; | 168 | 44 | break; | 169 | 0 | } | 170 | 0 | default: { | 171 | 0 | _bit_width = SIZE_OF_TYPE * 8; | 172 | 0 | break; | 173 | 0 | } | 174 | 44 | } | 175 | | | 176 | 44 | _rle_decoder = | 177 | 44 | RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, | 178 | 44 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), _bit_width); | 179 | | | 180 | 44 | RETURN_IF_ERROR(seek_to_position_in_page(0)); | 181 | 44 | return Status::OK(); | 182 | 44 | } |
|
183 | | |
184 | 447 | Status seek_to_position_in_page(size_t pos) override { |
185 | 447 | DCHECK(_parsed) << "Must call init()"; |
186 | 447 | DCHECK_LE(pos, _num_elements) |
187 | 0 | << "Tried to seek to " << pos << " which is > number of elements (" << _num_elements |
188 | 0 | << ") in the block!"; |
189 | | // If the block is empty (e.g. the column is filled with nulls), there is no data to seek. |
190 | 447 | if (_num_elements == 0) [[unlikely]] { |
191 | 0 | if (pos != 0) { |
192 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( |
193 | 0 | "seek pos {} is larger than total elements {}", pos, _num_elements); |
194 | 0 | } else { |
195 | 0 | return Status::OK(); |
196 | 0 | } |
197 | 0 | } |
198 | 447 | if (_cur_index == pos) { |
199 | | // No need to seek. |
200 | 47 | return Status::OK(); |
201 | 400 | } else if (_cur_index < pos) { |
202 | 197 | size_t nskip = pos - _cur_index; |
203 | 197 | _rle_decoder.Skip(nskip); |
204 | 203 | } else { |
205 | 203 | _rle_decoder = RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, |
206 | 203 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), |
207 | 203 | _bit_width); |
208 | 203 | _rle_decoder.Skip(pos); |
209 | 203 | } |
210 | 400 | _cur_index = pos; |
211 | 400 | return Status::OK(); |
212 | 447 | } _ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE24seek_to_position_in_pageEm Line | Count | Source | 184 | 303 | Status seek_to_position_in_page(size_t pos) override { | 185 | 303 | DCHECK(_parsed) << "Must call init()"; | 186 | 303 | DCHECK_LE(pos, _num_elements) | 187 | 0 | << "Tried to seek to " << pos << " which is > number of elements (" << _num_elements | 188 | 0 | << ") in the block!"; | 189 | | // If the block is empty (e.g. the column is filled with nulls), there is no data to seek. | 190 | 303 | if (_num_elements == 0) [[unlikely]] { | 191 | 0 | if (pos != 0) { | 192 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( | 193 | 0 | "seek pos {} is larger than total elements {}", pos, _num_elements); | 194 | 0 | } else { | 195 | 0 | return Status::OK(); | 196 | 0 | } | 197 | 0 | } | 198 | 303 | if (_cur_index == pos) { | 199 | | // No need to seek. | 200 | 3 | return Status::OK(); | 201 | 300 | } else if (_cur_index < pos) { | 202 | 149 | size_t nskip = pos - _cur_index; | 203 | 149 | _rle_decoder.Skip(nskip); | 204 | 151 | } else { | 205 | 151 | _rle_decoder = RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, | 206 | 151 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), | 207 | 151 | _bit_width); | 208 | 151 | _rle_decoder.Skip(pos); | 209 | 151 | } | 210 | 300 | _cur_index = pos; | 211 | 300 | return Status::OK(); | 212 | 303 | } |
_ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE24seek_to_position_in_pageEm Line | Count | Source | 184 | 144 | Status seek_to_position_in_page(size_t pos) override { | 185 | 144 | DCHECK(_parsed) << "Must call init()"; | 186 | 144 | DCHECK_LE(pos, _num_elements) | 187 | 0 | << "Tried to seek to " << pos << " which is > number of elements (" << _num_elements | 188 | 0 | << ") in the block!"; | 189 | | // If the block is empty (e.g. the column is filled with nulls), there is no data to seek. | 190 | 144 | if (_num_elements == 0) [[unlikely]] { | 191 | 0 | if (pos != 0) { | 192 | 0 | return Status::Error<ErrorCode::INTERNAL_ERROR, false>( | 193 | 0 | "seek pos {} is larger than total elements {}", pos, _num_elements); | 194 | 0 | } else { | 195 | 0 | return Status::OK(); | 196 | 0 | } | 197 | 0 | } | 198 | 144 | if (_cur_index == pos) { | 199 | | // No need to seek. | 200 | 44 | return Status::OK(); | 201 | 100 | } else if (_cur_index < pos) { | 202 | 48 | size_t nskip = pos - _cur_index; | 203 | 48 | _rle_decoder.Skip(nskip); | 204 | 52 | } else { | 205 | 52 | _rle_decoder = RleDecoder<CppType>((uint8_t*)_data.data + RLE_PAGE_HEADER_SIZE, | 206 | 52 | cast_set<int>(_data.size - RLE_PAGE_HEADER_SIZE), | 207 | 52 | _bit_width); | 208 | 52 | _rle_decoder.Skip(pos); | 209 | 52 | } | 210 | 100 | _cur_index = pos; | 211 | 100 | return Status::OK(); | 212 | 144 | } |
|
213 | | |
214 | 531 | Status next_batch(size_t* n, MutableColumnPtr& dst) override { |
215 | 531 | DCHECK(_parsed); |
216 | 531 | if (*n == 0 || _cur_index >= _num_elements) [[unlikely]] { |
217 | 0 | *n = 0; |
218 | 0 | return Status::OK(); |
219 | 0 | } |
220 | | |
221 | 531 | size_t to_fetch = std::min(*n, static_cast<size_t>(_num_elements - _cur_index)); |
222 | 531 | size_t remaining = to_fetch; |
223 | 531 | bool result = false; |
224 | 531 | CppType value; |
225 | 42.4k | while (remaining > 0) { |
226 | 41.9k | result = _rle_decoder.Get(&value); |
227 | 41.9k | DCHECK(result); |
228 | 41.9k | dst->insert_data((char*)(&value), SIZE_OF_TYPE); |
229 | 41.9k | remaining--; |
230 | 41.9k | } |
231 | | |
232 | 531 | _cur_index += to_fetch; |
233 | 531 | *n = to_fetch; |
234 | 531 | return Status::OK(); |
235 | 531 | } _ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE10next_batchEPmRNS_3COWINS_7IColumnEE11mutable_ptrIS6_EE Line | Count | Source | 214 | 303 | Status next_batch(size_t* n, MutableColumnPtr& dst) override { | 215 | 303 | DCHECK(_parsed); | 216 | 303 | if (*n == 0 || _cur_index >= _num_elements) [[unlikely]] { | 217 | 0 | *n = 0; | 218 | 0 | return Status::OK(); | 219 | 0 | } | 220 | | | 221 | 303 | size_t to_fetch = std::min(*n, static_cast<size_t>(_num_elements - _cur_index)); | 222 | 303 | size_t remaining = to_fetch; | 223 | 303 | bool result = false; | 224 | 303 | CppType value; | 225 | 30.6k | while (remaining > 0) { | 226 | 30.3k | result = _rle_decoder.Get(&value); | 227 | 30.3k | DCHECK(result); | 228 | 30.3k | dst->insert_data((char*)(&value), SIZE_OF_TYPE); | 229 | 30.3k | remaining--; | 230 | 30.3k | } | 231 | | | 232 | 303 | _cur_index += to_fetch; | 233 | 303 | *n = to_fetch; | 234 | 303 | return Status::OK(); | 235 | 303 | } |
_ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE10next_batchEPmRNS_3COWINS_7IColumnEE11mutable_ptrIS6_EE Line | Count | Source | 214 | 228 | Status next_batch(size_t* n, MutableColumnPtr& dst) override { | 215 | 228 | DCHECK(_parsed); | 216 | 228 | if (*n == 0 || _cur_index >= _num_elements) [[unlikely]] { | 217 | 0 | *n = 0; | 218 | 0 | return Status::OK(); | 219 | 0 | } | 220 | | | 221 | 228 | size_t to_fetch = std::min(*n, static_cast<size_t>(_num_elements - _cur_index)); | 222 | 228 | size_t remaining = to_fetch; | 223 | 228 | bool result = false; | 224 | 228 | CppType value; | 225 | 11.8k | while (remaining > 0) { | 226 | 11.6k | result = _rle_decoder.Get(&value); | 227 | 11.6k | DCHECK(result); | 228 | 11.6k | dst->insert_data((char*)(&value), SIZE_OF_TYPE); | 229 | 11.6k | remaining--; | 230 | 11.6k | } | 231 | | | 232 | 228 | _cur_index += to_fetch; | 233 | 228 | *n = to_fetch; | 234 | 228 | return Status::OK(); | 235 | 228 | } |
|
236 | | |
237 | | Status read_by_rowids(const rowid_t* rowids, ordinal_t page_first_ordinal, size_t* n, |
238 | 2 | MutableColumnPtr& dst) override { |
239 | 2 | DCHECK(_parsed); |
240 | 2 | if (*n == 0 || _cur_index >= _num_elements) [[unlikely]] { |
241 | 0 | *n = 0; |
242 | 0 | return Status::OK(); |
243 | 0 | } |
244 | | |
245 | 2 | auto total = *n; |
246 | 2 | bool result = false; |
247 | 2 | size_t read_count = 0; |
248 | 2 | CppType value; |
249 | 6 | for (size_t i = 0; i < total; ++i) { |
250 | 4 | ordinal_t ord = rowids[i] - page_first_ordinal; |
251 | 4 | if (UNLIKELY(ord >= _num_elements)) { |
252 | 0 | *n = read_count; |
253 | 0 | return Status::OK(); |
254 | 0 | } |
255 | | |
256 | 4 | _rle_decoder.Skip(ord - _cur_index); |
257 | 4 | _cur_index = ord; |
258 | | |
259 | 4 | result = _rle_decoder.Get(&value); |
260 | 4 | _cur_index++; |
261 | 4 | DCHECK(result); |
262 | 4 | dst->insert_data((char*)(&value), SIZE_OF_TYPE); |
263 | 4 | read_count++; |
264 | 4 | } |
265 | 2 | *n = read_count; |
266 | 2 | return Status::OK(); |
267 | 2 | } Unexecuted instantiation: _ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE14read_by_rowidsEPKjmPmRNS_3COWINS_7IColumnEE11mutable_ptrIS8_EE _ZN5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE14read_by_rowidsEPKjmPmRNS_3COWINS_7IColumnEE11mutable_ptrIS8_EE Line | Count | Source | 238 | 2 | MutableColumnPtr& dst) override { | 239 | 2 | DCHECK(_parsed); | 240 | 2 | if (*n == 0 || _cur_index >= _num_elements) [[unlikely]] { | 241 | 0 | *n = 0; | 242 | 0 | return Status::OK(); | 243 | 0 | } | 244 | | | 245 | 2 | auto total = *n; | 246 | 2 | bool result = false; | 247 | 2 | size_t read_count = 0; | 248 | 2 | CppType value; | 249 | 6 | for (size_t i = 0; i < total; ++i) { | 250 | 4 | ordinal_t ord = rowids[i] - page_first_ordinal; | 251 | 4 | if (UNLIKELY(ord >= _num_elements)) { | 252 | 0 | *n = read_count; | 253 | 0 | return Status::OK(); | 254 | 0 | } | 255 | | | 256 | 4 | _rle_decoder.Skip(ord - _cur_index); | 257 | 4 | _cur_index = ord; | 258 | | | 259 | 4 | result = _rle_decoder.Get(&value); | 260 | 4 | _cur_index++; | 261 | 4 | DCHECK(result); | 262 | 4 | dst->insert_data((char*)(&value), SIZE_OF_TYPE); | 263 | 4 | read_count++; | 264 | 4 | } | 265 | 2 | *n = read_count; | 266 | 2 | return Status::OK(); | 267 | 2 | } |
|
268 | | |
269 | 4 | size_t count() const override { return _num_elements; }_ZNK5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE5countEv Line | Count | Source | 269 | 3 | size_t count() const override { return _num_elements; } |
_ZNK5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE5countEv Line | Count | Source | 269 | 1 | size_t count() const override { return _num_elements; } |
|
270 | | |
271 | 404 | size_t current_index() const override { return _cur_index; }_ZNK5doris10segment_v214RlePageDecoderILNS_9FieldTypeE5EE13current_indexEv Line | Count | Source | 271 | 303 | size_t current_index() const override { return _cur_index; } |
_ZNK5doris10segment_v214RlePageDecoderILNS_9FieldTypeE24EE13current_indexEv Line | Count | Source | 271 | 101 | size_t current_index() const override { return _cur_index; } |
|
272 | | |
273 | | private: |
274 | | typedef typename TypeTraits<Type>::CppType CppType; |
275 | | enum { SIZE_OF_TYPE = TypeTraits<Type>::size }; |
276 | | |
277 | | Slice _data; |
278 | | PageDecoderOptions _options; |
279 | | bool _parsed; |
280 | | uint32_t _num_elements; |
281 | | size_t _cur_index; |
282 | | int _bit_width; |
283 | | RleDecoder<CppType> _rle_decoder; |
284 | | }; |
285 | | |
286 | | } // namespace segment_v2 |
287 | | } // namespace doris |