LCOV - code coverage report
Current view: top level - src/storage - PaxStore.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 53 54 98.1 %
Date: 2025-03-25 01:19:55 Functions: 7 8 87.5 %
Branches: 21 32 65.6 %

           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 : }

Generated by: LCOV version 1.16