/** * Apply the column delta on the rollback segment to the given tuple */ void TileGroup::ApplyRollbackSegment(char *rb_seg, const oid_t &tuple_slot_id) { auto seg_col_count = storage::RollbackSegmentPool::GetColCount(rb_seg); auto table_schema = GetAbstractTable()->GetSchema(); for (size_t idx = 0; idx < seg_col_count; ++idx) { auto col_id = storage::RollbackSegmentPool::GetIdOffsetPair(rb_seg, idx)->col_id; Value col_value = storage::RollbackSegmentPool::GetValue(rb_seg, table_schema, idx); // Get target tile auto tile_id = GetTileIdFromColumnId(col_id); PL_ASSERT(tile_id < GetTileCount()); storage::Tile *tile = GetTile(tile_id); PL_ASSERT(tile); // Get tile schema auto &tile_schema = tile_schemas[tile_id]; // Get a tuple wrapper char *tile_tuple_location = tile->GetTupleLocation(tuple_slot_id); PL_ASSERT(tile_tuple_location); storage::Tuple tile_tuple(&tile_schema, tile_tuple_location); // Write the value to tuple auto tile_col_idx = GetTileColumnId(col_id); tile_tuple.SetValue(tile_col_idx, col_value, tile->GetPool()); } }
/** * Grab next slot (thread-safe) and fill in the tuple * * Returns slot where inserted (INVALID_ID if not inserted) */ void TileGroup::CopyTuple(const Tuple *tuple, const oid_t &tuple_slot_id) { LOG_TRACE("Tile Group Id :: %u status :: %u out of %u slots ", tile_group_id, tuple_slot_id, num_tuple_slots); oid_t tile_column_count; oid_t column_itr = 0; for (oid_t tile_itr = 0; tile_itr < tile_count; tile_itr++) { const catalog::Schema &schema = tile_schemas[tile_itr]; tile_column_count = schema.GetColumnCount(); storage::Tile *tile = GetTile(tile_itr); PL_ASSERT(tile); char *tile_tuple_location = tile->GetTupleLocation(tuple_slot_id); PL_ASSERT(tile_tuple_location); // NOTE:: Only a tuple wrapper storage::Tuple tile_tuple(&schema, tile_tuple_location); for (oid_t tile_column_itr = 0; tile_column_itr < tile_column_count; tile_column_itr++) { tile_tuple.SetValue(tile_column_itr, tuple->GetValue(column_itr), tile->GetPool()); column_itr++; } } }
/** * Grab specific slot and fill in the tuple * Used by recovery * Returns slot where inserted (INVALID_ID if not inserted) */ oid_t TileGroup::InsertTupleFromRecovery(cid_t commit_id, oid_t tuple_slot_id, const Tuple *tuple) { auto status = tile_group_header->GetEmptyTupleSlot(tuple_slot_id); // No more slots if (status == false) return INVALID_OID; tile_group_header->GetHeaderLock().Lock(); cid_t current_begin_cid = tile_group_header->GetBeginCommitId(tuple_slot_id); if (current_begin_cid != MAX_CID && current_begin_cid > commit_id) { tile_group_header->GetHeaderLock().Unlock(); return tuple_slot_id; } LOG_TRACE("Tile Group Id :: %u status :: %u out of %u slots ", tile_group_id, tuple_slot_id, num_tuple_slots); oid_t tile_column_count; oid_t column_itr = 0; for (oid_t tile_itr = 0; tile_itr < tile_count; tile_itr++) { const catalog::Schema &schema = tile_schemas[tile_itr]; tile_column_count = schema.GetColumnCount(); storage::Tile *tile = GetTile(tile_itr); PL_ASSERT(tile); char *tile_tuple_location = tile->GetTupleLocation(tuple_slot_id); PL_ASSERT(tile_tuple_location); // NOTE:: Only a tuple wrapper storage::Tuple tile_tuple(&schema, tile_tuple_location); for (oid_t tile_column_itr = 0; tile_column_itr < tile_column_count; tile_column_itr++) { tile_tuple.SetValue(tile_column_itr, tuple->GetValue(column_itr), tile->GetPool()); column_itr++; } } // Set MVCC info tile_group_header->SetTransactionId(tuple_slot_id, INITIAL_TXN_ID); tile_group_header->SetBeginCommitId(tuple_slot_id, commit_id); tile_group_header->SetEndCommitId(tuple_slot_id, MAX_CID); tile_group_header->SetInsertCommit(tuple_slot_id, false); tile_group_header->SetDeleteCommit(tuple_slot_id, false); tile_group_header->SetNextItemPointer(tuple_slot_id, INVALID_ITEMPOINTER); tile_group_header->GetHeaderLock().Unlock(); return tuple_slot_id; }
/** * Grab next slot (thread-safe) and fill in the tuple * * Returns slot where inserted (INVALID_ID if not inserted) */ oid_t TileGroup::InsertTuple(txn_id_t transaction_id, const Tuple *tuple) { oid_t tuple_slot_id = tile_group_header->GetNextEmptyTupleSlot(); LOG_TRACE("Tile Group Id :: %lu status :: %lu out of %lu slots ", tile_group_id, tuple_slot_id, num_tuple_slots); // No more slots if (tuple_slot_id == INVALID_OID) { LOG_INFO("Failed to get next empty tuple slot within tile group."); return INVALID_OID; } oid_t tile_column_count; oid_t column_itr = 0; for (oid_t tile_itr = 0; tile_itr < tile_count; tile_itr++) { const catalog::Schema &schema = tile_schemas[tile_itr]; tile_column_count = schema.GetColumnCount(); storage::Tile *tile = GetTile(tile_itr); assert(tile); char *tile_tuple_location = tile->GetTupleLocation(tuple_slot_id); assert(tile_tuple_location); // NOTE:: Only a tuple wrapper storage::Tuple tile_tuple(&schema, tile_tuple_location); for (oid_t tile_column_itr = 0; tile_column_itr < tile_column_count; tile_column_itr++) { tile_tuple.SetValue(tile_column_itr, tuple->GetValue(column_itr), tile->GetPool()); column_itr++; } } // Set MVCC info assert(tile_group_header->GetTransactionId(tuple_slot_id) == INVALID_TXN_ID); assert(tile_group_header->GetBeginCommitId(tuple_slot_id) == MAX_CID); assert(tile_group_header->GetEndCommitId(tuple_slot_id) == MAX_CID); tile_group_header->SetTransactionId(tuple_slot_id, transaction_id); tile_group_header->SetBeginCommitId(tuple_slot_id, MAX_CID); tile_group_header->SetEndCommitId(tuple_slot_id, MAX_CID); tile_group_header->SetInsertCommit(tuple_slot_id, false); tile_group_header->SetDeleteCommit(tuple_slot_id, false); return tuple_slot_id; }