| 113 | } |
| 114 | |
| 115 | void RowBatch::Deserialize(const kudu::Slice& input_tuple_offsets, |
| 116 | const kudu::Slice& input_tuple_data, int64_t uncompressed_size, |
| 117 | bool is_compressed, uint8_t* tuple_data) { |
| 118 | DCHECK(tuple_ptrs_ != nullptr); |
| 119 | DCHECK(tuple_data != nullptr); |
| 120 | if (is_compressed) { |
| 121 | // Decompress tuple data into data pool |
| 122 | const uint8_t* compressed_data = input_tuple_data.data(); |
| 123 | size_t compressed_size = input_tuple_data.size(); |
| 124 | |
| 125 | Lz4Decompressor decompressor(nullptr, false); |
| 126 | Status status = decompressor.Init(); |
| 127 | DCHECK(status.ok()) << status.GetDetail(); |
| 128 | auto compressor_cleanup = |
| 129 | MakeScopeExitTrigger([&decompressor]() { decompressor.Close(); }); |
| 130 | |
| 131 | status = decompressor.ProcessBlock( |
| 132 | true, compressed_size, compressed_data, &uncompressed_size, &tuple_data); |
| 133 | DCHECK_NE(uncompressed_size, -1) << "RowBatch decompression failed"; |
| 134 | DCHECK(status.ok()) << "RowBatch decompression failed."; |
| 135 | } else { |
| 136 | // Tuple data uncompressed, copy directly into data pool |
| 137 | DCHECK_EQ(uncompressed_size, input_tuple_data.size()); |
| 138 | memcpy(tuple_data, input_tuple_data.data(), input_tuple_data.size()); |
| 139 | } |
| 140 | |
| 141 | // Convert input_batch.tuple_offsets into pointers |
| 142 | const int32_t* tuple_offsets = |
| 143 | reinterpret_cast<const int32_t*>(input_tuple_offsets.data()); |
| 144 | DCHECK_EQ(input_tuple_offsets.size() % sizeof(int32_t), 0); |
| 145 | int num_tuples = input_tuple_offsets.size() / sizeof(int32_t); |
| 146 | for (int tuple_idx = 0; tuple_idx < num_tuples; ++tuple_idx) { |
| 147 | int32_t offset = tuple_offsets[tuple_idx]; |
| 148 | if (offset == -1) { |
| 149 | tuple_ptrs_[tuple_idx] = nullptr; |
| 150 | } else { |
| 151 | tuple_ptrs_[tuple_idx] = reinterpret_cast<Tuple*>(tuple_data + offset); |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // Check whether we have slots that require offset-to-pointer conversion. |
| 156 | if (!row_desc_->HasVarlenSlots()) return; |
| 157 | |
| 158 | // For every unique tuple, convert string offsets contained in tuple data into |
| 159 | // pointers. Tuples were serialized in the order we are deserializing them in, |
| 160 | // so the first occurrence of a tuple will always have a higher offset than any |
| 161 | // tuple we already converted. |
| 162 | Tuple* last_converted = nullptr; |
| 163 | for (int i = 0; i < num_rows_; ++i) { |
| 164 | for (int j = 0; j < num_tuples_per_row_; ++j) { |
| 165 | const TupleDescriptor* desc = row_desc_->tuple_descriptors()[j]; |
| 166 | if (!desc->HasVarlenSlots()) continue; |
| 167 | Tuple* tuple = GetRow(i)->GetTuple(j); |
| 168 | // Handle NULL or already converted tuples with one check. |
| 169 | if (tuple <= last_converted) continue; |
| 170 | last_converted = tuple; |
| 171 | tuple->ConvertOffsetsToPointers(*desc, tuple_data); |
| 172 | } |
no test coverage detected