Branch data Line data Source code
1 : : #include "storage/PaxStore.hpp" 2 : : 3 : : #include <algorithm> 4 : : #include <exception> 5 : : #include <fstream> 6 : : #include <iomanip> 7 : : #include <mutable/catalog/Catalog.hpp> 8 : : #include <numeric> 9 : : 10 : : 11 : : using namespace m; 12 : : 13 : : 14 [ + - + - : 88 : PaxStore::PaxStore(const Table &table, uint32_t block_size_in_bytes) + - ] 15 : 44 : : Store(table) 16 [ + - + - ]: 44 : , offsets_(new uint32_t[table.num_attrs() + 1]) // add one slot for the offset of the meta data 17 : 44 : , block_size_(block_size_in_bytes) 18 : 44 : { 19 [ + - ]: 44 : compute_block_offsets(); 20 : : 21 [ + - - + ]: 44 : data_ = allocator_.allocate(ALLOCATION_SIZE); 22 : 44 : } 23 : : 24 : 128 : PaxStore::~PaxStore() 25 : 84 : { 26 [ + - ]: 44 : delete[] offsets_; 27 : 84 : } 28 : : 29 : 44 : void PaxStore::compute_block_offsets() 30 : : { 31 : : using std::max; 32 : : 33 : 44 : const auto num_attrs = table().num_attrs(); 34 : 44 : const Attribute **attrs = new const Attribute*[num_attrs]; 35 : : 36 [ + + ]: 292 : for (uint32_t pos = 0; pos != num_attrs; ++pos) 37 : 248 : attrs[pos] = &table()[pos]; 38 : : 39 : : /* Sort attributes by their alignment requirement in descending order. */ 40 : 563 : std::stable_sort(attrs, attrs + num_attrs, [](const Attribute *first, const Attribute *second) { 41 : 519 : return first->type->alignment() > second->type->alignment(); 42 : : }); 43 : : 44 : : /* Compute offsets (for a single row). */ 45 : 44 : uint64_t off = 0; 46 : 44 : uint64_t alignment = 8; 47 : 44 : std::size_t num_not_byte_aligned = 0; // number of attribute columns which are not necessarily byte-aligned 48 [ + + ]: 292 : for (uint32_t pos = 0; pos != num_attrs; ++pos) { 49 : 248 : const Attribute &attr = *attrs[pos]; 50 : 248 : offsets_[attr.id] = off; 51 : 248 : off += attr.type->size(); 52 : 248 : alignment = max(alignment, attr.type->alignment()); 53 [ + + ]: 248 : if (attr.type->size() % 8) 54 : 21 : ++num_not_byte_aligned; 55 : 248 : } 56 : : /* Add space for meta data. */ 57 : 44 : offsets_[num_attrs] = off; 58 : 44 : off += num_attrs; // reserve space for the NULL bitmap 59 : 44 : uint64_t row_size_ = off; 60 : : 61 : : #if 1 62 : : /* Compute number of rows within a PAX block. Consider worst case padding of 7 bits (because each column within 63 : : * a PAX block must be byte-aligned) for every possibly not byte-aligned attribute column. Null bitmap column is 64 : : * ignored since it is the last column. */ 65 : 44 : num_rows_per_block_ = (block_size_ * 8 - num_not_byte_aligned * 7) / row_size_; 66 : : #else 67 : 0 : /* Compute number of rows within a PAX block. Assert that the stride jumps to the next block are whole multiples 68 : : * of a byte by packing potentially less rows into one block. Therefore, padding can be ignored. */ 69 : : auto max_num_rows_per_block = (block_size_ * 8) / row_size_; 70 : : num_rows_per_block_ = (max_num_rows_per_block / 8) * 8; // round down to next multiple of 8 71 : : #endif 72 : : 73 : : /* Compute offsets (for all rows in a PAX block) by multiplying the offset for a single row by the number of rows 74 : 1 : * within a PAX block. Add padding to next byte if necessary. */ 75 : 44 : uint32_t running_bit_offset = 0; 76 [ + + ]: 292 : for (uint32_t pos = 0; pos != num_attrs; ++pos) { 77 : 248 : const Attribute &attr = *attrs[pos]; 78 : 248 : offsets_[attr.id] = offsets_[attr.id] * num_rows_per_block_ + running_bit_offset; 79 : 248 : M_insist(offsets_[attr.id] % 8 == 0, "attribute column must be byte aligned"); 80 [ + + ]: 248 : if (auto bit_offset = (offsets_[attr.id] + attr.type->size() * num_rows_per_block_) % 8; bit_offset) 81 : 17 : running_bit_offset += 8 - bit_offset; 82 : 248 : } 83 : 44 : offsets_[num_attrs] = offsets_[num_attrs] * num_rows_per_block_ + running_bit_offset; 84 : 44 : M_insist(offsets_[num_attrs] % 8 == 0, "NULL bitmap column must be byte aligned"); 85 : 44 : M_insist(offsets_[num_attrs] + num_attrs * num_rows_per_block_ <= block_size_ * 8); 86 : : 87 : : /* Compute capacity. */ 88 : 44 : capacity_ = (ALLOCATION_SIZE / block_size_) * num_rows_per_block_; 89 : : 90 [ + - ]: 44 : delete[] attrs; 91 : 44 : } 92 : : 93 : : M_LCOV_EXCL_START 94 : : void PaxStore::dump(std::ostream &out) const 95 : : { 96 : : out << "PaxStore at " << data_.addr() << " for table \"" << table().name() << "\": " << num_rows_ << '/' << capacity_ 97 : : << " rows, " << block_size_ << " bytes per block, " << num_rows_per_block_ << " rows per block, offsets in bits ["; 98 : : for (uint32_t i = 0, end = table().num_attrs(); i != end; ++i) { 99 : : if (i != 0) out << ", "; 100 : : out << offsets_[i]; 101 : : } 102 : : out << ']' << std::endl; 103 : : } 104 : : M_LCOV_EXCL_STOP 105 : : 106 : : __attribute__((constructor(202))) 107 : 1 : static void register_store() 108 : : { 109 : 1 : Catalog &C = Catalog::Get(); 110 [ + - ]: 1 : C.register_store<PaxStore>(C.pool("PaxStore"), "stores attributes using PAX layout"); 111 : 1 : }