Exemple #1
0
pos_list_t Store::buildValidPositions(tx::transaction_cid_t last_commit_id, tx::transaction_id_t tid) const {
  pos_list_t result;
  functional::forEachWithIndex(_cidBeginVector, [&](size_t i, tx::transaction_cid_t v){
    if(isVisibleForTransaction(i, last_commit_id, tid)) result.push_back(i);
  });
  return std::move(result);
}
Exemple #2
0
void Store::merge() {
  if (merger == nullptr) {
    throw std::runtime_error("No Merger set.");
  }

  // Create new delta and merge
  atable_ptr_t new_delta = delta->copy_structure(create_concurrent_dict, create_concurrent_storage);

  // Prepare the merge
  std::vector<c_atable_ptr_t> tmp {_main_table, delta};

  // get valid positions
  std::vector<bool> validPositions(_cidBeginVector.size());
  tx::transaction_cid_t last_commit_id = tx::TransactionManager::getInstance().getLastCommitId();
  functional::forEachWithIndex(_cidBeginVector, [&](size_t i, bool v){
    validPositions[i] = isVisibleForTransaction(i, last_commit_id, tx::MERGE_TID);
  });

  auto tables = merger->merge(tmp, true, validPositions);
  assert(tables.size() == 1);
  _main_table = tables.front();
  // Fixup the cid and tid vectors
  _cidBeginVector = tbb::concurrent_vector<tx::transaction_cid_t>(_main_table->size(), tx::UNKNOWN_CID);
  _cidEndVector = tbb::concurrent_vector<tx::transaction_cid_t>(_main_table->size(), tx::INF_CID);
  _tidVector = tbb::concurrent_vector<tx::transaction_id_t>(_main_table->size(), tx::START_TID);
  
  // Replace the delta partition
  delta = new_delta;
  _delta_size = new_delta->size();
}
Exemple #3
0
// This method iterates of the pos list and validates each position
void Store::validatePositions(pos_list_t& pos, tx::transaction_cid_t last_commit_id, tx::transaction_id_t tid) const {
  // Make sure we captured all rows
  assert(_cidBeginVector.size() == size() && _cidEndVector.size() == size() && _tidVector.size() == size());

  // Pos is nullptr, we should circumvent
  auto end = std::remove_if(std::begin(pos), std::end(pos), [&](const pos_t& v){

    return !isVisibleForTransaction(v, last_commit_id, tid);

  } );
  if (end != pos.end())
    pos.erase(end, pos.end());
}
Exemple #4
0
void CompoundIndexScan::executePlanOperation() {
  if (!_main_index_name.empty())
    setMainIndex(_main_index_name);
  if (!_delta_index_name.empty())
    setDeltaIndex(_delta_index_name);


  pos_list_t* result = new pos_list_t;

  if (!_validate) {
    if (!_json_predicates.empty())
      parseJsonPredicates();
    if (_main_index) {
      if (_predicates_added_main != _main_index->getColumns().size()) {
        throw std::runtime_error(
            "Incomplete predicate set specified - Partial Search only Implemeted for Validating-IndexScan");
      }
      storage::PositionRange main_result = _main_index->getPositionsForKey(_valueid_key_builder.get());
      result->resize(main_result.size());
      std::copy(main_result.cbegin(), main_result.cend(), result->begin());
    }

    if (_delta_index) {
      storage::PositionRange delta_result = _delta_index->getPositionsForKey(_value_key_builder.get());
      size_t real_result_size = result->size();  // we need to resize the result list below
      result->resize(result->size() + delta_result.size());
      std::copy(delta_result.cbegin(), delta_result.cend(), result->begin() + real_result_size);
    }
  } else {
    // The index performs a validation of results directly, minimizing the overhead for copying large, invalid positions
    // around.

    // Note: A large part of the index-lookup of the main is already performed during the predicate evaluation, when all
    // predicate-values are checked against the Main dictioanries.
    // therefore we seperatly create the predicates for the delta first, to save that work in the unqiue index-case


    // Refactoring Discussion:
    // The best solution might be a Planop "IndexLookup" for Complete-Key Lookups
    // and a seperate Planop IndexScan for partial keys.
    //

    auto c_store = checked_pointer_cast<const storage::Store>(input.getTables()[0]);
    pos_list_t validated_delta_result;
    bool skipmain = false;

    if (!_unique_index and !_json_predicates.empty())
      parseJsonPredicates(/*set_for_main=*/true, /*set_for_delta=*/true);

    if (_delta_index) {
      if (_unique_index and !_json_predicates.empty())
        parseJsonPredicates(/*set_for_main=*/false, /*set_for_delta=*/true);

      if (_main_index and _predicates_added_delta != _main_index->getColumns().size()) {
        // partial search
        auto s_key = _value_key_builder.get();
        auto up_key = _value_key_builder.get_upperbound();

        auto iterator_pair = _delta_index->getIteratorsForKeyBetween(s_key, up_key);

        if (!_unique_index) {
          for (auto dp = iterator_pair.first; dp != iterator_pair.second; ++dp) {
            if (c_store->isVisibleForTransaction(dp->second, _txContext.lastCid, _txContext.tid)) {
              validated_delta_result.push_back(dp->second);
            }
          }
        } else {
          // Evaluate a unique index
          auto dp = iterator_pair.second;
          // Validate entries from delta  index backwards, as newer items are to be found at the end.;
          while (dp != iterator_pair.first) {  // skips if start==end
            dp--;
            if (c_store->isVisibleForTransaction(dp->second, _txContext.lastCid, _txContext.tid)) {
              validated_delta_result.push_back(dp->second);
              skipmain = true;
              break;  // Unique Index, one hit sufficient
            }
          }
        }
      } else {
        // all attr in index specified
        auto iterator_pair = _delta_index->getIteratorsForKey(_value_key_builder.get());

        if (!_unique_index) {
          for (auto dp = iterator_pair.first; dp != iterator_pair.second; ++dp) {
            if (c_store->isVisibleForTransaction(dp->second, _txContext.lastCid, _txContext.tid)) {
              validated_delta_result.push_back(dp->second);
            }
          }
        } else {
          // Evaluate a unique index
          auto dp = iterator_pair.second;
          // Validate entries from delta  index backwards, as newer items are to be found at the end.;
          while (dp != iterator_pair.first) {  // skips if start==end
            dp--;
            if (c_store->isVisibleForTransaction(dp->second, _txContext.lastCid, _txContext.tid)) {
              validated_delta_result.push_back(dp->second);
              skipmain = true;
              break;  // Unique Index, one hit sufficient
            }
          }
        }
      }
    }

    if (!skipmain and _main_index) {
      if (_unique_index and !_json_predicates.empty())
        parseJsonPredicates(/*set_for_main=*/true, /*set_for_delta=*/false);

      if (_predicates_added_main != _main_index->getColumns().size()) {
        // incomplete key, perform partial search
        compound_valueid_key_t search_key = _valueid_key_builder.get();
        compound_valueid_key_t valid_bits = _valueid_key_builder.getValidBitMaskForCurrentKey();
        compound_valueid_key_t upper_bound = search_key | (~valid_bits);
        // std::cout << "SK: " << search_key << " UP:" << upper_bound << " Valid Bits: " << valid_bits << std::endl;

        storage::PositionRange main_result = _main_index->getPositionsForKeyBetween(search_key, upper_bound);
        result->resize(main_result.size());
        std::copy(main_result.cbegin(), main_result.cend(), result->begin());

        // note: can this break if the largest value id is a power of two?

      } else {
        storage::PositionRange main_result = _main_index->getPositionsForKey(_valueid_key_builder.get());
        result->resize(main_result.size());
        std::copy(main_result.cbegin(), main_result.cend(), result->begin());
      }
      c_store->validatePositions(*result, _txContext.lastCid, _txContext.tid);
    }

    if (skipmain) {
      result->swap(validated_delta_result);

    } else {
      size_t real_result_size = result->size();  // we need to resize the result list below
      result->resize(result->size() + validated_delta_result.size());
      std::copy(validated_delta_result.cbegin(), validated_delta_result.cend(), result->begin() + real_result_size);
    }
  }
  addResult(storage::PointerCalculator::create(input.getTables()[0], result));
}