void LogManager::LogInsert(cid_t commit_id, const ItemPointer &new_location) { if (this->IsInLoggingMode()) { auto logger = this->GetBackendLogger(); auto &manager = catalog::Manager::GetInstance(); auto new_tuple_tile_group = manager.GetTileGroup(new_location.block); auto tile_group = manager.GetTileGroup(new_location.block); auto schema = manager.GetTableWithOid(tile_group->GetDatabaseId(), tile_group->GetTableId())->GetSchema(); std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true)); for (oid_t col = 0; col < schema->GetColumnCount(); col++) { tuple->SetValue(col, new_tuple_tile_group->GetValue(new_location.offset, col), logger->GetVarlenPool()); } std::unique_ptr<LogRecord> record(logger->GetTupleRecord( LOGRECORD_TYPE_TUPLE_INSERT, commit_id, tile_group->GetTableId(), new_tuple_tile_group->GetDatabaseId(), new_location, INVALID_ITEMPOINTER, tuple.get())); logger->Log(record.get()); } }
void LogManager::LogUpdate(cid_t commit_id, const ItemPointer &old_version, const ItemPointer &new_version) { if (this->IsInLoggingMode()) { auto &manager = catalog::Manager::GetInstance(); auto new_tuple_tile_group = manager.GetTileGroup(new_version.block); auto logger = this->GetBackendLogger(); auto schema = manager.GetTableWithOid(new_tuple_tile_group->GetDatabaseId(), new_tuple_tile_group->GetTableId()) ->GetSchema(); // Can we avoid allocate tuple in head each time? std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true)); for (oid_t col = 0; col < schema->GetColumnCount(); col++) { tuple->SetValue(col, new_tuple_tile_group->GetValue(new_version.offset, col), logger->GetVarlenPool()); } std::unique_ptr<LogRecord> record( logger->GetTupleRecord(LOGRECORD_TYPE_TUPLE_UPDATE, commit_id, new_tuple_tile_group->GetTableId(), new_tuple_tile_group->GetDatabaseId(), new_version, old_version, tuple.get())); logger->Log(record.get()); } }
void LogManager::LogDelete(cid_t commit_id, const ItemPointer &delete_location) { if (this->IsInLoggingMode()) { auto logger = this->GetBackendLogger(); auto &manager = catalog::Manager::GetInstance(); auto tile_group = manager.GetTileGroup(delete_location.block); std::unique_ptr<LogRecord> record(logger->GetTupleRecord( LOGRECORD_TYPE_TUPLE_DELETE, commit_id, tile_group->GetTableId(), tile_group->GetDatabaseId(), INVALID_ITEMPOINTER, delete_location)); logger->Log(record.get()); } }
// Do insert and create insert tuple log records std::vector<ItemPointer> InsertTuples( storage::DataTable* table, const std::vector<storage::Tuple*>& tuples, bool committed) { std::vector<ItemPointer> locations; auto& txn_manager = concurrency::TransactionManagerFactory::GetInstance(); for (auto tuple : tuples) { auto txn = txn_manager.BeginTransaction(); ItemPointer location = table->InsertTuple(tuple); if (location.block == INVALID_OID) { txn->SetResult(Result::RESULT_FAILURE); LOG_ERROR("Insert failed"); exit(EXIT_FAILURE); } txn->RecordInsert(location); locations.push_back(location); // Logging { auto& log_manager = logging::LogManager::GetInstance(); if (log_manager.IsInLoggingMode()) { auto logger = log_manager.GetBackendLogger(); auto record = logger->GetTupleRecord( LOGRECORD_TYPE_TUPLE_INSERT, txn->GetTransactionId(), table->GetOid(), location, INVALID_ITEMPOINTER, tuple, LOGGING_TESTS_DATABASE_OID); logger->Log(record); } } // commit or abort as required if (committed) { txn_manager.CommitTransaction(); } else { txn_manager.AbortTransaction(); } } return locations; }
/** * @brief Adds a column to the logical tile, using the position lists. * @return true on success, false otherwise. */ bool InsertExecutor::DExecute() { if (done_) return false; assert(!done_); assert(executor_context_ != nullptr); const planner::InsertPlan &node = GetPlanNode<planner::InsertPlan>(); storage::DataTable *target_table_ = node.GetTable(); oid_t bulk_insert_count = node.GetBulkInsertCount(); assert(target_table_); auto transaction_ = executor_context_->GetTransaction(); auto executor_pool = executor_context_->GetExecutorContextPool(); // Inserting a logical tile. if (children_.size() == 1) { LOG_INFO("Insert executor :: 1 child \n"); if (!children_[0]->Execute()) { return false; } std::unique_ptr<LogicalTile> logical_tile(children_[0]->GetOutput()); assert(logical_tile.get() != nullptr); auto target_table_schema = target_table_->GetSchema(); auto column_count = target_table_schema->GetColumnCount(); std::unique_ptr<storage::Tuple> tuple( new storage::Tuple(target_table_schema, true)); // Go over the logical tile for (oid_t tuple_id : *logical_tile) { expression::ContainerTuple<LogicalTile> cur_tuple(logical_tile.get(), tuple_id); // Materialize the logical tile tuple for (oid_t column_itr = 0; column_itr < column_count; column_itr++) tuple->SetValue(column_itr, cur_tuple.GetValue(column_itr), executor_pool); peloton::ItemPointer location = target_table_->InsertTuple(transaction_, tuple.get()); if (location.block == INVALID_OID) { transaction_->SetResult(peloton::Result::RESULT_FAILURE); return false; } transaction_->RecordInsert(location); executor_context_->num_processed += 1; // insert one } return true; } // Inserting a collection of tuples from plan node else if (children_.size() == 0) { LOG_INFO("Insert executor :: 0 child \n"); // Extract expressions from plan node and construct the tuple. // For now we just handle a single tuple auto schema = target_table_->GetSchema(); std::unique_ptr<storage::Tuple> tuple(new storage::Tuple(schema, true)); auto project_info = node.GetProjectInfo(); // There should be no direct maps assert(project_info); assert(project_info->GetDirectMapList().size() == 0); for (auto target : project_info->GetTargetList()) { peloton::Value value = target.second->Evaluate(nullptr, nullptr, executor_context_); tuple->SetValue(target.first, value, executor_pool); } // Bulk Insert Mode for (oid_t insert_itr = 0; insert_itr < bulk_insert_count; insert_itr++) { // Carry out insertion ItemPointer location = target_table_->InsertTuple(transaction_, tuple.get()); LOG_INFO("Inserted into location: %lu, %lu", location.block, location.offset); if (location.block == INVALID_OID) { LOG_INFO("Failed to Insert. Set txn failure."); transaction_->SetResult(peloton::Result::RESULT_FAILURE); return false; } transaction_->RecordInsert(location); // Logging { auto &log_manager = logging::LogManager::GetInstance(); if (log_manager.IsInLoggingMode()) { auto logger = log_manager.GetBackendLogger(); auto record = logger->GetTupleRecord( LOGRECORD_TYPE_TUPLE_INSERT, transaction_->GetTransactionId(), target_table_->GetOid(), location, INVALID_ITEMPOINTER, tuple.get()); logger->Log(record); } } } executor_context_->num_processed += 1; // insert one done_ = true; return true; } return true; }
/** * @brief Delete the table tuples using the position list in the logical tile. * * If truncate is on, then it will truncate the table itself. * @return true on success, false otherwise. */ bool DeleteExecutor::DExecute() { assert(target_table_); // Retrieve next tile. const bool success = children_[0]->Execute(); if (!success) { return false; } std::unique_ptr<LogicalTile> source_tile(children_[0]->GetOutput()); storage::Tile *tile = source_tile->GetBaseTile(0); storage::TileGroup *tile_group = tile->GetTileGroup(); auto &pos_lists = source_tile.get()->GetPositionLists(); auto tile_group_id = tile_group->GetTileGroupId(); auto transaction_ = executor_context_->GetTransaction(); LOG_INFO("Source tile : %p Tuples : %lu \n", source_tile.get(), source_tile->GetTupleCount()); LOG_INFO("Transaction ID: %lu\n", transaction_->GetTransactionId()); // Delete each tuple for (oid_t visible_tuple_id : *source_tile) { oid_t physical_tuple_id = pos_lists[0][visible_tuple_id]; LOG_INFO("Visible Tuple id : %lu, Physical Tuple id : %lu \n", visible_tuple_id, physical_tuple_id); peloton::ItemPointer delete_location(tile_group_id, physical_tuple_id); // Logging { auto &log_manager = logging::LogManager::GetInstance(); if (log_manager.IsInLoggingMode()) { auto logger = log_manager.GetBackendLogger(); auto record = logger->GetTupleRecord( LOGRECORD_TYPE_TUPLE_DELETE, transaction_->GetTransactionId(), target_table_->GetOid(), INVALID_ITEMPOINTER, delete_location); logger->Log(record); } } // try to delete the tuple // this might fail due to a concurrent operation that has latched the tuple bool status = target_table_->DeleteTuple(transaction_, delete_location); if (status == false) { LOG_INFO("Fail to delete. Set txn failure"); transaction_->SetResult(peloton::Result::RESULT_FAILURE); return false; } executor_context_->num_processed += 1; // deleted one transaction_->RecordDelete(delete_location); } return true; }