const std::string DataTable::GetInfo() const { std::ostringstream os; // os << "=====================================================\n"; // os << "TABLE :\n"; oid_t tile_group_count = GetTileGroupCount(); // os << "Tile Group Count : " << tile_group_count << "\n"; oid_t tuple_count = 0; oid_t table_id = 0; for (oid_t tile_group_itr = 0; tile_group_itr < tile_group_count; tile_group_itr++) { auto tile_group = GetTileGroup(tile_group_itr); table_id = tile_group->GetTableId(); auto tile_tuple_count = tile_group->GetNextTupleSlot(); // os << "Tile Group Id : " << tile_group_itr // << " Tuple Count : " << tile_tuple_count << "\n"; // os << (*tile_group); tuple_count += tile_tuple_count; } os << "Table " << table_id << " Tuple Count :: " << tuple_count << "\n"; // os << "=====================================================\n"; return os.str(); }
void TimestampOrderingTransactionManager::PerformInsert( TransactionContext *const current_txn, const ItemPointer &location, ItemPointer *index_entry_ptr) { PELOTON_ASSERT(!current_txn->IsReadOnly()); oid_t tile_group_id = location.block; oid_t tuple_id = location.offset; auto storage_manager = storage::StorageManager::GetInstance(); auto tile_group_header = storage_manager->GetTileGroup(tile_group_id)->GetHeader(); auto transaction_id = current_txn->GetTransactionId(); // check MVCC info // the tuple slot must be empty. PELOTON_ASSERT(tile_group_header->GetTransactionId(tuple_id) == INVALID_TXN_ID); PELOTON_ASSERT(tile_group_header->GetBeginCommitId(tuple_id) == MAX_CID); PELOTON_ASSERT(tile_group_header->GetEndCommitId(tuple_id) == MAX_CID); tile_group_header->SetTransactionId(tuple_id, transaction_id); tile_group_header->SetLastReaderCommitId(tuple_id, current_txn->GetCommitId()); // no need to set next item pointer. // Add the new tuple into the insert set current_txn->RecordInsert(location); // Write down the head pointer's address in tile group header tile_group_header->SetIndirection(tuple_id, index_entry_ptr); }
// Generate a scan over all tile groups. // // @code // column_layouts := alloca<peloton::ColumnLayoutInfo>( // table.GetSchema().GetColumnCount()) // // oid_t tile_group_idx := 0 // num_tile_groups = GetTileGroupCount(table_ptr) // // for (; tile_group_idx < num_tile_groups; ++tile_group_idx) { // tile_group_ptr := GetTileGroup(table_ptr, tile_group_idx) // consumer.TileGroupStart(tile_group_ptr); // tile_group.TidScan(tile_group_ptr, column_layouts, vector_size, consumer); // consumer.TileGroupEnd(tile_group_ptr); // } // // @endcode void Table::GenerateScan(CodeGen &codegen, llvm::Value *table_ptr, uint32_t batch_size, ScanCallback &consumer) const { // First get the columns from the table the consumer needs. For every column, // we'll need to have a ColumnInfoLayout struct const uint32_t num_columns = static_cast<uint32_t>(table_.GetSchema()->GetColumnCount()); llvm::Value *column_layouts = codegen->CreateAlloca( RuntimeFunctionsProxy::_ColumnLayoutInfo::GetType(codegen), codegen.Const32(num_columns)); // Get the number of tile groups in the given table llvm::Value *tile_group_idx = codegen.Const64(0); llvm::Value *num_tile_groups = GetTileGroupCount(codegen, table_ptr); // Iterate over all tile groups in the table lang::Loop loop{codegen, codegen->CreateICmpULT(tile_group_idx, num_tile_groups), {{"tileGroupIdx", tile_group_idx}}}; { // Get the tile group with the given tile group ID tile_group_idx = loop.GetLoopVar(0); llvm::Value *tile_group_ptr = GetTileGroup(codegen, table_ptr, tile_group_idx); llvm::Value *tile_group_id = tile_group_.GetTileGroupId(codegen, tile_group_ptr); // Invoke the consumer to let her know that we're starting to iterate over // the tile group now consumer.TileGroupStart(codegen, tile_group_id, tile_group_ptr); // Generate the scan cover over the given tile group tile_group_.GenerateTidScan(codegen, tile_group_ptr, column_layouts, batch_size, consumer); // Invoke the consumer to let her know that we're done with this tile group consumer.TileGroupFinish(codegen, tile_group_ptr); // Move to next tile group in the table tile_group_idx = codegen->CreateAdd(tile_group_idx, codegen.Const64(1)); loop.LoopEnd(codegen->CreateICmpULT(tile_group_idx, num_tile_groups), {tile_group_idx}); } }
void CheckTupleCount(oid_t db_oid, oid_t table_oid, oid_t expected) { auto& manager = catalog::Manager::GetInstance(); storage::Database* db = manager.GetDatabaseWithOid(db_oid); auto table = db->GetTableWithOid(table_oid); oid_t tile_group_count = table->GetTileGroupCount(); oid_t active_tuple_count = 0; for (oid_t tile_group_itr = 0; tile_group_itr < tile_group_count; tile_group_itr++) { auto tile_group = table->GetTileGroup(tile_group_itr); active_tuple_count += tile_group->GetActiveTupleCount(INVALID_TXN_ID); } // check # of active tuples if (expected != active_tuple_count) { throw Exception("Tuple count does not match \n"); } }
void TimestampOrderingTransactionManager::PerformUpdate( TransactionContext *const current_txn, const ItemPointer &location, const ItemPointer &new_location) { PELOTON_ASSERT(!current_txn->IsReadOnly()); ItemPointer old_location = location; LOG_TRACE("Performing Update old tuple %u %u", old_location.block, old_location.offset); LOG_TRACE("Performing Update new tuple %u %u", new_location.block, new_location.offset); auto storage_manager = storage::StorageManager::GetInstance(); auto tile_group_header = storage_manager->GetTileGroup(old_location.block)->GetHeader(); auto new_tile_group_header = storage_manager->GetTileGroup(new_location.block)->GetHeader(); auto transaction_id = current_txn->GetTransactionId(); // if we can perform update, then we must have already locked the older // version. PELOTON_ASSERT(tile_group_header->GetTransactionId(old_location.offset) == transaction_id); PELOTON_ASSERT( tile_group_header->GetPrevItemPointer(old_location.offset).IsNull() == true); // check whether the new version is empty. PELOTON_ASSERT(new_tile_group_header->GetTransactionId(new_location.offset) == INVALID_TXN_ID); PELOTON_ASSERT(new_tile_group_header->GetBeginCommitId(new_location.offset) == MAX_CID); PELOTON_ASSERT(new_tile_group_header->GetEndCommitId(new_location.offset) == MAX_CID); // if the executor doesn't call PerformUpdate after AcquireOwnership, // no one will possibly release the write lock acquired by this txn. // Set double linked list tile_group_header->SetPrevItemPointer(old_location.offset, new_location); new_tile_group_header->SetNextItemPointer(new_location.offset, old_location); new_tile_group_header->SetTransactionId(new_location.offset, transaction_id); new_tile_group_header->SetLastReaderCommitId(new_location.offset, current_txn->GetCommitId()); // we should guarantee that the newer version is all set before linking the // newer version to older version. COMPILER_MEMORY_FENCE; // we must be updating the latest version. // Set the header information for the new version ItemPointer *index_entry_ptr = tile_group_header->GetIndirection(old_location.offset); // if there's no primary index on a table, then index_entry_ptr == nullptr. if (index_entry_ptr != nullptr) { new_tile_group_header->SetIndirection(new_location.offset, index_entry_ptr); // Set the index header in an atomic way. // We do it atomically because we don't want any one to see a half-done // pointer. // In case of contention, no one can update this pointer when we are // updating it // because we are holding the write lock. This update should success in // its first trial. UNUSED_ATTRIBUTE auto res = AtomicUpdateItemPointer(index_entry_ptr, new_location); PELOTON_ASSERT(res == true); } // Add the old tuple into the update set current_txn->RecordUpdate(old_location); }
// Add the old tuple into the update set current_txn->RecordUpdate(old_location); } void TimestampOrderingTransactionManager::PerformUpdate( TransactionContext *const current_txn UNUSED_ATTRIBUTE, const ItemPointer &location) { PELOTON_ASSERT(!current_txn->IsReadOnly()); oid_t tile_group_id = location.block; UNUSED_ATTRIBUTE oid_t tuple_id = location.offset; auto storage_manager = storage::StorageManager::GetInstance(); UNUSED_ATTRIBUTE auto tile_group_header = storage_manager->GetTileGroup(tile_group_id)->GetHeader(); PELOTON_ASSERT(tile_group_header->GetTransactionId(tuple_id) == current_txn->GetTransactionId()); PELOTON_ASSERT(tile_group_header->GetBeginCommitId(tuple_id) == MAX_CID); PELOTON_ASSERT(tile_group_header->GetEndCommitId(tuple_id) == MAX_CID); // no need to add the older version into the update set. // if there exists older version, then the older version must already // been added to the update set. // if there does not exist an older version, then it means that the // transaction // is updating a version that is installed by itself. // in this case, nothing needs to be performed. }