bool PessimisticTxnManager::PerformDelete(const oid_t &tile_group_id,
                                          const oid_t &tuple_id,
                                          const ItemPointer &new_location) {
  LOG_TRACE("Performing Delete");
  auto transaction_id = current_txn->GetTransactionId();

  auto tile_group_header =
      catalog::Manager::GetInstance().GetTileGroup(tile_group_id)->GetHeader();
  auto new_tile_group_header = catalog::Manager::GetInstance()
      .GetTileGroup(new_location.block)->GetHeader();


  assert(tile_group_header->GetTransactionId(tuple_id) == transaction_id);
  assert(new_tile_group_header->GetTransactionId(new_location.offset) == INVALID_TXN_ID);
  assert(new_tile_group_header->GetBeginCommitId(new_location.offset) == MAX_CID);
  assert(new_tile_group_header->GetEndCommitId(new_location.offset) == MAX_CID);

  // Set up double linked list
  tile_group_header->SetNextItemPointer(tuple_id, new_location);
  new_tile_group_header->SetPrevItemPointer(
      new_location.offset, ItemPointer(tile_group_id, tuple_id));

  new_tile_group_header->SetTransactionId(new_location.offset, transaction_id);
  new_tile_group_header->SetEndCommitId(new_location.offset, INVALID_CID);

  current_txn->RecordDelete(tile_group_id, tuple_id);
  return true;
}
bool PessimisticTxnManager::PerformUpdate(const oid_t &tile_group_id,
                                          const oid_t &tuple_id,
                                          const ItemPointer &new_location) {
  LOG_INFO("Performing Write %lu %lu", tile_group_id, tuple_id);

  auto transaction_id = current_txn->GetTransactionId();

  auto tile_group_header =
      catalog::Manager::GetInstance().GetTileGroup(tile_group_id)->GetHeader();
  auto new_tile_group_header = catalog::Manager::GetInstance()
      .GetTileGroup(new_location.block)->GetHeader();

  // if we can perform update, then we must have already locked the older
  // version.
  assert(tile_group_header->GetTransactionId(tuple_id) == transaction_id);
  assert(new_tile_group_header->GetTransactionId(new_location.offset) == INVALID_TXN_ID);
  assert(new_tile_group_header->GetBeginCommitId(new_location.offset) == MAX_CID);
  assert(new_tile_group_header->GetEndCommitId(new_location.offset) == MAX_CID);
  tile_group_header->SetTransactionId(tuple_id, transaction_id);

  // The write lock must have been acquired
  // Notice: 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->SetNextItemPointer(tuple_id, new_location);
  new_tile_group_header->SetPrevItemPointer(
      new_location.offset, ItemPointer(tile_group_id, tuple_id));

  new_tile_group_header->SetTransactionId(new_location.offset, transaction_id);

  // Add the old tuple into the update set
  current_txn->RecordUpdate(tile_group_id, tuple_id);
  return true;
}
Esempio n. 3
0
TEST_F(LoggingTests, BasicDeleteTest) {
  auto recovery_table = ExecutorTestsUtil::CreateTable(1024);
  auto &manager = catalog::Manager::GetInstance();
  storage::Database db(DEFAULT_DB_ID);
  manager.AddDatabase(&db);
  db.AddTable(recovery_table);

  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 0);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 1);
  logging::WriteAheadFrontendLogger fel(true);

  cid_t test_commit_id = 10;

  auto curr_rec = new logging::TupleRecord(
      LOGRECORD_TYPE_TUPLE_UPDATE, test_commit_id, recovery_table->GetOid(),
      INVALID_ITEMPOINTER, ItemPointer(100, 4), nullptr, DEFAULT_DB_ID);
  fel.DeleteTuple(curr_rec);

  delete curr_rec;

  auto tg_header = recovery_table->GetTileGroupById(100)->GetHeader();
  EXPECT_EQ(tg_header->GetEndCommitId(4), test_commit_id);

  //  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 1);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 2);
}
Esempio n. 4
0
// this function returns a free tuple slot, if one exists
// called by data_table.
ItemPointer GCManager::ReturnFreeSlot(const oid_t &table_id) {
  if (this->gc_type_ == GC_TYPE_OFF) {
    return INVALID_ITEMPOINTER;
  }

  std::shared_ptr<LockfreeQueue<TupleMetadata>> recycle_queue;
  // if there exists recycle_queue
  if (recycle_queue_map_.find(table_id, recycle_queue) == true) {
    TupleMetadata tuple_metadata;
    if (recycle_queue->Dequeue(tuple_metadata) == true) {
      LOG_TRACE("Reuse tuple(%u, %u) in table %u", tuple_metadata.tile_group_id,
               tuple_metadata.tuple_slot_id, table_id);
      return ItemPointer(tuple_metadata.tile_group_id,
                         tuple_metadata.tuple_slot_id);
    }
  }
  return ItemPointer();
}
Esempio n. 5
0
TEST_F(LoggingTests, BasicUpdateTest) {
  auto recovery_table = ExecutorTestsUtil::CreateTable(1024);
  auto &manager = catalog::Manager::GetInstance();
  storage::Database db(DEFAULT_DB_ID);
  manager.AddDatabase(&db);
  db.AddTable(recovery_table);

  auto tuples = BuildLoggingTuples(recovery_table, 1, false, false);
  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 0);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 1);
  EXPECT_EQ(tuples.size(), 1);
  logging::WriteAheadFrontendLogger fel(true);
  //  auto bel = logging::WriteAheadBackendLogger::GetInstance();
  cid_t test_commit_id = 10;

  Value val0 = tuples[0]->GetValue(0);
  Value val1 = tuples[0]->GetValue(1);
  Value val2 = tuples[0]->GetValue(2);
  Value val3 = tuples[0]->GetValue(3);

  auto curr_rec = new logging::TupleRecord(
      LOGRECORD_TYPE_TUPLE_UPDATE, test_commit_id, recovery_table->GetOid(),
      ItemPointer(100, 5), ItemPointer(100, 4), tuples[0], DEFAULT_DB_ID);
  curr_rec->SetTuple(tuples[0]);
  fel.UpdateTuple(curr_rec);
  delete curr_rec;

  auto tg_header = recovery_table->GetTileGroupById(100)->GetHeader();
  EXPECT_TRUE(tg_header->GetBeginCommitId(5) <= test_commit_id);
  EXPECT_EQ(tg_header->GetEndCommitId(5), MAX_CID);
  EXPECT_EQ(tg_header->GetEndCommitId(4), test_commit_id);

  EXPECT_TRUE(
      val0.Compare(recovery_table->GetTileGroupById(100)->GetValue(5, 0)) == 0);
  EXPECT_TRUE(
      val1.Compare(recovery_table->GetTileGroupById(100)->GetValue(5, 1)) == 0);
  EXPECT_TRUE(
      val2.Compare(recovery_table->GetTileGroupById(100)->GetValue(5, 2)) == 0);
  EXPECT_TRUE(
      val3.Compare(recovery_table->GetTileGroupById(100)->GetValue(5, 3)) == 0);

  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 0);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 2);
}
Esempio n. 6
0
TEST_F(LoggingTests, OutOfOrderCommitTest) {
  auto recovery_table = ExecutorTestsUtil::CreateTable(1024);
  auto &manager = catalog::Manager::GetInstance();
  storage::Database db(DEFAULT_DB_ID);
  manager.AddDatabase(&db);
  db.AddTable(recovery_table);

  auto tuples = BuildLoggingTuples(recovery_table, 1, false, false);
  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 0);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 1);
  EXPECT_EQ(tuples.size(), 1);
  logging::WriteAheadFrontendLogger fel(true);
  //  auto bel = logging::WriteAheadBackendLogger::GetInstance();
  cid_t test_commit_id = 10;

  auto curr_rec = new logging::TupleRecord(
      LOGRECORD_TYPE_TUPLE_UPDATE, test_commit_id + 1, recovery_table->GetOid(),
      INVALID_ITEMPOINTER, ItemPointer(100, 5), nullptr, DEFAULT_DB_ID);
  fel.DeleteTuple(curr_rec);
  delete curr_rec;

  EXPECT_EQ(recovery_table->GetTileGroupCount(), 2);

  curr_rec = new logging::TupleRecord(
      LOGRECORD_TYPE_TUPLE_INSERT, test_commit_id, recovery_table->GetOid(),
      ItemPointer(100, 5), INVALID_ITEMPOINTER, tuples[0], DEFAULT_DB_ID);

  curr_rec->SetTuple(tuples[0]);
  fel.InsertTuple(curr_rec);

  delete curr_rec;

  auto tg_header = recovery_table->GetTileGroupById(100)->GetHeader();
  EXPECT_EQ(tg_header->GetEndCommitId(5), test_commit_id + 1);

  EXPECT_EQ(recovery_table->GetNumberOfTuples(), 0);
  EXPECT_EQ(recovery_table->GetTileGroupCount(), 2);
}
Esempio n. 7
0
/**
 * @brief Move Tuples from log record-based local transaction to recovery
 * transaction
 * @param destination
 * @param source
 */
void AriesFrontendLogger::MoveTuples(concurrency::Transaction *destination,
                                     concurrency::Transaction *source) {
  // This is the local transaction
  auto inserted_tuples = source->GetInsertedTuples();
  // Record the inserts in recovery txn
  for (auto entry : inserted_tuples) {
    oid_t tile_group_id = entry.first;
    for (auto tuple_slot : entry.second) {
      destination->RecordInsert(ItemPointer(tile_group_id, tuple_slot));
    }
  }

  // Record the deletes in recovery txn
  auto deleted_tuples = source->GetDeletedTuples();
  for (auto entry : deleted_tuples) {
    oid_t tile_group_id = entry.first;
    for (auto tuple_slot : entry.second) {
      destination->RecordDelete(ItemPointer(tile_group_id, tuple_slot));
    }
  }

  // Clear inserted/deleted tuples from txn, just in case
  source->ResetState();
}
Esempio n. 8
0
TEST_F(LogRecordTests, LogRecordTest) {
  
  std::vector<LogRecordType> tuple_type_list = {
    LogRecordType::TUPLE_INSERT,
    LogRecordType::TUPLE_DELETE,
    LogRecordType::TUPLE_UPDATE
  };

  for (auto type : tuple_type_list) {
    logging::LogRecord tuple_record = 
        logging::LogRecordFactory::CreateTupleRecord(type, ItemPointer(0, 0));

    EXPECT_EQ(tuple_record.GetType(), type);
  }
  
  std::vector<LogRecordType> txn_type_list = {
    LogRecordType::TRANSACTION_BEGIN,
    LogRecordType::TRANSACTION_COMMIT
  };

  for (auto type : txn_type_list) {
    logging::LogRecord txn_record = 
        logging::LogRecordFactory::CreateTxnRecord(type, 50);

    EXPECT_EQ(txn_record.GetType(), type);
  }

  std::vector<LogRecordType> epoch_type_list = {
    LogRecordType::EPOCH_BEGIN, 
    LogRecordType::EPOCH_END
  };

  for (auto type : epoch_type_list) {
    logging::LogRecord epoch_record = 
        logging::LogRecordFactory::CreateEpochRecord(type, 100);

    EXPECT_EQ(epoch_record.GetType(), type);
  }
}
Esempio n. 9
0
TEST_F(LogicalTileTests, TileMaterializationTest) {
    const int tuple_count = 4;
    std::shared_ptr<storage::TileGroup> tile_group(
        ExecutorTestsUtil::CreateTileGroup(tuple_count));

    // Create tuple schema from tile schemas.
    std::vector<catalog::Schema> &tile_schemas = tile_group->GetTileSchemas();
    std::unique_ptr<catalog::Schema> schema(
        catalog::Schema::AppendSchemaList(tile_schemas));

    // Create tuples and insert them into tile group.
    const bool allocate = true;
    storage::Tuple tuple1(schema.get(), allocate);
    storage::Tuple tuple2(schema.get(), allocate);
    auto pool = tile_group->GetTilePool(1);

    tuple1.SetValue(0, ValueFactory::GetIntegerValue(1), pool);
    tuple1.SetValue(1, ValueFactory::GetIntegerValue(1), pool);
    tuple1.SetValue(2, ValueFactory::GetTinyIntValue(1), pool);
    tuple1.SetValue(3, ValueFactory::GetStringValue("tuple 1"), pool);

    tuple2.SetValue(0, ValueFactory::GetIntegerValue(2), pool);
    tuple2.SetValue(1, ValueFactory::GetIntegerValue(2), pool);
    tuple2.SetValue(2, ValueFactory::GetTinyIntValue(2), pool);
    tuple2.SetValue(3, ValueFactory::GetStringValue("tuple 2"), pool);

    auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
    txn_manager.BeginTransaction();
    // txn_id_t txn_id = txn->GetTransactionId();

    auto tuple_id1 = tile_group->InsertTuple(&tuple1);
    auto tuple_id2 = tile_group->InsertTuple(&tuple2);
    auto tuple_id3 = tile_group->InsertTuple(&tuple1);

    txn_manager.PerformInsert(ItemPointer(tile_group->GetTileGroupId(), tuple_id1));
    txn_manager.PerformInsert(ItemPointer(tile_group->GetTileGroupId(), tuple_id2));
    txn_manager.PerformInsert(ItemPointer(tile_group->GetTileGroupId(), tuple_id3));

    txn_manager.CommitTransaction();

    ////////////////////////////////////////////////////////////////
    // LOGICAL TILE (1 BASE TILE)
    ////////////////////////////////////////////////////////////////

    // Don't transfer ownership of any base tile to logical tile.
    auto base_tile_ref = tile_group->GetTileReference(1);

    std::vector<oid_t> position_list1 = {0, 1};
    std::vector<oid_t> position_list2 = {0, 1};

    std::unique_ptr<executor::LogicalTile> logical_tile(
        executor::LogicalTileFactory::GetTile());

    logical_tile->AddPositionList(std::move(position_list1));
    logical_tile->AddPositionList(std::move(position_list2));

    assert(tile_schemas.size() == 2);
    catalog::Schema *schema1 = &tile_schemas[0];
    catalog::Schema *schema2 = &tile_schemas[1];
    oid_t column_count = schema2->GetColumnCount();
    for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
        logical_tile->AddColumn(base_tile_ref, column_itr, column_itr);
    }

    LOG_INFO("%s", logical_tile->GetInfo().c_str());

    ////////////////////////////////////////////////////////////////
    // LOGICAL TILE (2 BASE TILE)
    ////////////////////////////////////////////////////////////////

    logical_tile.reset(executor::LogicalTileFactory::GetTile());

    auto base_tile_ref1 = tile_group->GetTileReference(0);
    auto base_tile_ref2 = tile_group->GetTileReference(1);

    position_list1 = {0, 1};
    position_list2 = {0, 1};
    std::vector<oid_t> position_list3 = {0, 1};
    std::vector<oid_t> position_list4 = {0, 1};

    logical_tile->AddPositionList(std::move(position_list1));
    logical_tile->AddPositionList(std::move(position_list2));
    logical_tile->AddPositionList(std::move(position_list3));
    logical_tile->AddPositionList(std::move(position_list4));

    oid_t column_count1 = schema1->GetColumnCount();
    for (oid_t column_itr = 0; column_itr < column_count1; column_itr++) {
        logical_tile->AddColumn(base_tile_ref1, column_itr, column_itr);
    }

    oid_t column_count2 = schema2->GetColumnCount();
    for (oid_t column_itr = 0; column_itr < column_count2; column_itr++) {
        logical_tile->AddColumn(base_tile_ref2, column_itr,
                                column_count1 + column_itr);
    }

    LOG_INFO("%s", logical_tile->GetInfo().c_str());
}
Esempio n. 10
0
TEST_F(LogicalTileTests, TileMaterializationTest) {
  const int tuple_count = 4;
  std::shared_ptr<storage::TileGroup> tile_group(
      TestingExecutorUtil::CreateTileGroup(tuple_count));

  std::vector<const catalog::Schema *> tile_schemas;
  for (unsigned int i = 0; i < tile_group->NumTiles(); i++) {
    tile_schemas.push_back(tile_group->GetTile(i)->GetSchema());
  }

  // Create tuple schema from tile schemas.
  std::unique_ptr<catalog::Schema> schema(
      catalog::Schema::AppendSchemaPtrList(tile_schemas));

  // Create tuples and insert them into tile group.
  const bool allocate = true;
  storage::Tuple tuple1(schema.get(), allocate);
  storage::Tuple tuple2(schema.get(), allocate);
  auto pool = tile_group->GetTilePool(1);

  tuple1.SetValue(0, type::ValueFactory::GetIntegerValue(1), pool);
  tuple1.SetValue(1, type::ValueFactory::GetIntegerValue(1), pool);
  tuple1.SetValue(2, type::ValueFactory::GetTinyIntValue(1), pool);
  tuple1.SetValue(3, type::ValueFactory::GetVarcharValue("tuple 1"), pool);

  tuple2.SetValue(0, type::ValueFactory::GetIntegerValue(2), pool);
  tuple2.SetValue(1, type::ValueFactory::GetIntegerValue(2), pool);
  tuple2.SetValue(2, type::ValueFactory::GetTinyIntValue(2), pool);
  tuple2.SetValue(3, type::ValueFactory::GetVarcharValue("tuple 2"), pool);

  auto &txn_manager = concurrency::TransactionManagerFactory::GetInstance();
  auto txn = txn_manager.BeginTransaction();
  // txn_id_t txn_id = txn->GetTransactionId();

  auto tuple_id1 = tile_group->InsertTuple(&tuple1);
  auto tuple_id2 = tile_group->InsertTuple(&tuple2);
  auto tuple_id3 = tile_group->InsertTuple(&tuple1);

  ItemPointer *index_entry_ptr = nullptr;
  txn_manager.PerformInsert(
      txn, ItemPointer(tile_group->GetTileGroupId(), tuple_id1),
      index_entry_ptr);
  txn_manager.PerformInsert(
      txn, ItemPointer(tile_group->GetTileGroupId(), tuple_id2),
      index_entry_ptr);
  txn_manager.PerformInsert(
      txn, ItemPointer(tile_group->GetTileGroupId(), tuple_id3),
      index_entry_ptr);

  txn_manager.CommitTransaction(txn);

  ////////////////////////////////////////////////////////////////
  // LOGICAL TILE (1 BASE TILE)
  ////////////////////////////////////////////////////////////////

  // Don't transfer ownership of any base tile to logical tile.
  auto base_tile_ref = tile_group->GetTileReference(1);

  std::vector<oid_t> position_list1 = {0, 1};
  std::vector<oid_t> position_list2 = {0, 1};

  std::unique_ptr<executor::LogicalTile> logical_tile(
      executor::LogicalTileFactory::GetTile());

  logical_tile->AddPositionList(std::move(position_list1));
  logical_tile->AddPositionList(std::move(position_list2));

  oid_t column_count = tile_schemas[1]->GetColumnCount();
  for (oid_t column_itr = 0; column_itr < column_count; column_itr++) {
    logical_tile->AddColumn(base_tile_ref, column_itr, column_itr);
  }

  LOG_TRACE("%s", logical_tile->GetInfo().c_str());

  ////////////////////////////////////////////////////////////////
  // LOGICAL TILE (2 BASE TILE)
  ////////////////////////////////////////////////////////////////

  logical_tile.reset(executor::LogicalTileFactory::GetTile());

  auto base_tile_ref1 = tile_group->GetTileReference(0);
  auto base_tile_ref2 = tile_group->GetTileReference(1);

  position_list1 = {0, 1};
  position_list2 = {0, 1};
  std::vector<oid_t> position_list3 = {0, 1};
  std::vector<oid_t> position_list4 = {0, 1};

  logical_tile->AddPositionList(std::move(position_list1));
  logical_tile->AddPositionList(std::move(position_list2));
  logical_tile->AddPositionList(std::move(position_list3));
  logical_tile->AddPositionList(std::move(position_list4));

  oid_t column_count1 = tile_schemas[0]->GetColumnCount();
  for (oid_t column_itr = 0; column_itr < column_count1; column_itr++) {
    logical_tile->AddColumn(base_tile_ref1, column_itr, column_itr);
  }

  oid_t column_count2 = tile_schemas[1]->GetColumnCount();
  for (oid_t column_itr = 0; column_itr < column_count2; column_itr++) {
    logical_tile->AddColumn(base_tile_ref2, column_itr,
                            column_count1 + column_itr);
  }

  LOG_TRACE("%s", logical_tile->GetInfo().c_str());
}