2014-12-18 18:50:47 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*
|
|
|
|
*/
|
2014-09-12 04:44:10 +00:00
|
|
|
|
2015-02-06 17:42:03 +00:00
|
|
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
|
|
|
2014-12-03 23:14:02 +00:00
|
|
|
#include <osquery/dispatcher.h>
|
|
|
|
#include <osquery/flags.h>
|
2015-01-21 21:36:55 +00:00
|
|
|
#include <osquery/logger.h>
|
2014-12-03 23:14:02 +00:00
|
|
|
|
2014-09-12 04:44:10 +00:00
|
|
|
#include "osquery/core/conversions.h"
|
|
|
|
|
|
|
|
using namespace apache::thrift::concurrency;
|
|
|
|
|
|
|
|
namespace osquery {
|
|
|
|
|
2014-10-27 16:34:13 +00:00
|
|
|
/// The worker_threads define the default thread pool size.
|
2015-02-17 08:36:20 +00:00
|
|
|
FLAG(int32, worker_threads, 4, "Number of work dispatch threads");
|
2014-09-12 04:44:10 +00:00
|
|
|
|
2015-02-10 17:42:13 +00:00
|
|
|
void interruptableSleep(size_t milli) {
|
2015-02-06 17:42:03 +00:00
|
|
|
boost::this_thread::sleep(boost::posix_time::milliseconds(milli));
|
|
|
|
}
|
|
|
|
|
2014-09-30 02:06:33 +00:00
|
|
|
Dispatcher& Dispatcher::getInstance() {
|
|
|
|
static Dispatcher d;
|
|
|
|
return d;
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Dispatcher::Dispatcher() {
|
2014-11-26 01:38:16 +00:00
|
|
|
#ifdef FBOSQUERY
|
|
|
|
thread_manager_ = ThreadManager::newSimpleThreadManager(
|
|
|
|
(size_t)FLAGS_worker_threads, 0);
|
|
|
|
auto threadFactory =
|
|
|
|
std::shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
|
|
|
|
#else
|
2015-02-04 03:55:16 +00:00
|
|
|
thread_manager_ =
|
|
|
|
boost_to_std_shared_ptr(InternalThreadManager::newSimpleThreadManager(
|
|
|
|
(size_t)FLAGS_worker_threads, 0));
|
2014-09-12 04:44:10 +00:00
|
|
|
auto threadFactory =
|
|
|
|
boost::shared_ptr<PosixThreadFactory>(new PosixThreadFactory());
|
2014-11-26 01:38:16 +00:00
|
|
|
#endif
|
2014-09-15 18:09:33 +00:00
|
|
|
thread_manager_->threadFactory(threadFactory);
|
|
|
|
thread_manager_->start();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
2015-02-04 03:55:16 +00:00
|
|
|
Status Dispatcher::add(std::shared_ptr<InternalRunnable> task) {
|
2014-09-12 04:44:10 +00:00
|
|
|
try {
|
2014-11-26 01:38:16 +00:00
|
|
|
#ifdef FBOSQUERY
|
|
|
|
thread_manager_->add(task, 0, 0);
|
|
|
|
#else
|
2014-09-15 18:09:33 +00:00
|
|
|
thread_manager_->add(std_to_boost_shared_ptr(task), 0, 0);
|
2014-11-26 01:38:16 +00:00
|
|
|
#endif
|
2014-09-21 21:29:28 +00:00
|
|
|
} catch (std::exception& e) {
|
2014-09-12 04:44:10 +00:00
|
|
|
return Status(1, e.what());
|
|
|
|
}
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
2015-02-04 03:55:16 +00:00
|
|
|
Status Dispatcher::addService(std::shared_ptr<InternalRunnable> service) {
|
|
|
|
if (service->hasRun()) {
|
|
|
|
return Status(1, "Cannot schedule a service twice");
|
|
|
|
}
|
|
|
|
|
|
|
|
auto thread = std::make_shared<boost::thread>(
|
|
|
|
boost::bind(&InternalRunnable::run, &*service));
|
|
|
|
service_threads_.push_back(thread);
|
|
|
|
services_.push_back(std::move(service));
|
|
|
|
return Status(0, "OK");
|
|
|
|
}
|
|
|
|
|
|
|
|
InternalThreadManagerRef Dispatcher::getThreadManager() {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_;
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-15 18:09:33 +00:00
|
|
|
void Dispatcher::join() { thread_manager_->join(); }
|
2014-09-12 04:44:10 +00:00
|
|
|
|
2015-02-04 03:55:16 +00:00
|
|
|
void Dispatcher::joinServices() {
|
2015-02-19 01:19:45 +00:00
|
|
|
for (auto& thread : getInstance().service_threads_) {
|
2015-02-04 03:55:16 +00:00
|
|
|
thread->join();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dispatcher::removeServices() {
|
|
|
|
for (const auto& service : services_) {
|
|
|
|
while (true) {
|
|
|
|
// Wait for each thread's entry point (enter) meaning the thread context
|
|
|
|
// was allocated and (run) was called by boost::thread started.
|
|
|
|
if (service->hasRun()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// We only need to check if std::terminate is call very quickly after
|
|
|
|
// the boost::thread is created.
|
|
|
|
::usleep(200);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& thread : service_threads_) {
|
|
|
|
thread->interrupt();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deallocate services.
|
|
|
|
service_threads_.clear();
|
|
|
|
services_.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
InternalThreadManager::STATE Dispatcher::state() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->state();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-15 18:09:33 +00:00
|
|
|
void Dispatcher::addWorker(size_t value) { thread_manager_->addWorker(value); }
|
2014-09-12 04:44:10 +00:00
|
|
|
|
|
|
|
void Dispatcher::removeWorker(size_t value) {
|
2014-09-15 18:09:33 +00:00
|
|
|
thread_manager_->removeWorker(value);
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Dispatcher::idleWorkerCount() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->idleWorkerCount();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-15 18:09:33 +00:00
|
|
|
size_t Dispatcher::workerCount() const {
|
|
|
|
return thread_manager_->workerCount();
|
|
|
|
}
|
2014-09-12 04:44:10 +00:00
|
|
|
|
|
|
|
size_t Dispatcher::pendingTaskCount() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->pendingTaskCount();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Dispatcher::totalTaskCount() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->totalTaskCount();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Dispatcher::pendingTaskCountMax() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->pendingTaskCountMax();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Dispatcher::expiredTaskCount() const {
|
2014-09-15 18:09:33 +00:00
|
|
|
return thread_manager_->expiredTaskCount();
|
2014-09-12 04:44:10 +00:00
|
|
|
}
|
|
|
|
}
|