blob: 739a723ce6d031202d9da6709451641a9f622584 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#ifndef QUICKSTEP_CATALOG_PARTITION_SCHEME_HPP_
#define QUICKSTEP_CATALOG_PARTITION_SCHEME_HPP_
#include <cstddef>
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include "catalog/Catalog.pb.h"
#include "catalog/CatalogTypedefs.hpp"
#include "catalog/PartitionSchemeHeader.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "threading/Mutex.hpp"
#include "threading/SharedMutex.hpp"
#include "threading/SpinSharedMutex.hpp"
#include "utility/Macros.hpp"
#include "glog/logging.h"
namespace quickstep {
class CatalogRelationSchema;
/** \addtogroup Catalog
* @{
*/
/**
* @brief The class which stores the partitioning information and partitioned
* blocks for a particular relation.
**/
class PartitionScheme {
public:
/**
* @brief Constructor.
* @note The constructor takes ownership of \c header.
*
* @param header The partition header.
* @param blocks_in_partition All blocks in partitions.
**/
explicit PartitionScheme(PartitionSchemeHeader *header)
: header_(DCHECK_NOTNULL(header)),
blocks_in_partition_(header_->getNumPartitions()),
blocks_in_partition_mutexes_(header_->getNumPartitions()) {}
/**
* @brief Constructor.
* @note The constructor takes ownership of \c header.
*
* @param header The partition header.
* @param blocks_in_partition All blocks in partitions.
**/
PartitionScheme(PartitionSchemeHeader *header,
std::vector<std::unordered_set<block_id>> &&blocks_in_partition)
: header_(DCHECK_NOTNULL(header)),
blocks_in_partition_(std::move(blocks_in_partition)),
blocks_in_partition_mutexes_(header_->getNumPartitions()) {}
/**
* @brief Reconstruct a Partition Scheme from its serialized
* Protocol Buffer form.
*
* @param proto The Protocol Buffer serialization of a Partition Scheme,
* previously produced by getProto().
* @return The deserialized partition scheme object.
**/
static PartitionScheme* ReconstructFromProto(const serialization::PartitionScheme &proto);
/**
* @brief Check whether a serialization::PartitionScheme is fully-formed and
* all parts are valid.
*
* @param proto A serialized Protocol Buffer representation of a
* PartitionScheme, originally generated by getProto().
* @return Whether proto is fully-formed and valid.
**/
static bool ProtoIsValid(const serialization::PartitionScheme &proto);
/**
* @brief Get the partitioning attribute for the relation.
*
* @return The partitioning attribute with which the relation
* is partitioned into.
**/
const PartitionSchemeHeader& getPartitionSchemeHeader() const {
return *header_;
}
/**
* @brief Add a block to a partition.
*
* @param block_id The id of the block to be added to the partition.
* @param part_id The id of the partition to add the block to.
**/
inline void addBlockToPartition(const block_id block,
const partition_id part_id) {
DCHECK_LT(part_id, header_->getNumPartitions());
SpinSharedMutexExclusiveLock<false> lock(
blocks_in_partition_mutexes_[part_id]);
blocks_in_partition_[part_id].insert(block);
}
/**
* @brief Remove a block from a partition.
*
* @param block_id The id of the block to be removed from the partition.
* @param part_id The id of the partition to remove the block from.
**/
inline void removeBlockFromPartition(const block_id block,
const partition_id part_id) {
DCHECK_LT(part_id, header_->getNumPartitions());
SpinSharedMutexExclusiveLock<false> lock(
blocks_in_partition_mutexes_[part_id]);
std::unordered_set<block_id> &blocks_in_partition =
blocks_in_partition_[part_id];
blocks_in_partition.erase(block);
}
/**
* @brief Get all the blocks from a particular partition.
*
* @param part_id The id of the partition to retrieve the blocks from.
* @return The block_ids of blocks belonging to this partition at the moment
* when this method is called.
**/
inline std::vector<block_id> getBlocksInPartition(
const partition_id part_id) const {
DCHECK_LT(part_id, header_->getNumPartitions());
SpinSharedMutexSharedLock<false> lock(
blocks_in_partition_mutexes_[part_id]);
return std::vector<block_id>(blocks_in_partition_[part_id].begin(),
blocks_in_partition_[part_id].end());
}
/**
* @brief Serialize the Partition Scheme as Protocol Buffer.
*
* @return The Protocol Buffer representation of Partition Scheme.
**/
serialization::PartitionScheme getProto() const;
/**
* @brief Get the partition id for a block.
*
* @param block The id of the block.
*
* @return The partition id to which the block belongs. If the block is not
* found in any partition, then the maximum finite value for the type
* std::size_t is returned.
**/
partition_id getPartitionForBlock(const block_id block) const;
/**
* @brief Display the partition scheme as a string.
*
* @param relation_schema The relation schema that owns this scheme.
*
* @return the string of the partition scheme.
**/
std::string toString(const CatalogRelationSchema &relation_schema) const;
private:
std::unique_ptr<const PartitionSchemeHeader> header_;
// The unordered set of blocks per partition.
std::vector<std::unordered_set<block_id>> blocks_in_partition_;
// Mutexes for locking each partition separately.
mutable std::vector<SpinSharedMutex<false>> blocks_in_partition_mutexes_;
DISALLOW_COPY_AND_ASSIGN(PartitionScheme);
};
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_CATALOG_PARTITION_SCHEME_HPP_