mirror of https://gitee.com/bigwinds/arangodb
191 lines
7.0 KiB
C++
191 lines
7.0 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014-2018 ArangoDB GmbH, Cologne, Germany
|
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed 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.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "ShardingFeature.h"
|
|
#include "Cluster/ServerState.h"
|
|
#include "Sharding/ShardingInfo.h"
|
|
#include "Sharding/ShardingStrategyDefault.h"
|
|
#include "VocBase/LogicalCollection.h"
|
|
|
|
#ifdef USE_ENTERPRISE
|
|
#include "Enterprise/Sharding/ShardingStrategyEE.h"
|
|
#endif
|
|
|
|
#include <velocypack/velocypack-aliases.h>
|
|
|
|
using namespace arangodb::application_features;
|
|
using namespace arangodb::basics;
|
|
|
|
namespace arangodb {
|
|
|
|
ShardingFeature::ShardingFeature(application_features::ApplicationServer& server)
|
|
: ApplicationFeature(server, "Sharding") {
|
|
setOptional(false);
|
|
startsAfter("GreetingsPhase");
|
|
}
|
|
|
|
void ShardingFeature::prepare() {
|
|
registerFactory(ShardingStrategyNone::NAME, [](ShardingInfo*) {
|
|
return std::make_unique<ShardingStrategyNone>();
|
|
});
|
|
registerFactory(ShardingStrategyCommunityCompat::NAME, [](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyCommunityCompat>(sharding);
|
|
});
|
|
// note: enterprise-compat is always there so users can downgrade from
|
|
// enterprise edition to community edition
|
|
registerFactory(ShardingStrategyEnterpriseCompat::NAME, [](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyEnterpriseCompat>(sharding);
|
|
});
|
|
registerFactory(ShardingStrategyHash::NAME, [](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyHash>(sharding);
|
|
});
|
|
#ifdef USE_ENTERPRISE
|
|
// the following sharding strategies are only available in the enterprise
|
|
// edition
|
|
registerFactory(ShardingStrategyEnterpriseSmartEdgeCompat::NAME, [](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyEnterpriseSmartEdgeCompat>(sharding);
|
|
});
|
|
registerFactory(ShardingStrategyEnterpriseHashSmartEdge::NAME, [](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyEnterpriseHashSmartEdge>(sharding);
|
|
});
|
|
#else
|
|
// in the community-version register some stand-ins for the sharding
|
|
// strategies only available in the enterprise edition
|
|
// note: these standins will actually not do any sharding, but always
|
|
// throw an exception telling the user that the selected sharding
|
|
// strategy is only available in the enterprise edition
|
|
for (auto const& name :
|
|
std::vector<std::string>{"enterprise-smart-edge-compat",
|
|
"enterprise-hash-smart-edge"}) {
|
|
registerFactory(name, [name](ShardingInfo* sharding) {
|
|
return std::make_unique<ShardingStrategyOnlyInEnterprise>(name);
|
|
});
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ShardingFeature::start() {
|
|
std::vector<std::string> strategies;
|
|
for (auto const& it : _factories) {
|
|
strategies.emplace_back(it.first);
|
|
}
|
|
LOG_TOPIC("2702f", TRACE, Logger::CLUSTER) << "supported sharding strategies: " << strategies;
|
|
}
|
|
|
|
void ShardingFeature::registerFactory(std::string const& name,
|
|
ShardingStrategy::FactoryFunction const& creator) {
|
|
LOG_TOPIC("69525", TRACE, Logger::CLUSTER) << "registering sharding strategy '" << name << "'";
|
|
|
|
if (!_factories.emplace(name, creator).second) {
|
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL,
|
|
std::string("sharding factory function '") +
|
|
name + "' already registered");
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<ShardingStrategy> ShardingFeature::fromVelocyPack(VPackSlice slice,
|
|
ShardingInfo* sharding) {
|
|
if (!slice.isObject()) {
|
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
|
|
"invalid collection meta data");
|
|
}
|
|
|
|
std::string name;
|
|
|
|
if (!ServerState::instance()->isRunningInCluster()) {
|
|
// not running in cluster... so no sharding
|
|
name = ShardingStrategyNone::NAME;
|
|
} else {
|
|
// running in cluster... determine the correct method for sharding
|
|
VPackSlice s = slice.get("shardingStrategy");
|
|
if (s.isString()) {
|
|
name = s.copyString();
|
|
} else {
|
|
name = getDefaultShardingStrategy(sharding);
|
|
}
|
|
}
|
|
|
|
return create(name, sharding);
|
|
}
|
|
|
|
std::unique_ptr<ShardingStrategy> ShardingFeature::create(std::string const& name,
|
|
ShardingInfo* sharding) {
|
|
auto it = _factories.find(name);
|
|
|
|
if (it == _factories.end()) {
|
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER,
|
|
std::string("unknown sharding type '") +
|
|
name + "'");
|
|
}
|
|
|
|
// now create a sharding strategy instance
|
|
return (*it).second(sharding);
|
|
}
|
|
|
|
std::string ShardingFeature::getDefaultShardingStrategy(ShardingInfo const* sharding) const {
|
|
TRI_ASSERT(ServerState::instance()->isRunningInCluster());
|
|
// TODO change these to use better algorithms when we no longer
|
|
// need to support collections created before 3.4
|
|
|
|
if (ServerState::instance()->isDBServer()) {
|
|
// on a DB server, we will not use sharding
|
|
return ShardingStrategyNone::NAME;
|
|
}
|
|
|
|
// before 3.4, there were only hard-coded sharding strategies
|
|
|
|
// no sharding strategy found in collection meta data
|
|
#ifdef USE_ENTERPRISE
|
|
if (sharding->collection()->isSmart() && sharding->collection()->type() == TRI_COL_TYPE_EDGE) {
|
|
// smart edge collection
|
|
return ShardingStrategyEnterpriseSmartEdgeCompat::NAME;
|
|
}
|
|
|
|
return ShardingStrategyEnterpriseCompat::NAME;
|
|
#else
|
|
return ShardingStrategyCommunityCompat::NAME;
|
|
#endif
|
|
}
|
|
|
|
std::string ShardingFeature::getDefaultShardingStrategyForNewCollection(VPackSlice const& properties) const {
|
|
TRI_ASSERT(ServerState::instance()->isRunningInCluster());
|
|
|
|
// from 3.4 onwards, the default sharding strategy for new collections is
|
|
// "hash"
|
|
#ifdef USE_ENTERPRISE
|
|
bool isSmart =
|
|
VelocyPackHelper::getBooleanValue(properties, StaticStrings::IsSmart, false);
|
|
bool isEdge = TRI_COL_TYPE_EDGE ==
|
|
VelocyPackHelper::getNumericValue<uint32_t>(properties, "type",
|
|
TRI_COL_TYPE_UNKNOWN);
|
|
if (isSmart && isEdge) {
|
|
// smart edge collection
|
|
return ShardingStrategyEnterpriseHashSmartEdge::NAME;
|
|
}
|
|
#endif
|
|
|
|
return ShardingStrategyHash::NAME;
|
|
}
|
|
|
|
} // namespace arangodb
|