blob: 71e062920f4403e6d9af89e3cdde36ade28a45fd [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_STORAGE_SUB_BLOCK_TYPE_REGISTRY_HPP_
#define QUICKSTEP_STORAGE_SUB_BLOCK_TYPE_REGISTRY_HPP_
#include <cstddef>
#include <type_traits>
#include <unordered_map>
#include "storage/StorageBlockLayout.pb.h"
#include "utility/Macros.hpp"
namespace quickstep {
class CatalogRelationSchema;
/** \addtogroup Expressions
* @{
*/
/**
* @brief Singleton registry object that allows different implementations of
* TupleStorageSubBlock and IndexSubBlock to register their
* layout-verification and size-estimation functions for use by
* StorageBlockLayout.
*
* Some macros are provided to make using the SubBlockTypeRegistry easier. To
* register an implementation of TupleStorageSubBlock, do the following:
* 1. Include "storage/SubBlockTypeRegistry.hpp" in the implementation
* (.cpp) file, and put an invocation of the
* QUICKSTEP_REGISTER_TUPLE_STORE() macro in the quickstep namespace.
* For example:
* QUICKSTEP_REGISTER_TUPLE_STORE(SplitRowStoreTupleStorageSubBlock, SPLIT_ROW_STORE);
* The first argument to the macro is the name of the class, the second
* is the name of the class' corresponding case in the
* TupleStorageSubBlockDescription::TupleStorageSubBlockType enum.
* 2. Include "storage/SubBlockTypeRegistryMacros.hpp" in the header (.hpp)
* file, and put an invocation of the
* QUICKSTEP_DECLARE_SUB_BLOCK_TYPE_REGISTERED() macro in the quickstep
* namespace like so:
* QUICKSTEP_DECLARE_SUB_BLOCK_TYPE_REGISTERED(SplitRowStoreTupleStorageSubBlock);
*
* Registration of IndexSubBlock implementations works the same way, except the
* first macro used should be QUICKSTEP_REGISTER_INDEX() instead of
* QUICKSTEP_REGISTER_TUPLE_STORE().
*
* SubBlockTypeRegistryMacros.hpp additionally provides a macro
* QUICKSTEP_FORCE_SUB_BLOCK_REGISTRATION(block_type) that can be used by
* executable targets to force linking and registration of particular SubBlock
* types in executables that never actually instantiate the block types in
* question. This is mainly useful for tests that need to verify the
* correctness of a StorageBlockLayout, but never actually create any
* StorageBlocks. See Catalog_unittest for an example.
**/
class SubBlockTypeRegistry {
private:
typedef typename std::underlying_type<TupleStorageSubBlockDescription::TupleStorageSubBlockType>::type
TupleStoreTypeIntegral;
typedef typename std::underlying_type<IndexSubBlockDescription::IndexSubBlockType>::type
IndexTypeIntegral;
public:
typedef bool (*TupleStoreDescriptionIsValidFunction)(
const CatalogRelationSchema&,
const TupleStorageSubBlockDescription&);
typedef std::size_t (*TupleStoreEstimateBytesPerTupleFunction)(
const CatalogRelationSchema&,
const TupleStorageSubBlockDescription&);
typedef bool (*IndexDescriptionIsValidFunction)(
const CatalogRelationSchema&,
const IndexSubBlockDescription&);
typedef std::size_t (*IndexEstimateBytesPerTupleFunction)(
const CatalogRelationSchema&,
const IndexSubBlockDescription&);
typedef std::size_t (*IndexEstimateBytesPerBlockFunction)(
const CatalogRelationSchema&,
const IndexSubBlockDescription&);
static bool RegisterTupleStoreDescriptionIsValidFunction(
const TupleStorageSubBlockDescription::TupleStorageSubBlockType sub_block_type,
TupleStoreDescriptionIsValidFunction function) {
Instance()->tuple_store_description_is_valid_functions_[
static_cast<TupleStoreTypeIntegral>(sub_block_type)] = function;
return true;
}
static bool RegisterTupleStoreEstimateBytesPerTupleFunction(
const TupleStorageSubBlockDescription::TupleStorageSubBlockType sub_block_type,
TupleStoreEstimateBytesPerTupleFunction function) {
Instance()->tuple_store_estimate_bytes_per_tuple_functions_[
static_cast<TupleStoreTypeIntegral>(sub_block_type)] = function;
return true;
}
static bool RegisterIndexDescriptionIsValidFunction(
const IndexSubBlockDescription::IndexSubBlockType sub_block_type,
IndexDescriptionIsValidFunction function) {
Instance()->index_description_is_valid_functions_[
static_cast<IndexTypeIntegral>(sub_block_type)] = function;
return true;
}
static bool RegisterIndexEstimateBytesPerTupleFunction(
const IndexSubBlockDescription::IndexSubBlockType sub_block_type,
IndexEstimateBytesPerTupleFunction function) {
Instance()->index_estimate_bytes_per_tuple_functions_[
static_cast<IndexTypeIntegral>(sub_block_type)] = function;
return true;
}
static bool RegisterIndexEstimateBytesPerBlockFunction(
const IndexSubBlockDescription::IndexSubBlockType sub_block_type,
IndexEstimateBytesPerBlockFunction function) {
Instance()->index_estimate_bytes_per_block_functions_[
static_cast<IndexTypeIntegral>(sub_block_type)] = function;
return true;
}
static bool LayoutDescriptionIsValid(
const CatalogRelationSchema &relation,
const StorageBlockLayoutDescription &description);
static bool IndexDescriptionIsValid(
const CatalogRelationSchema &relation,
const IndexSubBlockDescription &description);
static std::size_t EstimateBytesPerTupleForTupleStore(
const CatalogRelationSchema &relation,
const TupleStorageSubBlockDescription &description);
static std::size_t EstimateBytesPerTupleForIndex(
const CatalogRelationSchema &relation,
const IndexSubBlockDescription &description);
static std::size_t EstimateBytesPerBlockForIndex(
const CatalogRelationSchema &relation,
const IndexSubBlockDescription &description);
private:
std::unordered_map<TupleStoreTypeIntegral,
TupleStoreDescriptionIsValidFunction>
tuple_store_description_is_valid_functions_;
std::unordered_map<TupleStoreTypeIntegral,
TupleStoreEstimateBytesPerTupleFunction>
tuple_store_estimate_bytes_per_tuple_functions_;
std::unordered_map<IndexTypeIntegral,
IndexDescriptionIsValidFunction>
index_description_is_valid_functions_;
std::unordered_map<IndexTypeIntegral,
IndexEstimateBytesPerTupleFunction>
index_estimate_bytes_per_tuple_functions_;
std::unordered_map<IndexTypeIntegral,
IndexEstimateBytesPerTupleFunction>
index_estimate_bytes_per_block_functions_;
SubBlockTypeRegistry() {
}
static SubBlockTypeRegistry* Instance() {
static SubBlockTypeRegistry instance;
return &instance;
}
DISALLOW_COPY_AND_ASSIGN(SubBlockTypeRegistry);
};
/** @} */
} // namespace quickstep
#define QUICKSTEP_REGISTER_TUPLE_STORE(classname, proto_enum_case) \
namespace registry { \
static const bool classname##_desc_registered \
= quickstep::SubBlockTypeRegistry::RegisterTupleStoreDescriptionIsValidFunction( \
TupleStorageSubBlockDescription::proto_enum_case, \
&classname::DescriptionIsValid); \
static const bool classname##_size_registered \
= quickstep::SubBlockTypeRegistry::RegisterTupleStoreEstimateBytesPerTupleFunction( \
TupleStorageSubBlockDescription::proto_enum_case, \
&classname::EstimateBytesPerTuple); \
const bool classname##_registered \
= classname##_desc_registered && classname##_size_registered; \
bool classname##_check_registered() { return classname##_registered; } \
} /* namespace registry */ \
using registry::classname##_registered
#define QUICKSTEP_REGISTER_INDEX(classname, proto_enum_case) \
namespace registry { \
static const bool classname##_desc_registered \
= quickstep::SubBlockTypeRegistry::RegisterIndexDescriptionIsValidFunction( \
IndexSubBlockDescription::proto_enum_case, \
&classname::DescriptionIsValid); \
static const bool classname##_size_per_tuple_registered \
= quickstep::SubBlockTypeRegistry::RegisterIndexEstimateBytesPerTupleFunction( \
IndexSubBlockDescription::proto_enum_case, \
&classname::EstimateBytesPerTuple); \
static const bool classname##_size_per_block_registered \
= quickstep::SubBlockTypeRegistry::RegisterIndexEstimateBytesPerBlockFunction( \
IndexSubBlockDescription::proto_enum_case, \
&classname::EstimateBytesPerBlock); \
const bool classname##_registered \
= classname##_desc_registered && classname##_size_per_tuple_registered \
&& classname##_size_per_block_registered; \
bool classname##_check_registered() { return classname##_registered; } \
} /* namespace registry */ \
using registry::classname##_registered
#endif // QUICKSTEP_STORAGE_SUB_BLOCK_TYPE_REGISTRY_HPP_