mirror of https://gitee.com/bigwinds/arangodb
runtime addition and removal of endpoints
This commit is contained in:
parent
6bbfb65f7c
commit
6ff314de0e
|
@ -231,49 +231,6 @@ BOOST_AUTO_TEST_CASE (EndpointDomainTypes) {
|
|||
CHECK_ENDPOINT_FEATURE(client, "http@unix:///tmp/socket", DomainType, Endpoint::DOMAIN_UNIX);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test protocols
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BOOST_AUTO_TEST_CASE (EndpointProtocols) {
|
||||
Endpoint* e;
|
||||
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://localhost", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://www.arangodb.org", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://127.0.0.1:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://localhost:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://www.arangodb.org:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://[127.0.0.1]", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://[::]", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://[127.0.0.1]:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "tcp://[::]:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://localhost", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://www.arangodb.org", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://127.0.0.1:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://localhost:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://www.arangodb.org:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://[127.0.0.1]", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://[::]", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://[127.0.0.1]:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "ssl://[::]:8529", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
|
||||
CHECK_ENDPOINT_FEATURE(client, "unix:///tmp/socket", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "unix:///tmp/socket/arango.sock", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
|
||||
CHECK_ENDPOINT_FEATURE(client, "http@tcp://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "http@ssl://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "http@unix:///tmp/socket", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "Http@tcp://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "Http@ssl://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "Http@unix:///tmp/socket", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "HTTP@tcp://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "HTTP@ssl://127.0.0.1", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
CHECK_ENDPOINT_FEATURE(client, "HTTP@unix:///tmp/socket", Protocol, Endpoint::PROTOCOL_HTTP);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test ports
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -579,7 +536,6 @@ BOOST_AUTO_TEST_CASE (EndpointServerTcpIpv4WithPort) {
|
|||
BOOST_CHECK_EQUAL("tcp://127.0.0.1:667", e->getSpecification());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENDPOINT_SERVER, e->getType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::DOMAIN_IPV4, e->getDomainType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::PROTOCOL_HTTP, e->getProtocol());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENCRYPTION_NONE, e->getEncryption());
|
||||
BOOST_CHECK_EQUAL(AF_INET, e->getDomain());
|
||||
BOOST_CHECK_EQUAL("127.0.0.1", e->getHost());
|
||||
|
@ -600,7 +556,6 @@ BOOST_AUTO_TEST_CASE (EndpointServerUnix) {
|
|||
BOOST_CHECK_EQUAL("unix:///path/to/arango.sock", e->getSpecification());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENDPOINT_SERVER, e->getType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::DOMAIN_UNIX, e->getDomainType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::PROTOCOL_HTTP, e->getProtocol());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENCRYPTION_NONE, e->getEncryption());
|
||||
BOOST_CHECK_EQUAL(AF_UNIX, e->getDomain());
|
||||
BOOST_CHECK_EQUAL("localhost", e->getHost());
|
||||
|
@ -621,7 +576,6 @@ BOOST_AUTO_TEST_CASE (EndpointClientSslIpV6WithPortHttp) {
|
|||
BOOST_CHECK_EQUAL("http@SSL://[0001:0002:0003:0004:0005:0006:0007:0008]:43425", e->getSpecification());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENDPOINT_CLIENT, e->getType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::DOMAIN_IPV6, e->getDomainType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::PROTOCOL_HTTP, e->getProtocol());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENCRYPTION_SSL, e->getEncryption());
|
||||
BOOST_CHECK_EQUAL(AF_INET6, e->getDomain());
|
||||
BOOST_CHECK_EQUAL("0001:0002:0003:0004:0005:0006:0007:0008", e->getHost());
|
||||
|
@ -642,7 +596,6 @@ BOOST_AUTO_TEST_CASE (EndpointClientTcpIpv6WithoutPort) {
|
|||
BOOST_CHECK_EQUAL("tcp://[::]", e->getSpecification());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENDPOINT_CLIENT, e->getType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::DOMAIN_IPV6, e->getDomainType());
|
||||
BOOST_CHECK_EQUAL(Endpoint::PROTOCOL_HTTP, e->getProtocol());
|
||||
BOOST_CHECK_EQUAL(Endpoint::ENCRYPTION_NONE, e->getEncryption());
|
||||
BOOST_CHECK_EQUAL(AF_INET6, e->getDomain());
|
||||
BOOST_CHECK_EQUAL("::", e->getHost());
|
||||
|
|
|
@ -560,6 +560,9 @@ void ArangoServer::buildApplicationServer () {
|
|||
LOGGER_FATAL_AND_EXIT("no database path has been supplied, giving up");
|
||||
}
|
||||
|
||||
// strip trailing separators
|
||||
_databasePath = StringUtils::rTrim(_databasePath, TRI_DIR_SEPARATOR_STR);
|
||||
|
||||
// .............................................................................
|
||||
// now run arangod
|
||||
// .............................................................................
|
||||
|
@ -1191,6 +1194,7 @@ void ArangoServer::openDatabases () {
|
|||
assert(_server != 0);
|
||||
|
||||
int res = TRI_InitServer(_server,
|
||||
_applicationEndpointServer,
|
||||
_databasePath.c_str(),
|
||||
&defaults,
|
||||
_disableReplicationLogger,
|
||||
|
|
|
@ -539,8 +539,8 @@ void ApplicationV8::setupOptions (map<string, basics::ProgramOptionsDescription>
|
|||
("javascript.gc-interval", &_gcInterval, "JavaScript request-based garbage collection interval (each x requests)")
|
||||
("javascript.gc-frequency", &_gcFrequency, "JavaScript time-based garbage collection frequency (each x seconds)")
|
||||
("javascript.action-directory", &_actionPath, "path to the JavaScript action directory")
|
||||
("javascript.app-path", &_appPath, "one directory for applications")
|
||||
("javascript.dev-app-path", &_devAppPath, "one directory for dev applications")
|
||||
("javascript.app-path", &_appPath, "directory for Foxx applications (normal mode)")
|
||||
("javascript.dev-app-path", &_devAppPath, "directory for Foxx applications (development mode)")
|
||||
("javascript.modules-path", &_modulesPath, "one or more directories separated by semi-colons")
|
||||
("javascript.package-path", &_packagePath, "one or more directories separated by semi-colons")
|
||||
("javascript.startup-directory", &_startupPath, "path to the directory containing alternate JavaScript startup scripts")
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "BasicsC/tri-strings.h"
|
||||
#include "CapConstraint/cap-constraint.h"
|
||||
#include "FulltextIndex/fulltext-index.h"
|
||||
#include "HttpServer/ApplicationEndpointServer.h"
|
||||
#include "Replication/InitialSyncer.h"
|
||||
#include "Rest/SslInterface.h"
|
||||
#include "ShapedJson/shape-accessor.h"
|
||||
|
@ -7920,7 +7921,16 @@ static v8::Handle<v8::Value> JS_ConfigureEndpoint (v8::Arguments const& argv) {
|
|||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() < 1 || argv.Length() > 2) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "CONFIGURE_ENDPOINT(<endpoint>, <names>)");
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "configureEndpoint(<endpoint>, <databases>)");
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
TRI_server_t* server = (TRI_server_t*) v8g->_server;
|
||||
ApplicationEndpointServer* s = static_cast<ApplicationEndpointServer*>(server->_applicationEndpointServer);
|
||||
|
||||
if (s == 0) {
|
||||
// not implemented in console mode
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
TRI_vocbase_t* vocbase = GetContextVocBase();
|
||||
|
@ -7933,16 +7943,14 @@ static v8::Handle<v8::Value> JS_ConfigureEndpoint (v8::Arguments const& argv) {
|
|||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
|
||||
}
|
||||
|
||||
// TODO: check endpoint string
|
||||
const string endpoint = TRI_ObjectToString(argv[0]);
|
||||
|
||||
// validate and register dbNames
|
||||
TRI_vector_string_t dbNames;
|
||||
TRI_InitVectorString(&dbNames, TRI_CORE_MEM_ZONE);
|
||||
// register dbNames
|
||||
vector<string> dbNames;
|
||||
|
||||
if (argv.Length() > 1) {
|
||||
if (! argv[1]->IsArray()) {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<names> must be a list");
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<databases> must be a list");
|
||||
}
|
||||
|
||||
v8::Handle<v8::Array> list = v8::Handle<v8::Array>::Cast(argv[1]);
|
||||
|
@ -7952,23 +7960,119 @@ static v8::Handle<v8::Value> JS_ConfigureEndpoint (v8::Arguments const& argv) {
|
|||
v8::Handle<v8::Value> name = list->Get(i);
|
||||
|
||||
if (name->IsString()) {
|
||||
const string dbName = TRI_ObjectToString(name);
|
||||
TRI_PushBackVectorString(&dbNames, TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, dbName.c_str()));
|
||||
dbNames.push_back(TRI_ObjectToString(name));
|
||||
}
|
||||
else {
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<names> must be a list of strings");
|
||||
TRI_V8_EXCEPTION_PARAMETER(scope, "<databases> must be a list of strings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
TRI_StoreEndpointServer((TRI_server_t*) v8g->_server, endpoint.c_str(), &dbNames);
|
||||
|
||||
TRI_DestroyVectorString(&dbNames);
|
||||
bool result = s->addEndpoint(endpoint, dbNames);
|
||||
|
||||
if (! result) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_ERROR_BAD_PARAMETER, "unable to bind to endpoint");
|
||||
}
|
||||
|
||||
return scope.Close(v8::True());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes a new endpoint
|
||||
///
|
||||
/// @FUN{REMOVE_ENDPOINT}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_RemoveEndpoint (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() < 1 || argv.Length() > 2) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "removeEndpoint(<endpoint>)");
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
TRI_server_t* server = (TRI_server_t*) v8g->_server;
|
||||
ApplicationEndpointServer* s = static_cast<ApplicationEndpointServer*>(server->_applicationEndpointServer);
|
||||
|
||||
if (s == 0) {
|
||||
// not implemented in console mode
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
TRI_vocbase_t* vocbase = GetContextVocBase();
|
||||
|
||||
if (vocbase == 0) {
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (! TRI_IsSystemVocBase(vocbase)) {
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
|
||||
}
|
||||
|
||||
bool result = s->removeEndpoint(TRI_ObjectToString(argv[0]));
|
||||
|
||||
if (! result) {
|
||||
TRI_V8_EXCEPTION_MESSAGE(scope, TRI_ERROR_BAD_PARAMETER, "endpoint is not registered");
|
||||
}
|
||||
|
||||
return scope.Close(v8::True());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a list of all endpoints
|
||||
///
|
||||
/// @FUN{LIST_ENDPOINTS}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ListEndpoints (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
TRI_V8_EXCEPTION_USAGE(scope, "listEndpoints()");
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = (TRI_v8_global_t*) v8::Isolate::GetCurrent()->GetData();
|
||||
TRI_server_t* server = (TRI_server_t*) v8g->_server;
|
||||
ApplicationEndpointServer* s = static_cast<ApplicationEndpointServer*>(server->_applicationEndpointServer);
|
||||
|
||||
if (s == 0) {
|
||||
// not implemented in console mode
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
TRI_vocbase_t* vocbase = GetContextVocBase();
|
||||
|
||||
if (vocbase == 0) {
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (! TRI_IsSystemVocBase(vocbase)) {
|
||||
TRI_V8_EXCEPTION(scope, TRI_ERROR_ARANGO_USE_SYSTEM_DATABASE);
|
||||
}
|
||||
|
||||
const map<string, vector<string> >& endpoints = s->getEndpoints();
|
||||
|
||||
v8::Handle<v8::Array> result = v8::Array::New();
|
||||
uint32_t j = 0;
|
||||
|
||||
map<string, vector<string> >::const_iterator it;
|
||||
for (it = endpoints.begin(); it != endpoints.end(); ++it) {
|
||||
v8::Handle<v8::Array> dbNames = v8::Array::New();
|
||||
|
||||
for (uint32_t i = 0; i < (*it).second.size(); ++i) {
|
||||
dbNames->Set(i, v8::String::New((*it).second.at(i).c_str()));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> item = v8::Object::New();
|
||||
item->Set(v8::String::New("endpoint"), v8::String::New((*it).first.c_str()));
|
||||
item->Set(v8::String::New("databases"), dbNames);
|
||||
|
||||
result->Set(j++, item);
|
||||
}
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -8786,6 +8890,8 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(context, "PARSE_DATETIME", JS_parseDatetime);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(context, "CONFIGURE_ENDPOINT", JS_ConfigureEndpoint, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "REMOVE_ENDPOINT", JS_RemoveEndpoint, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "LIST_ENDPOINTS", JS_ListEndpoints, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "RELOAD_AUTH", JS_ReloadAuth, true);
|
||||
TRI_AddGlobalFunctionVocbase(context, "TRANSACTION", JS_Transaction, true);
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ static bool EqualKeyDatabaseName (TRI_associative_pointer_t* array,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- endpoint functions
|
||||
// --SECTION-- server id functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -163,99 +163,6 @@ static bool EqualKeyDatabaseName (TRI_associative_pointer_t* array,
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes the endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashElementEndpoint (TRI_associative_pointer_t* array,
|
||||
void const* element) {
|
||||
TRI_server_endpoint_t const* e = element;
|
||||
|
||||
return TRI_FnvHashString((char const*) e->_endpoint);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compares an endpoint name and an endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualKeyEndpoint (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
char const* k = (char const*) key;
|
||||
TRI_server_endpoint_t const* e = element;
|
||||
|
||||
return TRI_EqualString(k, e->_endpoint);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- tick functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the current tick value, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline TRI_voc_tick_t GetTick (void) {
|
||||
return (ServerIdentifier | (CurrentTick << 16));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates the tick counter, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline void UpdateTick (TRI_voc_tick_t tick) {
|
||||
TRI_voc_tick_t s = tick >> 16;
|
||||
|
||||
if (CurrentTick < s) {
|
||||
CurrentTick = s;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the numeric part from a filename
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t GetNumericFilenamePart (const char* filename) {
|
||||
char* pos;
|
||||
|
||||
pos = strrchr(filename, '-');
|
||||
|
||||
if (pos == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return TRI_UInt64String(pos + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compare two filenames, based on the numeric part contained in
|
||||
/// the filename. this is used to sort database filenames on startup
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int NameComparator (const void* lhs, const void* rhs) {
|
||||
const char* l = *((char**) lhs);
|
||||
const char* r = *((char**) rhs);
|
||||
|
||||
const uint64_t numLeft = GetNumericFilenamePart(l);
|
||||
const uint64_t numRight = GetNumericFilenamePart(r);
|
||||
|
||||
if (numLeft != numRight) {
|
||||
return numLeft < numRight ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates a new server id
|
||||
///
|
||||
|
@ -393,6 +300,43 @@ static int DetermineServerId (TRI_server_t* server) {
|
|||
return res;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- tick functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the current tick value, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline TRI_voc_tick_t GetTick (void) {
|
||||
return (ServerIdentifier | (CurrentTick << 16));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates the tick counter, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static inline void UpdateTick (TRI_voc_tick_t tick) {
|
||||
TRI_voc_tick_t s = tick >> 16;
|
||||
|
||||
if (CurrentTick < s) {
|
||||
CurrentTick = s;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads shutdown information file
|
||||
/// this is called at server startup. if the file is present, the last tick
|
||||
|
@ -513,6 +457,58 @@ static int WriteShutdownInfo (TRI_server_t* server) {
|
|||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- database functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the current tick value, without using a lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the numeric part from a filename
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t GetNumericFilenamePart (const char* filename) {
|
||||
char* pos;
|
||||
|
||||
pos = strrchr(filename, '-');
|
||||
|
||||
if (pos == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return TRI_UInt64String(pos + 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief compare two filenames, based on the numeric part contained in
|
||||
/// the filename. this is used to sort database filenames on startup
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int NameComparator (const void* lhs, const void* rhs) {
|
||||
const char* l = *((char**) lhs);
|
||||
const char* r = *((char**) rhs);
|
||||
|
||||
const uint64_t numLeft = GetNumericFilenamePart(l);
|
||||
const uint64_t numRight = GetNumericFilenamePart(r);
|
||||
|
||||
if (numLeft != numRight) {
|
||||
return numLeft < numRight ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief iterate over all databases in the databases directory and open them
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1298,7 +1294,6 @@ static void DatabaseManager (void* data) {
|
|||
// remember the database path
|
||||
char* path;
|
||||
|
||||
printf("PHYSICALLY REMOVING DATABASE %s\n", database->_name);
|
||||
path = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, database->_path);
|
||||
|
||||
TRI_DestroyVocBase(database);
|
||||
|
@ -1348,12 +1343,17 @@ TRI_server_t* TRI_CreateServer () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InitServer (TRI_server_t* server,
|
||||
void* applicationEndpointServer,
|
||||
char const* basePath,
|
||||
TRI_vocbase_defaults_t const* defaults,
|
||||
bool disableLoggers,
|
||||
bool disableAppliers) {
|
||||
|
||||
assert(server != NULL);
|
||||
assert(basePath != NULL);
|
||||
|
||||
// c++ object, may be null in console mode
|
||||
server->_applicationEndpointServer = applicationEndpointServer;
|
||||
|
||||
// .............................................................................
|
||||
// set up paths and filenames
|
||||
|
@ -1426,20 +1426,6 @@ int TRI_InitServer (TRI_server_t* server,
|
|||
|
||||
TRI_InitMutex(&server->_createLock);
|
||||
|
||||
// .............................................................................
|
||||
// endpoints
|
||||
// .............................................................................
|
||||
|
||||
|
||||
TRI_InitAssociativePointer(&server->_endpoints,
|
||||
TRI_UNKNOWN_MEM_ZONE,
|
||||
&TRI_HashStringKeyAssociativePointer,
|
||||
HashElementEndpoint,
|
||||
EqualKeyEndpoint,
|
||||
NULL);
|
||||
|
||||
TRI_InitReadWriteLock(&server->_endpointsLock);
|
||||
|
||||
|
||||
server->_disableReplicationLoggers = disableLoggers;
|
||||
server->_disableReplicationAppliers = disableAppliers;
|
||||
|
@ -1457,9 +1443,6 @@ int TRI_InitServer (TRI_server_t* server,
|
|||
void TRI_DestroyServer (TRI_server_t* server) {
|
||||
CloseDatabases(server);
|
||||
|
||||
TRI_DestroyReadWriteLock(&server->_endpointsLock);
|
||||
TRI_DestroyAssociativePointer(&server->_endpoints);
|
||||
|
||||
TRI_DestroyMutex(&server->_createLock);
|
||||
TRI_DestroyVectorPointer(&server->_droppedDatabases);
|
||||
TRI_DestroyReadWriteLock(&server->_databasesLock);
|
||||
|
@ -2000,65 +1983,6 @@ TRI_voc_tick_t TRI_CurrentTickServer () {
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_server_endpoint_t* CreateEndpoint (char const* endpoint,
|
||||
TRI_vector_string_t const* databases) {
|
||||
TRI_server_endpoint_t* ep;
|
||||
|
||||
ep = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(TRI_server_endpoint_t), false);
|
||||
|
||||
if (ep == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ep->_endpoint = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, endpoint);
|
||||
|
||||
if (ep->_endpoint == NULL) {
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, ep);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_InitVectorString(&ep->_databases, TRI_CORE_MEM_ZONE);
|
||||
TRI_CopyDataVectorString(TRI_CORE_MEM_ZONE, &ep->_databases, databases);
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
static void FreeEndpoint (TRI_server_endpoint_t* ep) {
|
||||
TRI_FreeString(TRI_CORE_MEM_ZONE, ep->_endpoint);
|
||||
TRI_DestroyVectorString(&ep->_databases);
|
||||
|
||||
TRI_Free(TRI_CORE_MEM_ZONE, ep);
|
||||
}
|
||||
|
||||
int TRI_StoreEndpointServer (TRI_server_t* server,
|
||||
char const* endpoint,
|
||||
TRI_vector_string_t const* databases) {
|
||||
TRI_server_endpoint_t* ep;
|
||||
|
||||
TRI_WriteLockReadWriteLock(&server->_endpointsLock);
|
||||
|
||||
ep = TRI_RemoveKeyAssociativePointer(&server->_endpoints, endpoint);
|
||||
|
||||
if (ep != NULL) {
|
||||
FreeEndpoint(ep);
|
||||
}
|
||||
|
||||
ep = CreateEndpoint(endpoint, databases);
|
||||
|
||||
if (ep == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&server->_endpointsLock);
|
||||
|
||||
return TRI_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
TRI_InsertKeyAssociativePointer(&server->_endpoints, ep->_endpoint, ep, false);
|
||||
|
||||
TRI_WriteUnlockReadWriteLock(&server->_endpointsLock);
|
||||
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief msyncs a memory block between begin (incl) and end (excl)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -62,10 +62,8 @@ typedef struct TRI_server_s {
|
|||
TRI_vector_pointer_t _droppedDatabases;
|
||||
bool _shutdown;
|
||||
|
||||
TRI_associative_pointer_t _endpoints;
|
||||
TRI_read_write_lock_t _endpointsLock;
|
||||
|
||||
TRI_vocbase_defaults_t _defaults;
|
||||
void* _applicationEndpointServer; // ptr to C++ object
|
||||
|
||||
char* _basePath;
|
||||
char* _databasePath;
|
||||
|
@ -80,17 +78,6 @@ typedef struct TRI_server_s {
|
|||
}
|
||||
TRI_server_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief endpoint declaration for a server
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_server_endpoint_s {
|
||||
char* _endpoint;
|
||||
TRI_vector_string_t _databases;
|
||||
}
|
||||
TRI_server_endpoint_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief page size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -121,6 +108,7 @@ TRI_server_t* TRI_CreateServer (void);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_InitServer (TRI_server_t* server,
|
||||
void*,
|
||||
char const*,
|
||||
TRI_vocbase_defaults_t const*,
|
||||
bool,
|
||||
|
@ -277,14 +265,6 @@ TRI_voc_tick_t TRI_CurrentTickServer (void);
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief store a setting for an endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_StoreEndpointServer (TRI_server_t*,
|
||||
char const*,
|
||||
TRI_vector_string_t const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief msyncs a memory block between begin (incl) and end (excl)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -650,6 +650,58 @@ actions.defineHttp({
|
|||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSF_get_admin_configure_endpoint
|
||||
/// @brief configures a server endpoint
|
||||
///
|
||||
/// @RESTHEADER{POST /_admin/endpoint,configures a server endpoint}
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_admin/endpoint",
|
||||
context : "admin",
|
||||
prefix : true,
|
||||
|
||||
callback : function (req, res) {
|
||||
try {
|
||||
if (req.requestType === actions.GET) {
|
||||
actions.resultOk(req, res, actions.HTTP_OK, internal.listEndpoints());
|
||||
}
|
||||
|
||||
else if (req.requestType === actions.POST) {
|
||||
var body = actions.getJsonBody(req, res);
|
||||
|
||||
if (typeof body === undefined || typeof body.endpoint !== 'string') {
|
||||
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER,
|
||||
"invalid endpoint value");
|
||||
return;
|
||||
}
|
||||
|
||||
var result = internal.configureEndpoint(body.endpoint, body.databases || [ ]);
|
||||
actions.resultOk(req, res, actions.HTTP_OK, { result: result });
|
||||
}
|
||||
|
||||
else if (req.requestType === actions.DELETE) {
|
||||
if (req.suffix.length !== 1) {
|
||||
actions.resultBad(req, res, arangodb.ERROR_HTTP_BAD_PARAMETER,
|
||||
"expected DELETE /" + this.url + "/<endpoint>");
|
||||
return;
|
||||
}
|
||||
|
||||
var endpoint = decodeURIComponent(req.suffix[0]);
|
||||
var result = internal.removeEndpoint(endpoint);
|
||||
actions.resultOk(req, res, actions.HTTP_OK, { result: result });
|
||||
}
|
||||
else {
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err, undefined, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
REPLICATION_LOGGER_START, REPLICATION_LOGGER_STOP, REPLICATION_LOGGER_STATE,
|
||||
REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START,
|
||||
REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE,
|
||||
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID,
|
||||
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
|
||||
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
|
||||
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
|
||||
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
|
||||
|
@ -329,6 +329,33 @@
|
|||
delete REPLICATION_SERVER_ID;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief configureEndpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof CONFIGURE_ENDPOINT !== "undefined") {
|
||||
exports.configureEndpoint = CONFIGURE_ENDPOINT;
|
||||
delete CONFIGURE_ENDPOINT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removeEndpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof REMOVE_ENDPOINT !== "undefined") {
|
||||
exports.removeEndpoint = REMOVE_ENDPOINT;
|
||||
delete REMOVE_ENDPOINT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief listEndpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof LIST_ENDPOINTS !== "undefined") {
|
||||
exports.listEndpoints = LIST_ENDPOINTS;
|
||||
delete LIST_ENDPOINTS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugSetFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
REPLICATION_LOGGER_START, REPLICATION_LOGGER_STOP, REPLICATION_LOGGER_STATE,
|
||||
REPLICATION_LOGGER_CONFIGURE, REPLICATION_APPLIER_CONFIGURE, REPLICATION_APPLIER_START,
|
||||
REPLICATION_APPLIER_STOP, REPLICATION_APPLIER_FORGET, REPLICATION_APPLIER_STATE,
|
||||
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID,
|
||||
REPLICATION_SYNCHRONISE, REPLICATION_SERVER_ID, CONFIGURE_ENDPOINT, REMOVE_ENDPOINT, LIST_ENDPOINTS,
|
||||
SYS_DEBUG_CAN_USE_FAILAT, SYS_DEBUG_SET_FAILAT, SYS_DEBUG_REMOVE_FAILAT, SYS_DEBUG_CLEAR_FAILAT,
|
||||
SYS_DOWNLOAD, SYS_EXECUTE, SYS_LOAD, SYS_LOG_LEVEL, SYS_MD5, SYS_OUTPUT, SYS_PROCESS_STATISTICS,
|
||||
SYS_RAND, SYS_SERVER_STATISTICS, SYS_SPRINTF, SYS_TIME, SYS_START_PAGER, SYS_STOP_PAGER,
|
||||
|
@ -329,6 +329,33 @@
|
|||
delete REPLICATION_SERVER_ID;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief configureEndpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof CONFIGURE_ENDPOINT !== "undefined") {
|
||||
exports.configureEndpoint = CONFIGURE_ENDPOINT;
|
||||
delete CONFIGURE_ENDPOINT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removeEndpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof REMOVE_ENDPOINT !== "undefined") {
|
||||
exports.removeEndpoint = REMOVE_ENDPOINT;
|
||||
delete REMOVE_ENDPOINT;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief listEndpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (typeof LIST_ENDPOINTS !== "undefined") {
|
||||
exports.listEndpoints = LIST_ENDPOINTS;
|
||||
delete LIST_ENDPOINTS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief debugSetFailAt
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -160,7 +160,7 @@
|
|||
fm.scanAppDirectory();
|
||||
}
|
||||
catch (err) {
|
||||
console.error("cannot initialize FOXX application: %s", String(err));
|
||||
console.error("cannot initialize Foxx application: %s", String(err));
|
||||
}
|
||||
|
||||
var aal = internal.db._collection("_aal");
|
||||
|
|
|
@ -101,12 +101,6 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the protocol to be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual Endpoint::ProtocolType getProtocol () const = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the encryption to be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -122,11 +116,23 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief starts listining
|
||||
/// @brief add another endpoint at runtime
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool addEndpoint (Endpoint*) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove an endpoint at runtime
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual bool removeEndpoint (Endpoint*) = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief starts listening
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void startListening () = 0;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shuts down handlers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -180,31 +180,64 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief starts listining
|
||||
/// @brief starts listening
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void startListening () {
|
||||
EndpointList::ListType endpoints = _endpointList->getEndpoints(this->getProtocol(), this->getEncryption());
|
||||
map<string, Endpoint*> endpoints = _endpointList->getByPrefix(this->getEncryption());
|
||||
|
||||
for (EndpointList::ListType::const_iterator i = endpoints.begin(); i != endpoints.end(); ++i) {
|
||||
LOGGER_TRACE("trying to bind to endpoint '" << (*i).first->getSpecification() << "' for requests");
|
||||
for (map<string, Endpoint*>::iterator i = endpoints.begin(); i != endpoints.end(); ++i) {
|
||||
LOGGER_TRACE("trying to bind to endpoint '" << (*i).first << "' for requests");
|
||||
|
||||
bool ok = openEndpoint((*i).first);
|
||||
bool ok = openEndpoint((*i).second);
|
||||
|
||||
if (ok) {
|
||||
LOGGER_DEBUG("bound to endpoint '" << (*i).first->getSpecification() << "'");
|
||||
LOGGER_DEBUG("bound to endpoint '" << (*i).first << "'");
|
||||
}
|
||||
else {
|
||||
if ((*i).second) {
|
||||
LOGGER_FATAL_AND_EXIT("failed to bind to endpoint '" << (*i).first->getSpecification() << "'");
|
||||
}
|
||||
else {
|
||||
LOGGER_WARNING("failed to bind to endpoint '" << (*i).first->getSpecification() << "'");
|
||||
}
|
||||
LOGGER_FATAL_AND_EXIT("failed to bind to endpoint '" << (*i).first << "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add another endpoint at runtime
|
||||
/// the caller must make sure this is not called in parallel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool addEndpoint (Endpoint* endpoint) {
|
||||
bool ok = openEndpoint(endpoint);
|
||||
|
||||
if (ok) {
|
||||
LOGGER_INFO("added endpoint '" << endpoint->getSpecification() << "'");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an endpoint at runtime
|
||||
/// the caller must make sure this is not called in parallel
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool removeEndpoint (Endpoint* endpoint) {
|
||||
for (vector<ListenTask*>::iterator i = _listenTasks.begin(); i != _listenTasks.end(); ++i) {
|
||||
ListenTask* task = (*i);
|
||||
|
||||
if (task->endpoint() == endpoint) {
|
||||
// TODO: remove commtasks for the listentask
|
||||
|
||||
_scheduler->destroyTask(task);
|
||||
_listenTasks.erase(i);
|
||||
|
||||
LOGGER_INFO("removed endpoint '" << endpoint->getSpecification() << "'");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief shuts down handlers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -220,7 +253,7 @@ namespace triagens {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stops listining
|
||||
/// @brief stops listening
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void stopListening () {
|
||||
|
@ -255,7 +288,8 @@ namespace triagens {
|
|||
/// @brief handles connection request
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void handleConnected (TRI_socket_t s, ConnectionInfo& info) {
|
||||
virtual void handleConnected (TRI_socket_t s,
|
||||
ConnectionInfo& info) {
|
||||
GeneralCommTask<S, HF>* task = new SpecificCommTask<S, HF, CT>(dynamic_cast<S*>(this), s, info, _keepAliveTimeout);
|
||||
|
||||
GENERAL_SERVER_LOCK(&_commTasksLock);
|
||||
|
|
|
@ -151,19 +151,16 @@ bool ApplicationEndpointServer::buildServers () {
|
|||
EndpointServer* server;
|
||||
|
||||
// unencrypted endpoints
|
||||
if (_endpointList.count(Endpoint::PROTOCOL_HTTP, Endpoint::ENCRYPTION_NONE) > 0) {
|
||||
// http endpoints
|
||||
server = new HttpServer(_applicationScheduler->scheduler(),
|
||||
_applicationDispatcher->dispatcher(),
|
||||
_keepAliveTimeout,
|
||||
_handlerFactory);
|
||||
server = new HttpServer(_applicationScheduler->scheduler(),
|
||||
_applicationDispatcher->dispatcher(),
|
||||
_keepAliveTimeout,
|
||||
_handlerFactory);
|
||||
|
||||
server->setEndpointList(&_endpointList);
|
||||
_servers.push_back(server);
|
||||
}
|
||||
server->setEndpointList(&_endpointList);
|
||||
_servers.push_back(server);
|
||||
|
||||
// ssl endpoints
|
||||
if (_endpointList.count(Endpoint::PROTOCOL_HTTP, Endpoint::ENCRYPTION_SSL) > 0) {
|
||||
if (_endpointList.has(Endpoint::ENCRYPTION_SSL)) {
|
||||
// check the ssl context
|
||||
if (_sslContext == 0) {
|
||||
LOGGER_INFO("please use the --server.keyfile option");
|
||||
|
@ -254,17 +251,11 @@ bool ApplicationEndpointServer::parsePhase2 (ProgramOptions& options) {
|
|||
LOGGER_FATAL_AND_EXIT("no endpoint has been specified, giving up");
|
||||
}
|
||||
|
||||
const vector<string> dbNames;
|
||||
|
||||
// add & validate endpoints
|
||||
for (vector<string>::const_iterator i = _endpoints.begin(); i != _endpoints.end(); ++i) {
|
||||
Endpoint* endpoint = Endpoint::serverFactory(*i, _backlogSize);
|
||||
|
||||
if (endpoint == 0) {
|
||||
LOGGER_FATAL_AND_EXIT("invalid endpoint '" << *i << "'");
|
||||
}
|
||||
|
||||
assert(endpoint);
|
||||
|
||||
bool ok = _endpointList.addEndpoint(endpoint->getProtocol(), endpoint->getEncryption(), endpoint, true);
|
||||
bool ok = _endpointList.add((*i), dbNames, _backlogSize);
|
||||
|
||||
if (! ok) {
|
||||
LOGGER_FATAL_AND_EXIT("invalid endpoint '" << *i << "'");
|
||||
|
@ -276,36 +267,123 @@ bool ApplicationEndpointServer::parsePhase2 (ProgramOptions& options) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
/// @brief return a list of all endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ApplicationEndpointServer::addEndpoint (std::string const& newEndpoint) {
|
||||
// create the ssl context (if possible)
|
||||
bool ok = createSslContext();
|
||||
std::map<std::string, std::vector<std::string> > ApplicationEndpointServer::getEndpoints () {
|
||||
MUTEX_LOCKER(_endpointsLock);
|
||||
|
||||
if (! ok) {
|
||||
return _endpointList.getAll();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a new endpoint at runtime, and connects to it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ApplicationEndpointServer::addEndpoint (std::string const& newEndpoint,
|
||||
vector<string> const& dbNames) {
|
||||
// validate...
|
||||
const string unified = Endpoint::getUnifiedForm(newEndpoint);
|
||||
|
||||
if (unified.empty()) {
|
||||
// invalid endpoint
|
||||
return false;
|
||||
}
|
||||
|
||||
Endpoint* endpoint = Endpoint::serverFactory(newEndpoint, _backlogSize);
|
||||
|
||||
if (endpoint != 0) {
|
||||
ok = _endpointList.addEndpoint(endpoint->getProtocol(), endpoint->getEncryption(), endpoint, false);
|
||||
|
||||
if (ok) {
|
||||
_endpoints.push_back(newEndpoint);
|
||||
}
|
||||
Endpoint::EncryptionType encryption;
|
||||
if (unified.substr(0, 6) == "ssl://") {
|
||||
encryption = Endpoint::ENCRYPTION_SSL;
|
||||
}
|
||||
else {
|
||||
ok = false;
|
||||
encryption = Endpoint::ENCRYPTION_NONE;
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
LOGGER_WARNING("Could not add endpoint '" << newEndpoint << "'");
|
||||
// find the correct server (HTTP or HTTPS)
|
||||
for (size_t i = 0; i < _servers.size(); ++i) {
|
||||
if (_servers[i]->getEncryption() == encryption) {
|
||||
// found the correct server
|
||||
MUTEX_LOCKER(_endpointsLock);
|
||||
|
||||
Endpoint* endpoint;
|
||||
bool ok = _endpointList.add(newEndpoint, dbNames, _backlogSize, &endpoint);
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endpoint == 0) {
|
||||
// in this case, we updated an existing endpoint and are done
|
||||
return true;
|
||||
}
|
||||
|
||||
// this connects the new endpoint
|
||||
ok = _servers[i]->addEndpoint(endpoint);
|
||||
|
||||
if (ok) {
|
||||
LOGGER_DEBUG("bound to endpoint '" << newEndpoint << "'");
|
||||
}
|
||||
else {
|
||||
LOGGER_WARNING("failed to bind to endpoint '" << newEndpoint << "'");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an existing endpoint, and disconnects from it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ApplicationEndpointServer::removeEndpoint (std::string const& oldEndpoint) {
|
||||
// validate...
|
||||
const string unified = Endpoint::getUnifiedForm(oldEndpoint);
|
||||
|
||||
if (unified.empty()) {
|
||||
// invalid endpoint
|
||||
return false;
|
||||
}
|
||||
|
||||
return ok;
|
||||
Endpoint::EncryptionType encryption;
|
||||
if (unified.substr(0, 6) == "ssl://") {
|
||||
encryption = Endpoint::ENCRYPTION_SSL;
|
||||
}
|
||||
else {
|
||||
encryption = Endpoint::ENCRYPTION_NONE;
|
||||
}
|
||||
|
||||
// find the correct server (HTTP or HTTPS)
|
||||
for (size_t i = 0; i < _servers.size(); ++i) {
|
||||
if (_servers[i]->getEncryption() == encryption) {
|
||||
// found the correct server
|
||||
MUTEX_LOCKER(_endpointsLock);
|
||||
|
||||
Endpoint* endpoint;
|
||||
bool ok = _endpointList.remove(unified, &endpoint);
|
||||
|
||||
if (! ok) {
|
||||
LOGGER_WARNING("could not remove endpoint '" << oldEndpoint << "'");
|
||||
return false;
|
||||
}
|
||||
|
||||
// this disconnects the new endpoint
|
||||
ok = _servers[i]->removeEndpoint(endpoint);
|
||||
delete endpoint;
|
||||
|
||||
if (ok) {
|
||||
LOGGER_DEBUG("removed endpoint '" << oldEndpoint << "'");
|
||||
}
|
||||
else {
|
||||
LOGGER_WARNING("failed to remove endpoint '" << oldEndpoint << "'");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -313,7 +391,7 @@ bool ApplicationEndpointServer::addEndpoint (std::string const& newEndpoint) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ApplicationEndpointServer::prepare () {
|
||||
// dump used endpoints for user information
|
||||
// dump all endpoints for user information
|
||||
_endpointList.dump();
|
||||
|
||||
_handlerFactory = new HttpHandlerFactory(_authenticationRealm,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
#include "Basics/MutexLocker.h"
|
||||
#include "GeneralServer/EndpointServer.h"
|
||||
#include "Rest/EndpointList.h"
|
||||
#include "HttpServer/HttpHandlerFactory.h"
|
||||
|
@ -150,10 +151,23 @@ namespace triagens {
|
|||
bool parsePhase2 (basics::ProgramOptions&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
/// @brief return a list of all endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::map<std::string, std::vector<std::string> > getEndpoints ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a new endpoint at runtime, and connects to it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool addEndpoint (std::string const&);
|
||||
bool addEndpoint (std::string const&,
|
||||
std::vector<std::string> const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an existing endpoint and disconnects from it
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool removeEndpoint (std::string const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// {@inheritDoc}
|
||||
|
@ -275,6 +289,12 @@ namespace triagens {
|
|||
|
||||
rest::EndpointList _endpointList;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief mutex to protect _endpointList
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
basics::Mutex _endpointsLock;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deprecated hidden option for downwards compatibility
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -97,14 +97,6 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the protocol to be used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Endpoint::ProtocolType getProtocol () const {
|
||||
return Endpoint::PROTOCOL_HTTP;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the handler factory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -60,14 +60,12 @@ using namespace triagens::rest;
|
|||
|
||||
Endpoint::Endpoint (const Endpoint::EndpointType type,
|
||||
const Endpoint::DomainType domainType,
|
||||
const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption,
|
||||
const std::string& specification,
|
||||
int listenBacklog) :
|
||||
_connected(false),
|
||||
_type(type),
|
||||
_domainType(domainType),
|
||||
_protocol(protocol),
|
||||
_encryption(encryption),
|
||||
_specification(specification),
|
||||
_listenBacklog(listenBacklog) {
|
||||
|
@ -95,6 +93,81 @@ Endpoint::~Endpoint () {
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the endpoint specification in a unified form
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string Endpoint::getUnifiedForm (const std::string& specification) {
|
||||
if (specification.size() < 7) {
|
||||
return "";
|
||||
}
|
||||
|
||||
string copy = specification;
|
||||
StringUtils::trimInPlace(copy);
|
||||
copy = StringUtils::tolower(copy);
|
||||
|
||||
if (specification[specification.size() - 1] == '/') {
|
||||
// address ends with a slash => remove
|
||||
copy = copy.substr(0, copy.size() - 1);
|
||||
}
|
||||
|
||||
// read protocol from string
|
||||
if (StringUtils::isPrefix(copy, "http@")) {
|
||||
copy = copy.substr(5);
|
||||
}
|
||||
|
||||
#if TRI_HAVE_LINUX_SOCKETS
|
||||
if (StringUtils::isPrefix(copy, "unix://")) {
|
||||
// unix socket
|
||||
return copy;
|
||||
}
|
||||
#else
|
||||
// no unix socket for windows
|
||||
if (StringUtils::isPrefix(copy, "unix://")) {
|
||||
// unix socket
|
||||
return "";
|
||||
}
|
||||
#endif
|
||||
else if (! StringUtils::isPrefix(copy, "ssl://") &&
|
||||
! StringUtils::isPrefix(copy, "tcp://")) {
|
||||
// invalid type
|
||||
return "";
|
||||
}
|
||||
|
||||
// tcp/ip or ssl
|
||||
size_t found;
|
||||
string temp = copy.substr(6, copy.length()); // strip tcp:// or ssl://
|
||||
|
||||
if (temp[0] == '[') {
|
||||
// ipv6
|
||||
found = temp.find("]:", 1);
|
||||
if (found != string::npos && found > 2 && found + 2 < temp.size()) {
|
||||
// hostname and port (e.g. [address]:port)
|
||||
return copy;
|
||||
}
|
||||
|
||||
found = temp.find("]", 1);
|
||||
if (found != string::npos && found > 2 && found + 1 == temp.size()) {
|
||||
// hostname only (e.g. [address])
|
||||
return copy + ":" + StringUtils::itoa(EndpointIp::_defaultPort);
|
||||
}
|
||||
|
||||
// invalid address specification
|
||||
return "";
|
||||
}
|
||||
|
||||
// ipv4
|
||||
found = temp.find(':');
|
||||
|
||||
if (found != string::npos && found + 1 < temp.size()) {
|
||||
// hostname and port
|
||||
return copy;
|
||||
}
|
||||
|
||||
// hostname only
|
||||
return copy + ":" + StringUtils::itoa(EndpointIp::_defaultPort);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a client endpoint object from a string value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -133,9 +206,6 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
|
|||
copy = copy.substr(0, copy.size() - 1);
|
||||
}
|
||||
|
||||
// default protocol is HTTP
|
||||
Endpoint::ProtocolType protocol = PROTOCOL_HTTP;
|
||||
|
||||
// read protocol from string
|
||||
size_t found = copy.find('@');
|
||||
if (found != string::npos) {
|
||||
|
@ -161,7 +231,7 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
|
|||
#if TRI_HAVE_LINUX_SOCKETS
|
||||
else if (StringUtils::isPrefix(domainType, "unix://")) {
|
||||
// unix socket
|
||||
return new EndpointUnixDomain(type, protocol, specification, listenBacklog, copy.substr(strlen("unix://")));
|
||||
return new EndpointUnixDomain(type, specification, listenBacklog, copy.substr(strlen("unix://")));
|
||||
}
|
||||
#else
|
||||
// no unix socket for windows
|
||||
|
@ -186,14 +256,14 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
|
|||
// hostname and port (e.g. [address]:port)
|
||||
uint16_t port = (uint16_t) StringUtils::uint32(copy.substr(found + 2));
|
||||
|
||||
return new EndpointIpV6(type, protocol, encryption, specification, listenBacklog, copy.substr(1, found - 1), port);
|
||||
return new EndpointIpV6(type, encryption, specification, listenBacklog, copy.substr(1, found - 1), port);
|
||||
}
|
||||
|
||||
found = copy.find("]", 1);
|
||||
if (found != string::npos && found > 2 && found + 1 == copy.size()) {
|
||||
// hostname only (e.g. [address])
|
||||
|
||||
return new EndpointIpV6(type, protocol, encryption, specification, listenBacklog, copy.substr(1, found - 1), EndpointIp::_defaultPort);
|
||||
return new EndpointIpV6(type, encryption, specification, listenBacklog, copy.substr(1, found - 1), EndpointIp::_defaultPort);
|
||||
}
|
||||
|
||||
// invalid address specification
|
||||
|
@ -207,11 +277,11 @@ Endpoint* Endpoint::factory (const Endpoint::EndpointType type,
|
|||
// hostname and port
|
||||
uint16_t port = (uint16_t) StringUtils::uint32(copy.substr(found + 1));
|
||||
|
||||
return new EndpointIpV4(type, protocol, encryption, specification, listenBacklog, copy.substr(0, found), port);
|
||||
return new EndpointIpV4(type, encryption, specification, listenBacklog, copy.substr(0, found), port);
|
||||
}
|
||||
|
||||
// hostname only
|
||||
return new EndpointIpV4(type, protocol, encryption, specification, listenBacklog, copy, EndpointIp::_defaultPort);
|
||||
return new EndpointIpV4(type, encryption, specification, listenBacklog, copy, EndpointIp::_defaultPort);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -96,15 +96,6 @@ namespace triagens {
|
|||
DOMAIN_IPV6
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief protocols used for endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum ProtocolType {
|
||||
PROTOCOL_UNKNOWN,
|
||||
PROTOCOL_HTTP
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief encryption used when talking to endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -135,7 +126,6 @@ namespace triagens {
|
|||
|
||||
Endpoint (const EndpointType,
|
||||
const DomainType,
|
||||
const ProtocolType,
|
||||
const EncryptionType,
|
||||
const std::string&,
|
||||
int);
|
||||
|
@ -163,6 +153,12 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the endpoint specification in a unified form
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string getUnifiedForm (const std::string&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a server endpoint from a string value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -249,14 +245,6 @@ namespace triagens {
|
|||
return _domainType;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the protocol of an endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProtocolType getProtocol () const {
|
||||
return _protocol;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the encryption used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -336,12 +324,6 @@ namespace triagens {
|
|||
|
||||
DomainType _domainType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief protocol used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ProtocolType _protocol;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief encryption used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -81,13 +81,12 @@ const std::string EndpointIp::_defaultHost = "127.0.0.1";
|
|||
|
||||
EndpointIp::EndpointIp (const Endpoint::EndpointType type,
|
||||
const Endpoint::DomainType domainType,
|
||||
const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption,
|
||||
const std::string& specification,
|
||||
int listenBacklog,
|
||||
const std::string& host,
|
||||
const uint16_t port) :
|
||||
Endpoint(type, domainType, protocol, encryption, specification, listenBacklog), _host(host), _port(port) {
|
||||
Endpoint(type, domainType, encryption, specification, listenBacklog), _host(host), _port(port) {
|
||||
|
||||
assert(domainType == DOMAIN_IPV4 || domainType == Endpoint::DOMAIN_IPV6);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,6 @@ namespace triagens {
|
|||
|
||||
EndpointIp (const EndpointType,
|
||||
const DomainType,
|
||||
const ProtocolType,
|
||||
const EncryptionType,
|
||||
const std::string&,
|
||||
int,
|
||||
|
|
|
@ -50,13 +50,12 @@ using namespace triagens::rest;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointIpV4::EndpointIpV4 (const Endpoint::EndpointType type,
|
||||
const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption,
|
||||
const std::string& specification,
|
||||
int listenBacklog,
|
||||
const std::string& host,
|
||||
const uint16_t port) :
|
||||
EndpointIp(type, DOMAIN_IPV4, protocol, encryption, specification, listenBacklog, host, port) {
|
||||
EndpointIp(type, DOMAIN_IPV4, encryption, specification, listenBacklog, host, port) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointIpV4 (const EndpointType,
|
||||
const ProtocolType,
|
||||
const EncryptionType,
|
||||
const std::string&,
|
||||
int,
|
||||
|
|
|
@ -50,13 +50,12 @@ using namespace triagens::rest;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointIpV6::EndpointIpV6 (const Endpoint::EndpointType type,
|
||||
const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption,
|
||||
const std::string& specification,
|
||||
int listenBacklog,
|
||||
const std::string& host,
|
||||
const uint16_t port) :
|
||||
EndpointIp(type, DOMAIN_IPV6, protocol, encryption, specification, listenBacklog, host, port) {
|
||||
EndpointIp(type, DOMAIN_IPV6, encryption, specification, listenBacklog, host, port) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -56,7 +56,6 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointIpV6 (const EndpointType,
|
||||
const ProtocolType,
|
||||
const EncryptionType,
|
||||
const std::string&,
|
||||
int,
|
||||
|
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
#include "EndpointList.h"
|
||||
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Logger/Logger.h"
|
||||
|
||||
using namespace triagens::basics;
|
||||
using namespace triagens::rest;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -49,7 +51,7 @@ using namespace triagens::rest;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointList::EndpointList () :
|
||||
_lists() {
|
||||
_endpoints() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -57,13 +59,15 @@ EndpointList::EndpointList () :
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointList::~EndpointList () {
|
||||
for (map<string, ListType>::iterator i = _lists.begin(); i != _lists.end(); ++i) {
|
||||
for (ListType::iterator i2 = (*i).second.begin(); i2 != (*i).second.end(); ++i2) {
|
||||
delete (*i2).first;
|
||||
}
|
||||
map<string, pair<Endpoint*, vector<string> > >::iterator it;
|
||||
|
||||
(*i).second.clear();
|
||||
for (it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
Endpoint* ep = (*it).second.first;
|
||||
|
||||
delete ep;
|
||||
}
|
||||
|
||||
_endpoints.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -80,19 +84,151 @@ EndpointList::~EndpointList () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief count the number of elements in a sub-list
|
||||
/// @brief add a new endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t EndpointList::count (const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption) const {
|
||||
bool EndpointList::add (const string& specification,
|
||||
const vector<string>& dbNames,
|
||||
int backLogSize,
|
||||
Endpoint** dst) {
|
||||
const string key = Endpoint::getUnifiedForm(specification);
|
||||
|
||||
map<string, ListType>::const_iterator i = _lists.find(getKey(protocol, encryption));
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i == _lists.end()) {
|
||||
return 0;
|
||||
}
|
||||
map<string, pair<Endpoint*, vector<string> > >::iterator it = _endpoints.find(key);
|
||||
|
||||
return i->second.size();
|
||||
if (it != _endpoints.end()) {
|
||||
// already in list, just update
|
||||
(*it).second.second = dbNames;
|
||||
*dst = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
Endpoint* ep = Endpoint::serverFactory(key, backLogSize);
|
||||
|
||||
if (ep == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_endpoints[key] = pair<Endpoint*, vector<string> >(ep, dbNames);
|
||||
|
||||
if (dst != 0) {
|
||||
*dst = ep;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief remove a specific endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool EndpointList::remove (const string& specification,
|
||||
Endpoint** dst) {
|
||||
const string key = Endpoint::getUnifiedForm(specification);
|
||||
|
||||
if (key.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
map<string, pair<Endpoint*, vector<string> > >::const_iterator it = _endpoints.find(key);
|
||||
|
||||
if (it == _endpoints.end()) {
|
||||
// not in list
|
||||
return false;
|
||||
}
|
||||
|
||||
*dst = (*it).second.first;
|
||||
_endpoints.erase(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return all endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::map<std::string, std::vector<std::string> > EndpointList::getAll () const {
|
||||
map<string, vector<string> > result;
|
||||
map<string, pair<Endpoint*, vector<string> > >::const_iterator it;
|
||||
|
||||
for (it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
result[(*it).first] = (*it).second.second;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return all endpoints with a certain prefix
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::map<std::string, Endpoint*> EndpointList::getByPrefix (const string& prefix) const {
|
||||
map<string, Endpoint*> result;
|
||||
map<string, pair<Endpoint*, vector<string> > >::const_iterator it;
|
||||
|
||||
for (it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
const string& key = (*it).first;
|
||||
|
||||
if (StringUtils::isPrefix(key, prefix)) {
|
||||
result[key] = (*it).second.first;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return all endpoints with a certain encryption type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::map<std::string, Endpoint*> EndpointList::getByPrefix (const Endpoint::EncryptionType encryption) const {
|
||||
map<string, Endpoint*> result;
|
||||
map<string, pair<Endpoint*, vector<string> > >::const_iterator it;
|
||||
|
||||
for (it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
const string& key = (*it).first;
|
||||
|
||||
if (encryption == Endpoint::ENCRYPTION_SSL) {
|
||||
if (StringUtils::isPrefix(key, "ssl://")) {
|
||||
result[key] = (*it).second.first;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (StringUtils::isPrefix(key, "tcp://") || StringUtils::isPrefix(key, "unix://")) {
|
||||
result[key] = (*it).second.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return if there is an endpoint with a certain encryption type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool EndpointList::has (const Endpoint::EncryptionType encryption) const {
|
||||
map<string, pair<Endpoint*, vector<string> > >::const_iterator it;
|
||||
|
||||
for (it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
const string& key = (*it).first;
|
||||
|
||||
if (encryption == Endpoint::ENCRYPTION_SSL) {
|
||||
if (StringUtils::isPrefix(key, "ssl://")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (StringUtils::isPrefix(key, "tcp://") || StringUtils::isPrefix(key, "unix://")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -100,43 +236,25 @@ size_t EndpointList::count (const Endpoint::ProtocolType protocol,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EndpointList::dump () const {
|
||||
for (map<string, ListType>::const_iterator i = _lists.begin(); i != _lists.end(); ++i) {
|
||||
for (ListType::const_iterator i2 = (*i).second.begin(); i2 != (*i).second.end(); ++i2) {
|
||||
LOGGER_INFO("using endpoint '" << (*i2).first->getSpecification() << "' for " << (*i).first << " requests");
|
||||
}
|
||||
for (map<string, pair<Endpoint*, vector<string> > >::const_iterator it = _endpoints.begin(); it != _endpoints.end(); ++it) {
|
||||
Endpoint const* ep = (*it).second.first;
|
||||
|
||||
LOGGER_INFO("using endpoint '" << (*it).first << "' for " << getEncryptionName(ep->getEncryption()) << " requests");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return all endpoints for a specific protocol
|
||||
/// @brief return an encryption name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointList::ListType EndpointList::getEndpoints (const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption) const {
|
||||
|
||||
EndpointList::ListType result;
|
||||
map<string, EndpointList::ListType>::const_iterator i = _lists.find(getKey(protocol, encryption));
|
||||
|
||||
if (i != _lists.end()) {
|
||||
for (ListType::const_iterator i2 = (*i).second.begin(); i2 != (*i).second.end(); ++i2) {
|
||||
result.insert(pair<Endpoint*, bool>((*i2).first, (*i2).second));
|
||||
}
|
||||
|
||||
std::string EndpointList::getEncryptionName (const Endpoint::EncryptionType encryption) {
|
||||
switch (encryption) {
|
||||
case Endpoint::ENCRYPTION_SSL:
|
||||
return "ssl-encrypted";
|
||||
case Endpoint::ENCRYPTION_NONE:
|
||||
default:
|
||||
return "non-encrypted";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an endpoint for a specific protocol
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool EndpointList::addEndpoint (const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption,
|
||||
Endpoint* endpoint,
|
||||
bool isSystem) {
|
||||
|
||||
_lists[getKey(protocol, encryption)].insert(pair<Endpoint*, bool>(endpoint, isSystem));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -43,25 +43,6 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- typedefs
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Rest
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief typedef for list contents
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::map<Endpoint*, bool> ListType;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors / destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -93,25 +74,6 @@ namespace triagens {
|
|||
// --SECTION-- public methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Rest
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static const string getKey (const Endpoint::ProtocolType protocol,
|
||||
const Endpoint::EncryptionType encryption) {
|
||||
return string(getProtocolName(protocol) + " " + getEncryptionName(encryption));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Rest
|
||||
/// @{
|
||||
|
@ -120,60 +82,56 @@ namespace triagens {
|
|||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a protocol name
|
||||
/// @brief add a new endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const string getProtocolName (const Endpoint::ProtocolType protocol) {
|
||||
switch (protocol) {
|
||||
case Endpoint::PROTOCOL_HTTP:
|
||||
return "http";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
bool add (const std::string&,
|
||||
const std::vector<std::string>&,
|
||||
int,
|
||||
Endpoint** = 0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a encryption name
|
||||
/// @brief remove a specific endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const string getEncryptionName (const Endpoint::EncryptionType encryption) {
|
||||
switch (encryption) {
|
||||
case Endpoint::ENCRYPTION_SSL:
|
||||
return "ssl-encrypted";
|
||||
case Endpoint::ENCRYPTION_NONE:
|
||||
default:
|
||||
return "non-encrypted";
|
||||
}
|
||||
}
|
||||
bool remove (const std::string&,
|
||||
Endpoint**);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief count the number of elements in a sub-list
|
||||
/// @brief return all endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t count (const Endpoint::ProtocolType,
|
||||
const Endpoint::EncryptionType) const;
|
||||
std::map<std::string, std::vector<std::string> > getAll () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump all used endpoints
|
||||
/// @brief return all endpoints with a certain prefix
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dump() const ;
|
||||
std::map<std::string, Endpoint*> getByPrefix (const std::string&) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return all endpoints for a specific protocol
|
||||
/// @brief return all endpoints with a certain encryption type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ListType getEndpoints (const Endpoint::ProtocolType,
|
||||
const Endpoint::EncryptionType) const;
|
||||
std::map<std::string, Endpoint*> getByPrefix (const Endpoint::EncryptionType) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an endpoint for a specific protocol
|
||||
/// @brief return if there is an endpoint with a certain encryption type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool has (const Endpoint::EncryptionType) const;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dump all endpoints used
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool addEndpoint (const Endpoint::ProtocolType,
|
||||
const Endpoint::EncryptionType,
|
||||
Endpoint*,
|
||||
bool);
|
||||
void dump () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return an encryption name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static string getEncryptionName (const Endpoint::EncryptionType);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -191,10 +149,10 @@ namespace triagens {
|
|||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lists of endpoints
|
||||
/// @brief list of endpoints
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
map<string, ListType> _lists;
|
||||
std::map<std::string, std::pair<Endpoint*, std::vector<std::string> > > _endpoints;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -57,11 +57,10 @@ using namespace triagens::rest;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointUnixDomain::EndpointUnixDomain (const Endpoint::EndpointType type,
|
||||
const Endpoint::ProtocolType protocol,
|
||||
const std::string& specification,
|
||||
int listenBacklog,
|
||||
const std::string& path) :
|
||||
Endpoint(type, DOMAIN_UNIX, protocol, ENCRYPTION_NONE, specification, listenBacklog),
|
||||
Endpoint(type, DOMAIN_UNIX, ENCRYPTION_NONE, specification, listenBacklog),
|
||||
_path(path) {
|
||||
}
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EndpointUnixDomain (const EndpointType,
|
||||
const ProtocolType,
|
||||
const std::string&,
|
||||
int,
|
||||
const std::string&);
|
||||
|
|
|
@ -78,6 +78,14 @@ namespace triagens {
|
|||
|
||||
bool isBound () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the endpoint
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Endpoint* endpoint () const {
|
||||
return _endpoint;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -131,6 +139,7 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
Endpoint* _endpoint;
|
||||
|
||||
TRI_socket_t _listenSocket;
|
||||
|
||||
size_t acceptFailures;
|
||||
|
|
Loading…
Reference in New Issue