mirror of https://gitee.com/bigwinds/arangodb
issue 435.1: allow a user to specify the number of IResearchFeature threads via command line (#6164)
This commit is contained in:
parent
63efe2a634
commit
364360ae79
|
@ -425,7 +425,8 @@ NS_BEGIN(iresearch)
|
||||||
Field::Field(Field&& rhs)
|
Field::Field(Field&& rhs)
|
||||||
: _features(rhs._features),
|
: _features(rhs._features),
|
||||||
_analyzer(std::move(rhs._analyzer)),
|
_analyzer(std::move(rhs._analyzer)),
|
||||||
_name(std::move(rhs._name)) {
|
_name(std::move(rhs._name)),
|
||||||
|
_storeValues(std::move(rhs._storeValues)) {
|
||||||
rhs._features = nullptr;
|
rhs._features = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,6 +435,7 @@ Field& Field::operator=(Field&& rhs) {
|
||||||
_features = rhs._features;
|
_features = rhs._features;
|
||||||
_analyzer = std::move(rhs._analyzer);
|
_analyzer = std::move(rhs._analyzer);
|
||||||
_name = std::move(rhs._name);
|
_name = std::move(rhs._name);
|
||||||
|
_storeValues = std::move(rhs._storeValues);
|
||||||
rhs._features = nullptr;
|
rhs._features = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,20 @@ typedef arangodb::aql::AqlValue (*IResearchFunctionPtr)(
|
||||||
arangodb::SmallVector<arangodb::aql::AqlValue> const&
|
arangodb::SmallVector<arangodb::aql::AqlValue> const&
|
||||||
);
|
);
|
||||||
|
|
||||||
|
size_t computeThreadPoolSize(size_t threads, size_t threadsLimit) {
|
||||||
|
static const size_t MAX_THREADS = 8; // arbitrary limit on the upper bound of threads in pool
|
||||||
|
static const size_t MIN_THREADS = 1; // at least one thread is required
|
||||||
|
auto maxThreads = threadsLimit ? threadsLimit : MAX_THREADS;
|
||||||
|
|
||||||
|
return threads
|
||||||
|
? threads
|
||||||
|
: std::max(
|
||||||
|
MIN_THREADS,
|
||||||
|
std::min(maxThreads, size_t(std::thread::hardware_concurrency()) / 4)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
void registerFunctions(arangodb::aql::AqlFunctionFeature& functions) {
|
void registerFunctions(arangodb::aql::AqlFunctionFeature& functions) {
|
||||||
arangodb::iresearch::addFunction(functions, {
|
arangodb::iresearch::addFunction(functions, {
|
||||||
"__ARANGOSEARCH_SCORE_DEBUG", // name
|
"__ARANGOSEARCH_SCORE_DEBUG", // name
|
||||||
|
@ -382,11 +396,13 @@ class IResearchFeature::Async {
|
||||||
public:
|
public:
|
||||||
typedef std::function<bool(size_t& timeoutMsec, bool timeout)> Fn;
|
typedef std::function<bool(size_t& timeoutMsec, bool timeout)> Fn;
|
||||||
|
|
||||||
Async();
|
explicit Async(size_t poolSize = 0);
|
||||||
|
Async(size_t poolSize, Async&& other);
|
||||||
~Async();
|
~Async();
|
||||||
|
|
||||||
void emplace(std::shared_ptr<ResourceMutex> const& mutex, Fn &&fn); // add an asynchronous task
|
void emplace(std::shared_ptr<ResourceMutex> const& mutex, Fn &&fn); // add an asynchronous task
|
||||||
void notify() const; // notify all tasks
|
void notify() const; // notify all tasks
|
||||||
|
size_t poolSize() { return _pool.size(); }
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -431,6 +447,8 @@ class IResearchFeature::Async {
|
||||||
arangodb::basics::ConditionVariable _join; // mutex to join on
|
arangodb::basics::ConditionVariable _join; // mutex to join on
|
||||||
std::vector<Thread> _pool; // thread pool (size fixed for the entire life of object)
|
std::vector<Thread> _pool; // thread pool (size fixed for the entire life of object)
|
||||||
std::atomic<bool> _terminate; // unconditionaly terminate async tasks
|
std::atomic<bool> _terminate; // unconditionaly terminate async tasks
|
||||||
|
|
||||||
|
void stop(Thread* redelegate = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
void IResearchFeature::Async::Thread::run() {
|
void IResearchFeature::Async::Thread::run() {
|
||||||
|
@ -446,7 +464,7 @@ void IResearchFeature::Async::Thread::run() {
|
||||||
SCOPED_LOCK_NAMED(_mutex, lock); // aquire before '_terminate' check so that don't miss notify()
|
SCOPED_LOCK_NAMED(_mutex, lock); // aquire before '_terminate' check so that don't miss notify()
|
||||||
|
|
||||||
if (_terminate->load()) {
|
if (_terminate->load()) {
|
||||||
return; // termination requested
|
break; // termination requested
|
||||||
}
|
}
|
||||||
|
|
||||||
// transfer any new pending tasks into active tasks
|
// transfer any new pending tasks into active tasks
|
||||||
|
@ -492,7 +510,7 @@ void IResearchFeature::Async::Thread::run() {
|
||||||
_wasNotified = false; // ignore notification since woke up
|
_wasNotified = false; // ignore notification since woke up
|
||||||
|
|
||||||
if (_terminate->load()) { // check again after sleep
|
if (_terminate->load()) { // check again after sleep
|
||||||
return; // termination requested
|
break; // termination requested
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,15 +575,25 @@ void IResearchFeature::Async::Thread::run() {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ...........................................................................
|
||||||
|
// move all tasks back into _pending in case the may neeed to be reasigned
|
||||||
|
// ...........................................................................
|
||||||
|
SCOPED_LOCK_NAMED(_mutex, lock); // '_pending' may be modified asynchronously
|
||||||
|
|
||||||
|
for (auto& task: pendingRedelegate) {
|
||||||
|
_pending.emplace_back(std::move(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& task: _tasks) {
|
||||||
|
_pending.emplace_back(std::move(task));
|
||||||
|
}
|
||||||
|
|
||||||
|
_tasks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
IResearchFeature::Async::Async(): _terminate(false) {
|
IResearchFeature::Async::Async(size_t poolSize): _terminate(false) {
|
||||||
static const unsigned int MAX_THREADS = 8; // arbitrary limit on the upper bound of threads in pool
|
poolSize = std::max(size_t(1), poolSize); // need at least one thread
|
||||||
static const unsigned int MIN_THREADS = 1; // at least one thread is required
|
|
||||||
auto const poolSize = std::max(
|
|
||||||
MIN_THREADS,
|
|
||||||
std::min(MAX_THREADS, std::thread::hardware_concurrency() / 4) // arbitrary fraction of available cores
|
|
||||||
);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < poolSize; ++i) {
|
for (size_t i = 0; i < poolSize; ++i) {
|
||||||
_pool.emplace_back(std::string("ArangoSearch #") + std::to_string(i));
|
_pool.emplace_back(std::string("ArangoSearch #") + std::to_string(i));
|
||||||
|
@ -579,23 +607,15 @@ IResearchFeature::Async::Async(): _terminate(false) {
|
||||||
last = &thread;
|
last = &thread;
|
||||||
thread._terminate = &_terminate;
|
thread._terminate = &_terminate;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IResearchFeature::Async::Async(size_t poolSize, Async&& other)
|
||||||
|
: Async(poolSize) {
|
||||||
|
other.stop(&_pool[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
IResearchFeature::Async::~Async() {
|
IResearchFeature::Async::~Async() {
|
||||||
_terminate.store(true); // request stop asynchronous tasks
|
stop();
|
||||||
notify(); // notify all threads
|
|
||||||
|
|
||||||
CONDITION_LOCKER(lock, _join);
|
|
||||||
|
|
||||||
// join with all threads in pool
|
|
||||||
for (auto& thread: _pool) {
|
|
||||||
if (thread.hasStarted()) {
|
|
||||||
while(thread.isRunning()) {
|
|
||||||
_join.wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IResearchFeature::Async::emplace(
|
void IResearchFeature::Async::emplace(
|
||||||
|
@ -632,6 +652,35 @@ void IResearchFeature::Async::start() {
|
||||||
<< "started " << _pool.size() << " ArangoSearch maintenance thread(s)";
|
<< "started " << _pool.size() << " ArangoSearch maintenance thread(s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IResearchFeature::Async::stop(Thread* redelegate /*= nullptr*/) {
|
||||||
|
_terminate.store(true); // request stop asynchronous tasks
|
||||||
|
notify(); // notify all threads
|
||||||
|
|
||||||
|
CONDITION_LOCKER(lock, _join);
|
||||||
|
|
||||||
|
// join with all threads in pool
|
||||||
|
for (auto& thread: _pool) {
|
||||||
|
if (thread.hasStarted()) {
|
||||||
|
while(thread.isRunning()) {
|
||||||
|
_join.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// redelegate all thread tasks if requested
|
||||||
|
if (redelegate) {
|
||||||
|
SCOPED_LOCK(redelegate->_mutex);
|
||||||
|
|
||||||
|
for (auto& task: thread._pending) {
|
||||||
|
redelegate->_pending.emplace_back(std::move(task));
|
||||||
|
++redelegate->_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread._pending.clear();
|
||||||
|
redelegate->_cond.notify_all(); // notify thread about a new task (thread may be sleeping indefinitely)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IResearchFeature::IResearchFeature(
|
IResearchFeature::IResearchFeature(
|
||||||
arangodb::application_features::ApplicationServer& server
|
arangodb::application_features::ApplicationServer& server
|
||||||
)
|
)
|
||||||
|
@ -642,7 +691,6 @@ IResearchFeature::IResearchFeature(
|
||||||
_threadsLimit(0) {
|
_threadsLimit(0) {
|
||||||
setOptional(true);
|
setOptional(true);
|
||||||
startsAfter("V8Phase");
|
startsAfter("V8Phase");
|
||||||
|
|
||||||
startsAfter("IResearchAnalyzer"); // used for retrieving IResearch analyzers for functions
|
startsAfter("IResearchAnalyzer"); // used for retrieving IResearch analyzers for functions
|
||||||
startsAfter("AQLFunctions");
|
startsAfter("AQLFunctions");
|
||||||
}
|
}
|
||||||
|
@ -716,6 +764,12 @@ void IResearchFeature::prepare() {
|
||||||
// start the async task thread pool
|
// start the async task thread pool
|
||||||
if (!ServerState::instance()->isCoordinator() &&
|
if (!ServerState::instance()->isCoordinator() &&
|
||||||
!ServerState::instance()->isAgent()) {
|
!ServerState::instance()->isAgent()) {
|
||||||
|
auto poolSize = computeThreadPoolSize(_threads, _threadsLimit);
|
||||||
|
|
||||||
|
if (_async->poolSize() != poolSize) {
|
||||||
|
_async = std::make_unique<Async>(poolSize, std::move(*_async));
|
||||||
|
}
|
||||||
|
|
||||||
_async->start();
|
_async->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ struct IResearchFeatureSetup {
|
||||||
|
|
||||||
~IResearchFeatureSetup() {
|
~IResearchFeatureSetup() {
|
||||||
arangodb::LogTopic::setLogLevel(arangodb::iresearch::TOPIC.name(), arangodb::LogLevel::DEFAULT);
|
arangodb::LogTopic::setLogLevel(arangodb::iresearch::TOPIC.name(), arangodb::LogLevel::DEFAULT);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr;
|
||||||
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -75,6 +76,15 @@ TEST_CASE("IResearchFeatureTest", "[iresearch][iresearch-feature]") {
|
||||||
UNUSED(s);
|
UNUSED(s);
|
||||||
|
|
||||||
SECTION("test_start") {
|
SECTION("test_start") {
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
auto* functions = new arangodb::aql::AqlFunctionFeature(server);
|
auto* functions = new arangodb::aql::AqlFunctionFeature(server);
|
||||||
arangodb::iresearch::IResearchFeature iresearch(server);
|
arangodb::iresearch::IResearchFeature iresearch(server);
|
||||||
|
@ -130,6 +140,15 @@ SECTION("IResearch_version") {
|
||||||
SECTION("test_async") {
|
SECTION("test_async") {
|
||||||
// schedule task (null resource mutex)
|
// schedule task (null resource mutex)
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -150,6 +169,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// schedule task (null resource mutex value)
|
// schedule task (null resource mutex value)
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -171,6 +199,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// schedule task (null functr)
|
// schedule task (null functr)
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -187,6 +224,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// schedule task (wait indefinite)
|
// schedule task (wait indefinite)
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -210,6 +256,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// single-run task
|
// single-run task
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -231,6 +286,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// multi-run task
|
// multi-run task
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -265,6 +329,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// trigger task by notify
|
// trigger task by notify
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -297,6 +370,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// trigger by timeout
|
// trigger by timeout
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -332,6 +414,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// deallocate empty
|
// deallocate empty
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -343,6 +434,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// deallocate with running tasks
|
// deallocate with running tasks
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
auto resourceMutex = std::make_shared<arangodb::iresearch::ResourceMutex>(&server);
|
auto resourceMutex = std::make_shared<arangodb::iresearch::ResourceMutex>(&server);
|
||||||
bool deallocated = false;
|
bool deallocated = false;
|
||||||
|
@ -365,6 +465,15 @@ SECTION("test_async") {
|
||||||
|
|
||||||
// multiple tasks with same resourceMutex + resourceMutex reset (sequential creation)
|
// multiple tasks with same resourceMutex + resourceMutex reset (sequential creation)
|
||||||
{
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::iresearch::IResearchFeature feature(server);
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
@ -409,6 +518,53 @@ SECTION("test_async") {
|
||||||
CHECK((true == deallocated1));
|
CHECK((true == deallocated1));
|
||||||
thread.join();
|
thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// schedule task (resize pool)
|
||||||
|
{
|
||||||
|
// create a new instance of an ApplicationServer and fill it with the required features
|
||||||
|
// cannot use the existing server since its features already have some state
|
||||||
|
std::shared_ptr<arangodb::application_features::ApplicationServer> originalServer(
|
||||||
|
arangodb::application_features::ApplicationServer::server,
|
||||||
|
[](arangodb::application_features::ApplicationServer* ptr)->void {
|
||||||
|
arangodb::application_features::ApplicationServer::server = ptr;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
|
arangodb::iresearch::IResearchFeature feature(server);
|
||||||
|
server.addFeature(new arangodb::ViewTypesFeature(server)); // required for IResearchFeature::prepare()
|
||||||
|
arangodb::options::ProgramOptions options("", "", "", nullptr);
|
||||||
|
auto optionsPtr = std::shared_ptr<arangodb::options::ProgramOptions>(&options, [](arangodb::options::ProgramOptions*)->void {});
|
||||||
|
feature.collectOptions(optionsPtr);
|
||||||
|
options.get<arangodb::options::UInt64Parameter>("arangosearch.threads")->set("8");
|
||||||
|
auto resourceMutex = std::make_shared<arangodb::iresearch::ResourceMutex>(&server);
|
||||||
|
bool deallocated = false;
|
||||||
|
std::condition_variable cond;
|
||||||
|
std::mutex mutex;
|
||||||
|
size_t count = 0;
|
||||||
|
auto last = std::chrono::system_clock::now();
|
||||||
|
std::chrono::system_clock::duration diff;
|
||||||
|
SCOPED_LOCK_NAMED(mutex, lock);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::shared_ptr<bool> flag(&deallocated, [](bool* ptr)->void { *ptr = true; });
|
||||||
|
feature.async(resourceMutex, [&cond, &mutex, flag, &count, &last, &diff](size_t& timeoutMsec, bool)->bool {
|
||||||
|
diff = std::chrono::system_clock::now() - last;
|
||||||
|
last = std::chrono::system_clock::now();
|
||||||
|
timeoutMsec = 100;
|
||||||
|
if (++count <= 1) return true;
|
||||||
|
SCOPED_LOCK(mutex);
|
||||||
|
cond.notify_all();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
feature.prepare(); // start thread pool after a task has been scheduled, to trigger resize with a task
|
||||||
|
CHECK((std::cv_status::timeout != cond.wait_for(lock, std::chrono::milliseconds(1000))));
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
CHECK((true == deallocated));
|
||||||
|
CHECK((2 == count));
|
||||||
|
CHECK((std::chrono::milliseconds(100) < diff));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -45,6 +45,7 @@ struct IResearchViewMetaSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
~IResearchViewMetaSetup() {
|
~IResearchViewMetaSetup() {
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr;
|
||||||
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct LogicalDataSourceSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
~LogicalDataSourceSetup() {
|
~LogicalDataSourceSetup() {
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr;
|
||||||
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
arangodb::EngineSelectorFeature::ENGINE = nullptr;
|
||||||
|
|
||||||
// destroy application features
|
// destroy application features
|
||||||
|
|
|
@ -82,6 +82,7 @@ int main(int argc, char* argv[]) {
|
||||||
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
arangodb::application_features::ApplicationServer server(nullptr, nullptr);
|
||||||
arangodb::ShellColorsFeature sc(server);
|
arangodb::ShellColorsFeature sc(server);
|
||||||
|
|
||||||
|
arangodb::application_features::ApplicationServer::server = nullptr; // avoid "ApplicationServer initialized twice"
|
||||||
sc.prepare();
|
sc.prepare();
|
||||||
|
|
||||||
arangodb::ArangoGlobalContext ctx(1, const_cast<char**>(&ARGV0), ".");
|
arangodb::ArangoGlobalContext ctx(1, const_cast<char**>(&ARGV0), ".");
|
||||||
|
|
Loading…
Reference in New Issue