Ejemplo n.º 1
0
Tile *Tile::CopyTile(BackendType backend_type) {
  auto schema = GetSchema();
  bool tile_columns_inlined = schema->IsInlined();
  auto allocated_tuple_count = GetAllocatedTupleCount();

  // Create a shallow copy of the old tile
  TileGroupHeader *new_header = GetHeader();
  Tile *new_tile = TileFactory::GetTile(
      backend_type, INVALID_OID, INVALID_OID, INVALID_OID, INVALID_OID,
      new_header, *schema, tile_group, allocated_tuple_count);

  PL_MEMCPY(static_cast<void *>(new_tile->data), static_cast<void *>(data),
            tile_size);

  // Do a deep copy if some column is uninlined, so that
  // the values in that column point to the new pool
  if (!tile_columns_inlined) {
    auto uninlined_col_cnt = schema->GetUninlinedColumnCount();

    // Go over each uninlined column, making a deep copy
    for (oid_t col_itr = 0; col_itr < uninlined_col_cnt; col_itr++) {
      auto uninlined_col_offset = schema->GetUninlinedColumn(col_itr);

      // Copy the column over to the new tile group
      for (oid_t tuple_itr = 0; tuple_itr < allocated_tuple_count;
           tuple_itr++) {
        type::Value val =
            (new_tile->GetValue(tuple_itr, uninlined_col_offset));
        new_tile->SetValue(val, tuple_itr, uninlined_col_offset);
      }
    }
  }

  return new_tile;
}
Ejemplo n.º 2
0
/**
 * Insert tuple at slot
 * NOTE : No checks, must be at valid slot.
 */
void Tile::InsertTuple(const oid_t tuple_offset, Tuple *tuple) {
  PL_ASSERT(tuple_offset < GetAllocatedTupleCount());

  // Find slot location
  char *location = tuple_offset * tuple_length + data;

  // Copy over the tuple data into the tuple slot in the tile
  PL_MEMCPY(location, tuple->tuple_data_, tuple_length);
}
Ejemplo n.º 3
0
/**
 * Insert tuple at slot
 * NOTE : No checks, must be at valid slot.
 */
void Tile::InsertTuple(const oid_t tuple_offset, Tuple *tuple) {
  assert(tuple_offset < GetAllocatedTupleCount());

  // Find slot location
  char *location = tuple_offset * tuple_length + data;

  // Copy over the tuple data into the tuple slot in the tile
  std::memcpy(location, tuple->tuple_data, tuple_length);
}
Ejemplo n.º 4
0
// column offset is the actual offset of the column within the tuple slot
common::Value *Tile::GetValueFast(const oid_t tuple_offset, const size_t column_offset,
                                  const common::Type::TypeId column_type, const bool is_inlined) {
    PL_ASSERT(tuple_offset < GetAllocatedTupleCount());
    PL_ASSERT(column_offset < schema.GetLength());

    const char *tuple_location = GetTupleLocation(tuple_offset);
    const char *field_location = tuple_location + column_offset;

    return common::Value::DeserializeFrom(field_location, column_type, is_inlined);
}
Ejemplo n.º 5
0
// column offset is the actual offset of the column within the tuple slot
Value Tile::GetValueFast(const oid_t tuple_offset, const size_t column_offset,
                         const ValueType column_type, const bool is_inlined) {
  assert(tuple_offset < GetAllocatedTupleCount());
  assert(column_offset < schema.GetLength());

  const char *tuple_location = GetTupleLocation(tuple_offset);
  const char *field_location = tuple_location + column_offset;

  return Value::InitFromTupleStorage(field_location, column_type, is_inlined);
}
Ejemplo n.º 6
0
// column id is a 0-based column number
common::Value *Tile::GetValue(const oid_t tuple_offset, const oid_t column_id) {
    PL_ASSERT(tuple_offset < GetAllocatedTupleCount());
    PL_ASSERT(column_id < schema.GetColumnCount());

    const common::Type::TypeId column_type = schema.GetType(column_id);

    const char *tuple_location = GetTupleLocation(tuple_offset);
    const char *field_location = tuple_location + schema.GetOffset(column_id);
    const bool is_inlined = schema.IsInlined(column_id);

    return common::Value::DeserializeFrom(field_location, column_type, is_inlined);
}
Ejemplo n.º 7
0
// column id is a 0-based column number
Value Tile::GetValue(const oid_t tuple_offset, const oid_t column_id) {
  assert(tuple_offset < GetAllocatedTupleCount());
  assert(column_id < schema.GetColumnCount());

  const ValueType column_type = schema.GetType(column_id);

  const char *tuple_location = GetTupleLocation(tuple_offset);
  const char *field_location = tuple_location + schema.GetOffset(column_id);
  const bool is_inlined = schema.IsInlined(column_id);

  return Value::InitFromTupleStorage(field_location, column_type, is_inlined);
}
Ejemplo n.º 8
0
storage::TileGroup *DataTable::TransformTileGroup(
    const oid_t &tile_group_offset, const double &theta) {
  // First, check if the tile group is in this table
  if (tile_group_offset >= tile_groups_.GetSize()) {
    LOG_ERROR("Tile group offset not found in table : %u ", tile_group_offset);
    return nullptr;
  }

  auto tile_group_id =
      tile_groups_.FindValid(tile_group_offset, invalid_tile_group_id);

  // Get orig tile group from catalog
  auto &catalog_manager = catalog::Manager::GetInstance();
  auto tile_group = catalog_manager.GetTileGroup(tile_group_id);
  auto diff = tile_group->GetSchemaDifference(default_partition_);

  // Check threshold for transformation
  if (diff < theta) {
    return nullptr;
  }

  LOG_TRACE("Transforming tile group : %u", tile_group_offset);

  // Get the schema for the new transformed tile group
  auto new_schema =
      TransformTileGroupSchema(tile_group.get(), default_partition_);

  // Allocate space for the transformed tile group
  std::shared_ptr<storage::TileGroup> new_tile_group(
      TileGroupFactory::GetTileGroup(
          tile_group->GetDatabaseId(), tile_group->GetTableId(),
          tile_group->GetTileGroupId(), tile_group->GetAbstractTable(),
          new_schema, default_partition_,
          tile_group->GetAllocatedTupleCount()));

  // Set the transformed tile group column-at-a-time
  SetTransformedTileGroup(tile_group.get(), new_tile_group.get());

  // Set the location of the new tile group
  // and clean up the orig tile group
  catalog_manager.AddTileGroup(tile_group_id, new_tile_group);

  return new_tile_group.get();
}
Ejemplo n.º 9
0
// Validate that MVCC storage is correct, it assumes an old-to-new chain
// Invariants
// 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
// 2. Begin commit id should <= end commit id
// 3. Timestamp consistence
// 4. Version doubly linked list consistency
static void ValidateMVCC_OldToNew(storage::DataTable *table) {
  auto &catalog_manager = catalog::Manager::GetInstance();
  LOG_INFO("Validating MVCC storage");
  int tile_group_count = table->GetTileGroupCount();
  LOG_INFO("The table has %d tile groups in the table", tile_group_count);

  for (int tile_group_offset = 0; tile_group_offset < tile_group_count;
       tile_group_offset++) {
    LOG_INFO("Validate tile group #%d", tile_group_offset);
    auto tile_group = table->GetTileGroup(tile_group_offset);
    auto tile_group_header = tile_group->GetHeader();
    size_t tuple_count = tile_group->GetAllocatedTupleCount();
    LOG_INFO("Tile group #%d has allocated %lu tuples", tile_group_offset,
             tuple_count);

    // 1. Transaction id should either be INVALID_TXNID or INITIAL_TXNID
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      EXPECT_TRUE(txn_id == INVALID_TXN_ID || txn_id == INITIAL_TXN_ID)
          << "Transaction id is not INVALID_TXNID or INITIAL_TXNID";
    }

    LOG_INFO("[OK] All tuples have valid txn id");

    // double avg_version_chain_length = 0.0;
    for (oid_t tuple_slot = 0; tuple_slot < tuple_count; tuple_slot++) {
      txn_id_t txn_id = tile_group_header->GetTransactionId(tuple_slot);
      cid_t begin_cid = tile_group_header->GetBeginCommitId(tuple_slot);
      cid_t end_cid = tile_group_header->GetEndCommitId(tuple_slot);
      ItemPointer next_location =
          tile_group_header->GetNextItemPointer(tuple_slot);
      ItemPointer prev_location =
          tile_group_header->GetPrevItemPointer(tuple_slot);

      // 2. Begin commit id should <= end commit id
      EXPECT_TRUE(begin_cid <= end_cid)
          << "Tuple begin commit id is less than or equal to end commit id";

      // This test assumes a oldest-to-newest version chain
      if (txn_id != INVALID_TXN_ID) {
        EXPECT_TRUE(begin_cid != MAX_CID)
            << "Non invalid txn shouldn't have a MAX_CID begin commit id";

        // The version is an oldest version
        if (prev_location.IsNull()) {
          if (next_location.IsNull()) {
            EXPECT_EQ(end_cid, MAX_CID)
                << "Single version has a non MAX_CID end commit time";
          } else {
            cid_t prev_end_cid = end_cid;
            ItemPointer prev_location(tile_group->GetTileGroupId(), tuple_slot);
            while (!next_location.IsNull()) {
              auto next_tile_group =
                  catalog_manager.GetTileGroup(next_location.block);
              auto next_tile_group_header = next_tile_group->GetHeader();

              txn_id_t next_txn_id = next_tile_group_header->GetTransactionId(
                  next_location.offset);

              if (next_txn_id == INVALID_TXN_ID) {
                // If a version in the version chain has a INVALID_TXN_ID, it
                // must be at the tail
                // of the chain. It is either because we have deleted a tuple
                // (so append a invalid tuple),
                // or because this new version is aborted.
                EXPECT_TRUE(
                    next_tile_group_header->GetNextItemPointer(
                                                next_location.offset).IsNull())
                    << "Invalid version in a version chain and is not delete";
              }

              cid_t next_begin_cid = next_tile_group_header->GetBeginCommitId(
                  next_location.offset);
              cid_t next_end_cid =
                  next_tile_group_header->GetEndCommitId(next_location.offset);

              // 3. Timestamp consistence
              if (next_begin_cid == MAX_CID) {
                // It must be an aborted version, it should be at the end of the
                // chain
                EXPECT_TRUE(
                    next_tile_group_header->GetNextItemPointer(
                                                next_location.offset).IsNull())
                    << "Version with MAX_CID begin cid is not version tail";
              } else {
                EXPECT_EQ(prev_end_cid, next_begin_cid)
                    << "Prev end commit id should equal net begin commit id";
                ItemPointer next_prev_location =
                    next_tile_group_header->GetPrevItemPointer(
                        next_location.offset);

                // 4. Version doubly linked list consistency
                EXPECT_TRUE(next_prev_location.offset == prev_location.offset &&
                            next_prev_location.block == prev_location.block)
                    << "Next version's prev version does not match";
              }

              prev_location = next_location;
              prev_end_cid = next_end_cid;
              next_location = next_tile_group_header->GetNextItemPointer(
                  next_location.offset);
            }

            // Now prev_location is at the tail of the version chain
            ItemPointer last_location = prev_location;
            auto last_tile_group =
                catalog_manager.GetTileGroup(last_location.block);
            auto last_tile_group_header = last_tile_group->GetHeader();
            // txn_id_t last_txn_id =
            // last_tile_group_header->GetTransactionId(last_location.offset);
            cid_t last_end_cid =
                last_tile_group_header->GetEndCommitId(last_location.offset);
            EXPECT_TRUE(
                last_tile_group_header->GetNextItemPointer(last_location.offset)
                    .IsNull())
                << "Last version has a next pointer";

            EXPECT_EQ(last_end_cid, MAX_CID)
                << "Last version doesn't end with MAX_CID";
          }
        }
      } else {
        EXPECT_TRUE(tile_group_header->GetNextItemPointer(tuple_slot).IsNull())
            << "Invalid tuple must not have next item pointer";
      }
    }
    LOG_INFO("[OK] oldest-to-newest version chain validated");
  }
}