Make MergeOperator+CompactionFilter/Factory into Customizable Classes (#8481)
Summary: - Changed MergeOperator, CompactionFilter, and CompactionFilterFactory into Customizable classes. - Added Options/Configurable/Object Registration for TTL and Cassandra variants - Changed the StringAppend MergeOperators to accept a string delimiter rather than a simple char. Made the delimiter into a configurable option - Added tests for new functionality Pull Request resolved: https://github.com/facebook/rocksdb/pull/8481 Reviewed By: zhichao-cao Differential Revision: D30136050 Pulled By: mrambacher fbshipit-source-id: 271d1772835935b6773abaf018ee71e42f9491afmain
parent
fd2079938d
commit
d057e8326d
@ -0,0 +1,40 @@ |
|||||||
|
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
|
||||||
|
// This source code is licensed under both the GPLv2 (found in the
|
||||||
|
// COPYING file in the root directory) and Apache 2.0 License
|
||||||
|
// (found in the LICENSE.Apache file in the root directory).
|
||||||
|
|
||||||
|
#pragma once |
||||||
|
#include <cinttypes> |
||||||
|
|
||||||
|
#include "rocksdb/rocksdb_namespace.h" |
||||||
|
|
||||||
|
namespace ROCKSDB_NAMESPACE { |
||||||
|
class ObjectLibrary; |
||||||
|
namespace cassandra { |
||||||
|
struct CassandraOptions { |
||||||
|
static const char* kName() { return "CassandraOptions"; } |
||||||
|
CassandraOptions(int32_t _gc_grace_period_in_seconds, size_t _operands_limit, |
||||||
|
bool _purge_ttl_on_expiration = false) |
||||||
|
: operands_limit(_operands_limit), |
||||||
|
gc_grace_period_in_seconds(_gc_grace_period_in_seconds), |
||||||
|
purge_ttl_on_expiration(_purge_ttl_on_expiration) {} |
||||||
|
// Limit on the number of merge operands.
|
||||||
|
size_t operands_limit; |
||||||
|
|
||||||
|
// How long (in seconds) tombstoned data remains before it is purged
|
||||||
|
int32_t gc_grace_period_in_seconds; |
||||||
|
|
||||||
|
// If is set to true, expired data will be directly purged.
|
||||||
|
// Otherwise expired data will be converted tombstones first,
|
||||||
|
// then be eventually removed after gc grace period. This value should
|
||||||
|
// only true if all writes have same ttl setting, otherwise it could bring old
|
||||||
|
// data back.
|
||||||
|
bool purge_ttl_on_expiration; |
||||||
|
}; |
||||||
|
#ifndef ROCKSDB_LITE |
||||||
|
extern "C" { |
||||||
|
int RegisterCassandraObjects(ObjectLibrary& library, const std::string& arg); |
||||||
|
} // extern "C"
|
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
} // namespace cassandra
|
||||||
|
} // namespace ROCKSDB_NAMESPACE
|
@ -0,0 +1,56 @@ |
|||||||
|
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||||
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||||
|
|
||||||
|
#include <memory> |
||||||
|
|
||||||
|
#include "rocksdb/compaction_filter.h" |
||||||
|
#include "rocksdb/options.h" |
||||||
|
#include "rocksdb/utilities/customizable_util.h" |
||||||
|
#include "rocksdb/utilities/options_type.h" |
||||||
|
#include "utilities/compaction_filters/layered_compaction_filter_base.h" |
||||||
|
#include "utilities/compaction_filters/remove_emptyvalue_compactionfilter.h" |
||||||
|
|
||||||
|
namespace ROCKSDB_NAMESPACE { |
||||||
|
#ifndef ROCKSDB_LITE |
||||||
|
static int RegisterBuiltinCompactionFilters(ObjectLibrary& library, |
||||||
|
const std::string& /*arg*/) { |
||||||
|
library.Register<CompactionFilter>( |
||||||
|
RemoveEmptyValueCompactionFilter::kClassName(), |
||||||
|
[](const std::string& /*uri*/, |
||||||
|
std::unique_ptr<CompactionFilter>* /*guard*/, |
||||||
|
std::string* /*errmsg*/) { |
||||||
|
return new RemoveEmptyValueCompactionFilter(); |
||||||
|
}); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
Status CompactionFilter::CreateFromString(const ConfigOptions& config_options, |
||||||
|
const std::string& value, |
||||||
|
const CompactionFilter** result) { |
||||||
|
#ifndef ROCKSDB_LITE |
||||||
|
static std::once_flag once; |
||||||
|
std::call_once(once, [&]() { |
||||||
|
RegisterBuiltinCompactionFilters(*(ObjectLibrary::Default().get()), ""); |
||||||
|
}); |
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
CompactionFilter* filter = const_cast<CompactionFilter*>(*result); |
||||||
|
Status status = LoadStaticObject<CompactionFilter>(config_options, value, |
||||||
|
nullptr, &filter); |
||||||
|
if (status.ok()) { |
||||||
|
*result = const_cast<CompactionFilter*>(filter); |
||||||
|
} |
||||||
|
return status; |
||||||
|
} |
||||||
|
|
||||||
|
Status CompactionFilterFactory::CreateFromString( |
||||||
|
const ConfigOptions& config_options, const std::string& value, |
||||||
|
std::shared_ptr<CompactionFilterFactory>* result) { |
||||||
|
// Currently there are no builtin CompactionFilterFactories.
|
||||||
|
// If any are introduced, they need to be registered here.
|
||||||
|
Status status = LoadSharedObject<CompactionFilterFactory>( |
||||||
|
config_options, value, nullptr, result); |
||||||
|
return status; |
||||||
|
} |
||||||
|
} // namespace ROCKSDB_NAMESPACE
|
@ -0,0 +1,125 @@ |
|||||||
|
// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||||
|
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file. See the AUTHORS file for names of contributors.
|
||||||
|
|
||||||
|
#include "utilities/merge_operators.h" |
||||||
|
|
||||||
|
#include <memory> |
||||||
|
|
||||||
|
#include "rocksdb/merge_operator.h" |
||||||
|
#include "rocksdb/options.h" |
||||||
|
#include "rocksdb/utilities/customizable_util.h" |
||||||
|
#include "rocksdb/utilities/object_registry.h" |
||||||
|
#include "utilities/merge_operators/bytesxor.h" |
||||||
|
#include "utilities/merge_operators/sortlist.h" |
||||||
|
#include "utilities/merge_operators/string_append/stringappend.h" |
||||||
|
#include "utilities/merge_operators/string_append/stringappend2.h" |
||||||
|
|
||||||
|
namespace ROCKSDB_NAMESPACE { |
||||||
|
static bool LoadMergeOperator(const std::string& id, |
||||||
|
std::shared_ptr<MergeOperator>* result) { |
||||||
|
bool success = true; |
||||||
|
// TODO: Hook the "name" up to the actual Name() of the MergeOperators?
|
||||||
|
// Requires these classes be moved into a header file...
|
||||||
|
if (id == "put" || id == "PutOperator") { |
||||||
|
*result = MergeOperators::CreatePutOperator(); |
||||||
|
} else if (id == "put_v1") { |
||||||
|
*result = MergeOperators::CreateDeprecatedPutOperator(); |
||||||
|
} else if (id == "uint64add" || id == "UInt64AddOperator") { |
||||||
|
*result = MergeOperators::CreateUInt64AddOperator(); |
||||||
|
} else if (id == "max" || id == "MaxOperator") { |
||||||
|
*result = MergeOperators::CreateMaxOperator(); |
||||||
|
#ifdef ROCKSDB_LITE |
||||||
|
// The remainder of the classes are handled by the ObjectRegistry in
|
||||||
|
// non-LITE mode
|
||||||
|
} else if (id == StringAppendOperator::kNickName() || |
||||||
|
id == StringAppendOperator::kClassName()) { |
||||||
|
*result = MergeOperators::CreateStringAppendOperator(); |
||||||
|
} else if (id == StringAppendTESTOperator::kNickName() || |
||||||
|
id == StringAppendTESTOperator::kClassName()) { |
||||||
|
*result = MergeOperators::CreateStringAppendTESTOperator(); |
||||||
|
} else if (id == BytesXOROperator::kNickName() || |
||||||
|
id == BytesXOROperator::kClassName()) { |
||||||
|
*result = MergeOperators::CreateBytesXOROperator(); |
||||||
|
} else if (id == SortList::kNickName() || id == SortList::kClassName()) { |
||||||
|
*result = MergeOperators::CreateSortOperator(); |
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
} else { |
||||||
|
success = false; |
||||||
|
} |
||||||
|
return success; |
||||||
|
} |
||||||
|
|
||||||
|
#ifndef ROCKSDB_LITE |
||||||
|
static int RegisterBuiltinMergeOperators(ObjectLibrary& library, |
||||||
|
const std::string& /*arg*/) { |
||||||
|
size_t num_types; |
||||||
|
auto AsRegex = [](const std::string& name, const std::string& alt) { |
||||||
|
std::string regex; |
||||||
|
regex.append("(").append(name); |
||||||
|
regex.append("|").append(alt).append(")"); |
||||||
|
return regex; |
||||||
|
}; |
||||||
|
|
||||||
|
library.Register<MergeOperator>( |
||||||
|
AsRegex(StringAppendOperator::kClassName(), |
||||||
|
StringAppendOperator::kNickName()), |
||||||
|
[](const std::string& /*uri*/, std::unique_ptr<MergeOperator>* guard, |
||||||
|
std::string* /*errmsg*/) { |
||||||
|
guard->reset(new StringAppendOperator(",")); |
||||||
|
return guard->get(); |
||||||
|
}); |
||||||
|
library.Register<MergeOperator>( |
||||||
|
AsRegex(StringAppendTESTOperator::kClassName(), |
||||||
|
StringAppendTESTOperator::kNickName()), |
||||||
|
[](const std::string& /*uri*/, std::unique_ptr<MergeOperator>* guard, |
||||||
|
std::string* /*errmsg*/) { |
||||||
|
guard->reset(new StringAppendTESTOperator(",")); |
||||||
|
return guard->get(); |
||||||
|
}); |
||||||
|
library.Register<MergeOperator>( |
||||||
|
AsRegex(SortList::kClassName(), SortList::kNickName()), |
||||||
|
[](const std::string& /*uri*/, std::unique_ptr<MergeOperator>* guard, |
||||||
|
std::string* /*errmsg*/) { |
||||||
|
guard->reset(new SortList()); |
||||||
|
return guard->get(); |
||||||
|
}); |
||||||
|
library.Register<MergeOperator>( |
||||||
|
AsRegex(BytesXOROperator::kClassName(), BytesXOROperator::kNickName()), |
||||||
|
[](const std::string& /*uri*/, std::unique_ptr<MergeOperator>* guard, |
||||||
|
std::string* /*errmsg*/) { |
||||||
|
guard->reset(new BytesXOROperator()); |
||||||
|
return guard->get(); |
||||||
|
}); |
||||||
|
|
||||||
|
return static_cast<int>(library.GetFactoryCount(&num_types)); |
||||||
|
} |
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
|
||||||
|
Status MergeOperator::CreateFromString(const ConfigOptions& config_options, |
||||||
|
const std::string& value, |
||||||
|
std::shared_ptr<MergeOperator>* result) { |
||||||
|
#ifndef ROCKSDB_LITE |
||||||
|
static std::once_flag once; |
||||||
|
std::call_once(once, [&]() { |
||||||
|
RegisterBuiltinMergeOperators(*(ObjectLibrary::Default().get()), ""); |
||||||
|
}); |
||||||
|
#endif // ROCKSDB_LITE
|
||||||
|
return LoadSharedObject<MergeOperator>(config_options, value, |
||||||
|
LoadMergeOperator, result); |
||||||
|
} |
||||||
|
|
||||||
|
std::shared_ptr<MergeOperator> MergeOperators::CreateFromStringId( |
||||||
|
const std::string& id) { |
||||||
|
std::shared_ptr<MergeOperator> result; |
||||||
|
Status s = MergeOperator::CreateFromString(ConfigOptions(), id, &result); |
||||||
|
if (s.ok()) { |
||||||
|
return result; |
||||||
|
} else { |
||||||
|
// Empty or unknown, just return nullptr
|
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} // namespace ROCKSDB_NAMESPACE
|
Loading…
Reference in new issue