<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// tile_group_header.h
//
// Identification: src/backend/storage/tile_group_header.h
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#pragma once

#include "backend/common/logger.h"
#include "backend/common/platform.h"
#include "backend/common/printable.h"
#include "backend/logging/log_manager.h"
#include "backend/gc/gc_manager.h"
#include "backend/expression/container_tuple.h"

#include <atomic>
#include <mutex>
#include <iostream>
#include <cassert>
#include <queue>
#include <cstring>

namespace peloton {
namespace storage {

//===--------------------------------------------------------------------===//
// Tile Group Header
//===--------------------------------------------------------------------===//

/**
 *
 * This contains information related to MVCC.
 * It is shared by all tiles in a tile group.
 *
 * Layout :
 *
 *  -----------------------------------------------------------------------------
 *  | TxnID (8 bytes)  | BeginTimeStamp (8 bytes) | EndTimeStamp (8 bytes) |
 *  | NextItemPointer (16 bytes) | PrevItemPointer (16 bytes) | ReservedField (24 bytes)
 *  | InsertCommit (1 byte) | DeleteCommit (1 byte)
 *  -----------------------------------------------------------------------------
 *
 */

#define TUPLE_HEADER_LOCATION data + (tuple_slot_id * header_entry_size)

class TileGroupHeader : public Printable {
  TileGroupHeader() = delete;

 public:
  TileGroupHeader(const BackendType &backend_type, const int &tuple_count);

  TileGroupHeader &operator=(const peloton::storage::TileGroupHeader &other) {
    // check for self-assignment
    if (&other == this) return *this;

    header_size = other.header_size;

    // copy over all the data
    memcpy(data, other.data, header_size);

    num_tuple_slots = other.num_tuple_slots;
    unsigned long long val = other.next_tuple_slot;
    next_tuple_slot = val;

    return *this;
  }

  ~TileGroupHeader();

  oid_t GetNextEmptyTupleSlot(int get_recycled) {
    oid_t tuple_slot_id = INVALID_OID;

    {
      std::lock_guard<std::mutex> tile_header_lock(tile_header_mutex);

      if(get_recycled) {
        // check if there are recycled tuple slots
        auto& gc_manager = gc::GCManager::GetInstance();
        auto free_slot = gc_manager.ReturnFreeSlot(tile_group->GetDatabaseId(), tile_group->GetTableId());
        if(free_slot != INVALID_OID) {
          tuple_slot_id = free_slot;
          this -> SetTransactionId(tuple_slot_id, INVALID_TXN_ID);
          this -> SetBeginCommitId(tuple_slot_id, MAX_CID);
          this -> SetEndCommitId(tuple_slot_id, MAX_CID);
        }
      }

      if ((tuple_slot_id == INVALID_OID) && (next_tuple_slot < num_tuple_slots)) {
        // check tile group capacity
        tuple_slot_id = next_tuple_slot;
        next_tuple_slot++;
      }
    }
    LOG_INFO("###### LARGEST TUPLE SLOT USED = %lu", GetNextTupleSlot());
    LOG_INFO("###### TUPLE SLOT USED = %lu", tuple_slot_id);
    return tuple_slot_id;
  }

  /**
   * Used by logging
   */
  bool GetEmptyTupleSlot(const oid_t &tuple_slot_id) {
    {
      std::lock_guard<std::mutex> tile_header_lock(tile_header_mutex);

      if (tuple_slot_id < num_tuple_slots) {
        if (next_tuple_slot <= tuple_slot_id) {
          next_tuple_slot = tuple_slot_id + 1;
        }
        return true;
      } else {
        return false;
      }
    }
  }

  inline void RecycleTupleSlot(const oid_t db_id, const oid_t tb_id, const oid_t tg_id, const oid_t t_id, const txn_id_t t) {
    auto& gc_manager = gc::GCManager::GetInstance();
    struct TupleMetadata tm;
    tm.database_id = db_id;
    tm.tile_group_id = tg_id;
    tm.table_id = tb_id;
    tm.tuple_slot_id = t_id;
    tm.transaction_id = t;<commit_msg>Added result file for tuple ID stats<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// tile_group_header.h
//
// Identification: src/backend/storage/tile_group_header.h
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#pragma once

#include "backend/common/logger.h"
#include "backend/common/platform.h"
#include "backend/common/printable.h"
#include "backend/logging/log_manager.h"
#include "backend/gc/gc_manager.h"
#include "backend/expression/container_tuple.h"

#include <atomic>
#include <mutex>
#include <iostream>
#include <cassert>
#include <queue>
#include <cstring>

namespace peloton {
namespace storage {

static std::mutex result_mutex;
static std::unordered_map<oid_t, oid_t> peak_tuple_id;
static FILE *result_file = NULL;

//===--------------------------------------------------------------------===//
// Tile Group Header
//===--------------------------------------------------------------------===//

/**
 *
 * This contains information related to MVCC.
 * It is shared by all tiles in a tile group.
 *
 * Layout :
 *
 *  -----------------------------------------------------------------------------
 *  | TxnID (8 bytes)  | BeginTimeStamp (8 bytes) | EndTimeStamp (8 bytes) |
 *  | NextItemPointer (16 bytes) | PrevItemPointer (16 bytes) | ReservedField (24 bytes)
 *  | InsertCommit (1 byte) | DeleteCommit (1 byte)
 *  -----------------------------------------------------------------------------
 *
 */

#define TUPLE_HEADER_LOCATION data + (tuple_slot_id * header_entry_size)

class TileGroupHeader : public Printable {
  TileGroupHeader() = delete;

 public:
  TileGroupHeader(const BackendType &backend_type, const int &tuple_count);

  TileGroupHeader &operator=(const peloton::storage::TileGroupHeader &other) {
    // check for self-assignment
    if (&other == this) return *this;

    header_size = other.header_size;

    // copy over all the data
    memcpy(data, other.data, header_size);

    num_tuple_slots = other.num_tuple_slots;
    unsigned long long val = other.next_tuple_slot;
    next_tuple_slot = val;

    return *this;
  }

  ~TileGroupHeader();

  oid_t GetNextEmptyTupleSlot(int get_recycled) {
    oid_t tuple_slot_id = INVALID_OID;

    {
      std::lock_guard<std::mutex> tile_header_lock(tile_header_mutex);

      if(get_recycled) {
        // check if there are recycled tuple slots
        auto& gc_manager = gc::GCManager::GetInstance();
        auto free_slot = gc_manager.ReturnFreeSlot(tile_group->GetDatabaseId(), tile_group->GetTableId());
        if(free_slot != INVALID_OID) {
          tuple_slot_id = free_slot;
          this -> SetTransactionId(tuple_slot_id, INVALID_TXN_ID);
          this -> SetBeginCommitId(tuple_slot_id, MAX_CID);
          this -> SetEndCommitId(tuple_slot_id, MAX_CID);
        }
      }

      if ((tuple_slot_id == INVALID_OID) && (next_tuple_slot < num_tuple_slots)) {
        // check tile group capacity
        tuple_slot_id = next_tuple_slot;
        next_tuple_slot++;
      }
    }

    if(result_file == NULL) {
      result_file = fopen("/tmp/result.file", "w");
      assert(!result_file);
    }

    {
      std::lock_guard<std::mutex> lock(result_mutex);

      auto table_id = tile_group->GetTableId();
      if(peak_tuple_id.find(table_id) == peak_tuple_id.end()) {
        peak_tuple_id[table_id] = 0;
      }

      if(peak_tuple_id[table_id] < tuple_slot_id) {
        peak_tuple_id.erase(table_id);
        peak_tuple_id[table_id] = tuple_slot_id;
        fprintf(result_file, "%lu %lu\n", table_id, tuple_slot_id);
        fflush(result_file);
      }
    }

    //LOG_INFO("###### LARGEST TUPLE SLOT USED = %lu", GetNextTupleSlot());
    //LOG_INFO("###### TUPLE SLOT USED = %lu", tuple_slot_id);
    return tuple_slot_id;
  }

  /**
   * Used by logging
   */
  bool GetEmptyTupleSlot(const oid_t &tuple_slot_id) {
    {
      std::lock_guard<std::mutex> tile_header_lock(tile_header_mutex);

      if (tuple_slot_id < num_tuple_slots) {
        if (next_tuple_slot <= tuple_slot_id) {
          next_tuple_slot = tuple_slot_id + 1;
        }
        return true;
      } else {
        return false;
      }
    }
  }

  inline void RecycleTupleSlot(const oid_t db_id, const oid_t tb_id, const oid_t tg_id, const oid_t t_id, const txn_id_t t) {
    auto& gc_manager = gc::GCManager::GetInstance();
    struct TupleMetadata tm;
    tm.database_id = db_id;
    tm.tile_group_id = tg_id;
    tm.table_id = tb_id;
    tm.tuple_slot_id = t_id;
    tm.transaction_id = t;
{'fraction_non_alphanumeric': 0.2120895695556329, 'fraction_numerical': 0.004292841396913795, 'mean_word_length': 2.1621423330887746, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3298790', 'n_tokens_mistral': 2758, 'n_tokens_neox': 2681, 'n_words': 558}