void ClusterFeature::prepare() { ServerState::instance()->setDataPath(_dataPath); ServerState::instance()->setLogPath(_logPath); ServerState::instance()->setArangodPath(_arangodPath); ServerState::instance()->setDBserverConfig(_dbserverConfig); ServerState::instance()->setCoordinatorConfig(_coordinatorConfig); V8DealerFeature* v8Dealer = ApplicationServer::getFeature<V8DealerFeature>("V8Dealer"); v8Dealer->defineDouble("SYS_DEFAULT_REPLICATION_FACTOR_SYSTEM", _systemReplicationFactor); // create callback registery _agencyCallbackRegistry.reset( new AgencyCallbackRegistry(agencyCallbacksPath())); // Initialize ClusterInfo library: ClusterInfo::createInstance(_agencyCallbackRegistry.get()); // initialize ConnectionManager library httpclient::ConnectionManager::initialize(); // create an instance (this will not yet create a thread) ClusterComm::instance(); AgencyFeature* agency = application_features::ApplicationServer::getFeature<AgencyFeature>( "Agency"); if (agency->isEnabled() || _enableCluster) { // initialize ClusterComm library, must call initialize only once ClusterComm::initialize(); auto authenticationFeature = application_features::ApplicationServer::getFeature<AuthenticationFeature>( "Authentication"); if (authenticationFeature->isEnabled() && !authenticationFeature->hasUserdefinedJwt()) { LOG(FATAL) << "Cluster authentication enabled but jwt not set via command line. Please" << " provide --server.jwt-secret which is used throughout the cluster."; FATAL_ERROR_EXIT(); } } // return if cluster is disabled if (!_enableCluster) { return; } ServerState::instance()->setClusterEnabled(); // register the prefix with the communicator AgencyComm::setPrefix(_agencyPrefix); for (size_t i = 0; i < _agencyEndpoints.size(); ++i) { std::string const unified = Endpoint::unifiedForm(_agencyEndpoints[i]); if (unified.empty()) { LOG(FATAL) << "invalid endpoint '" << _agencyEndpoints[i] << "' specified for --cluster.agency-endpoint"; FATAL_ERROR_EXIT(); } AgencyComm::addEndpoint(unified); } // Now either _myId is set properly or _myId is empty and _myLocalInfo and // _myAddress are set. if (!_myAddress.empty()) { ServerState::instance()->setAddress(_myAddress); } // disable error logging for a while ClusterComm::instance()->enableConnectionErrorLogging(false); // perform an initial connect to the agency std::string const endpoints = AgencyComm::getEndpointsString(); if (!AgencyComm::initialize()) { LOG(FATAL) << "Could not connect to agency endpoints (" << endpoints << ")"; FATAL_ERROR_EXIT(); } ServerState::instance()->setLocalInfo(_myLocalInfo); if (!_myId.empty()) { ServerState::instance()->setId(_myId); } if (!_myRole.empty()) { ServerState::RoleEnum role = ServerState::stringToRole(_myRole); if (role == ServerState::ROLE_SINGLE || role == ServerState::ROLE_UNDEFINED) { LOG(FATAL) << "Invalid role provided. Possible values: PRIMARY, " "SECONDARY, COORDINATOR"; FATAL_ERROR_EXIT(); } if (!ServerState::instance()->registerWithRole(role)) { LOG(FATAL) << "Couldn't register at agency."; FATAL_ERROR_EXIT(); } } ServerState::RoleEnum role = ServerState::instance()->getRole(); if (role == ServerState::ROLE_UNDEFINED) { // no role found LOG(FATAL) << "unable to determine unambiguous role for server '" << _myId << "'. No role configured in agency (" << endpoints << ")"; FATAL_ERROR_EXIT(); } if (role == ServerState::ROLE_SINGLE) { LOG(FATAL) << "determined single-server role for server '" << _myId << "'. Please check the configurarion in the agency (" << endpoints << ")"; FATAL_ERROR_EXIT(); } if (_myId.empty()) { _myId = ServerState::instance()->getId(); // has been set by getRole! } // check if my-address is set if (_myAddress.empty()) { // no address given, now ask the agency for our address _myAddress = ServerState::instance()->getAddress(); } // if nonempty, it has already been set above // If we are a coordinator, we wait until at least one DBServer is there, // otherwise we can do very little, in particular, we cannot create // any collection: if (role == ServerState::ROLE_COORDINATOR) { ClusterInfo* ci = ClusterInfo::instance(); double start = TRI_microtime(); while (true) { LOG(INFO) << "Waiting for DBservers to show up..."; ci->loadCurrentDBServers(); std::vector<ServerID> DBServers = ci->getCurrentDBServers(); if (DBServers.size() >= 1 && (DBServers.size() > 1 || TRI_microtime() - start > 15.0)) { LOG(INFO) << "Found " << DBServers.size() << " DBservers."; break; } sleep(1); }; } if (_myAddress.empty()) { LOG(FATAL) << "unable to determine internal address for server '" << _myId << "'. Please specify --cluster.my-address or configure the " "address for this server in the agency."; FATAL_ERROR_EXIT(); } // now we can validate --cluster.my-address std::string const unified = Endpoint::unifiedForm(_myAddress); if (unified.empty()) { LOG(FATAL) << "invalid endpoint '" << _myAddress << "' specified for --cluster.my-address"; FATAL_ERROR_EXIT(); } }
void GeneralServerFeature::defineHandlers() { TRI_ASSERT(_jobManager != nullptr); AgencyFeature* agency = application_features::ApplicationServer::getFeature<AgencyFeature>( "Agency"); TRI_ASSERT(agency != nullptr); ClusterFeature* cluster = application_features::ApplicationServer::getFeature<ClusterFeature>( "Cluster"); TRI_ASSERT(cluster != nullptr); AuthenticationFeature* authentication = application_features::ApplicationServer::getFeature< AuthenticationFeature>("Authentication"); TRI_ASSERT(authentication != nullptr); auto queryRegistry = QueryRegistryFeature::QUERY_REGISTRY; auto traverserEngineRegistry = TraverserEngineRegistryFeature::TRAVERSER_ENGINE_REGISTRY; // ........................................................................... // /_msg // ........................................................................... _handlerFactory->addPrefixHandler( "/_msg/please-upgrade", RestHandlerCreator<RestPleaseUpgradeHandler>::createNoData); // ........................................................................... // /_api // ........................................................................... _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::BATCH_PATH, RestHandlerCreator<RestBatchHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::CURSOR_PATH, RestHandlerCreator<RestCursorHandler>::createData<aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::DOCUMENT_PATH, RestHandlerCreator<RestDocumentHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::EDGES_PATH, RestHandlerCreator<RestEdgesHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::EXPORT_PATH, RestHandlerCreator<RestExportHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::IMPORT_PATH, RestHandlerCreator<RestImportHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::REPLICATION_PATH, RestHandlerCreator<RestReplicationHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::SIMPLE_QUERY_ALL_PATH, RestHandlerCreator<RestSimpleQueryHandler>::createData< aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::SIMPLE_QUERY_ALL_KEYS_PATH, RestHandlerCreator<RestSimpleQueryHandler>::createData< aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::WAL_PATH, RestHandlerCreator<RestWalHandler>::createNoData); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::SIMPLE_LOOKUP_PATH, RestHandlerCreator<RestSimpleHandler>::createData<aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::SIMPLE_REMOVE_PATH, RestHandlerCreator<RestSimpleHandler>::createData<aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::UPLOAD_PATH, RestHandlerCreator<RestUploadHandler>::createNoData); _handlerFactory->addPrefixHandler( "/_api/shard-comm", RestHandlerCreator<RestShardHandler>::createNoData); _handlerFactory->addPrefixHandler( "/_api/aql", RestHandlerCreator<aql::RestAqlHandler>::createData<aql::QueryRegistry*>, queryRegistry); _handlerFactory->addPrefixHandler( "/_api/aql-builtin", RestHandlerCreator<RestAqlFunctionsHandler>::createNoData); _handlerFactory->addPrefixHandler( "/_api/query", RestHandlerCreator<RestQueryHandler>::createNoData); _handlerFactory->addPrefixHandler( "/_api/query-cache", RestHandlerCreator<RestQueryCacheHandler>::createNoData); if (agency->isEnabled()) { _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::AGENCY_PATH, RestHandlerCreator<RestAgencyHandler>::createData<consensus::Agent*>, agency->agent()); _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::AGENCY_PRIV_PATH, RestHandlerCreator<RestAgencyPrivHandler>::createData< consensus::Agent*>, agency->agent()); } if (cluster->isEnabled()) { // add "/agency-callbacks" handler _handlerFactory->addPrefixHandler( cluster->agencyCallbacksPath(), RestHandlerCreator<RestAgencyCallbacksHandler>::createData< AgencyCallbackRegistry*>, cluster->agencyCallbackRegistry()); } _handlerFactory->addPrefixHandler( RestVocbaseBaseHandler::INTERNAL_TRAVERSER_PATH, RestHandlerCreator<InternalRestTraverserHandler>::createData< traverser::TraverserEngineRegistry*>, traverserEngineRegistry); // And now some handlers which are registered in both /_api and /_admin _handlerFactory->addPrefixHandler( "/_api/job", RestHandlerCreator<arangodb::RestJobHandler>::createData< AsyncJobManager*>, _jobManager.get()); _handlerFactory->addHandler( "/_api/version", RestHandlerCreator<RestVersionHandler>::createNoData); #ifdef ARANGODB_ENABLE_MAINTAINER_MODE _handlerFactory->addHandler( "/_admin/demo-engine", RestHandlerCreator<RestDemoHandler>::createNoData); #endif // ........................................................................... // /_admin // ........................................................................... _handlerFactory->addPrefixHandler( "/_admin/job", RestHandlerCreator<arangodb::RestJobHandler>::createData< AsyncJobManager*>, _jobManager.get()); _handlerFactory->addHandler( "/_admin/version", RestHandlerCreator<RestVersionHandler>::createNoData); // further admin handlers _handlerFactory->addPrefixHandler( "/_admin/log", RestHandlerCreator<arangodb::RestAdminLogHandler>::createNoData); _handlerFactory->addPrefixHandler( "/_admin/work-monitor", RestHandlerCreator<WorkMonitorHandler>::createNoData); _handlerFactory->addHandler( "/_admin/json-echo", RestHandlerCreator<RestEchoHandler>::createNoData); #ifdef ARANGODB_ENABLE_FAILURE_TESTS // This handler is to activate SYS_DEBUG_FAILAT on DB servers _handlerFactory->addPrefixHandler( "/_admin/debug", RestHandlerCreator<RestDebugHandler>::createNoData); #endif _handlerFactory->addPrefixHandler( "/_admin/shutdown", RestHandlerCreator<arangodb::RestShutdownHandler>::createNoData); if (authentication->isEnabled()) { _handlerFactory->addPrefixHandler( "/_open/auth", RestHandlerCreator<arangodb::RestAuthHandler>::createNoData); } // ........................................................................... // /_admin // ........................................................................... _handlerFactory->addPrefixHandler( "/", RestHandlerCreator<RestActionHandler>::createNoData); }