EventFactory, Dispatcher as singletons

This commit is contained in:
Teddy Reed 2014-09-29 19:06:33 -07:00
parent 5b3152230f
commit 6eb9c5fd44
11 changed files with 80 additions and 89 deletions

View File

@ -83,7 +83,7 @@ class DBHandle {
* @return an instance of osquery::Status which indicates the success or
* failure of connecting to RocksDB
*/
osquery::Status getStatus();
Status getStatus();
/**
* @brief Helper method which can be used to get a raw pointer to the
@ -112,9 +112,9 @@ class DBHandle {
* @return an instance of osquery::Status indicating the success or failure
* of the operation.
*/
osquery::Status Get(const std::string& domain,
const std::string& key,
std::string& value);
Status Get(const std::string& domain,
const std::string& key,
std::string& value);
/**
* @brief Put data into the database
@ -127,9 +127,9 @@ class DBHandle {
* @return an instance of osquery::Status indicating the success or failure
* of the operation.
*/
osquery::Status Put(const std::string& domain,
const std::string& key,
const std::string& value);
Status Put(const std::string& domain,
const std::string& key,
const std::string& value);
/**
* @brief Delete data from the database
@ -141,7 +141,7 @@ class DBHandle {
* @return an instance of osquery::Status indicating the success or failure
* of the operation.
*/
osquery::Status Delete(const std::string& domain, const std::string& key);
Status Delete(const std::string& domain, const std::string& key);
/**
* @brief List the data in a "domain"
@ -154,8 +154,7 @@ class DBHandle {
* @return an instance of osquery::Status indicating the success or failure
* of the operation.
*/
osquery::Status Scan(const std::string& domain,
std::vector<std::string>& results);
Status Scan(const std::string& domain, std::vector<std::string>& results);
private:
/**

View File

@ -42,7 +42,7 @@ class Dispatcher {
*
* @return a shared pointer to an instance of osquery::Dispatch.
*/
static std::shared_ptr<Dispatcher> getInstance();
static Dispatcher& getInstance();
/**
* @brief add a task to the dispatcher.

View File

@ -460,7 +460,7 @@ class EventModule {
class EventFactory {
public:
/// Access to the EventFactory instance.
static std::shared_ptr<EventFactory> getInstance();
static EventFactory& getInstance();
/**
* @brief Add an EventType to the factory.
@ -548,7 +548,7 @@ class EventFactory {
/// Get the number of EventTypes.
static size_t numEventTypes() {
return EventFactory::getInstance()->event_types_.size();
return EventFactory::getInstance().event_types_.size();
}
/**
@ -591,6 +591,8 @@ class EventFactory {
private:
EventFactory() { ending_ = false; }
EventFactory(EventFactory const&);
void operator=(EventFactory const&);
private:
/// Set ending to True to cause event type run loops to finish.

View File

@ -11,20 +11,19 @@
using osquery::Status;
const std::string kTestingDBHandlePath = "/tmp/rocksdb-osquery-dbhandletests";
namespace osquery {
class DBHandleTests : public testing::Test {
public:
void SetUp() {
// Setup a testing DB instance
db = DBHandle::getInstanceAtPath("/tmp/rocksdb-osquery-dbhandletests");
db = DBHandle::getInstanceAtPath(kTestingDBHandlePath);
cfh_queries = DBHandle::getInstance()->getHandleForColumnFamily(kQueries);
cfh_foobar =
DBHandle::getInstance()->getHandleForColumnFamily("foobartest");
}
void TearDown() {
boost::filesystem::remove_all("/tmp/rocksdb-osquery-dbhandletests");
}
public:
rocksdb::ColumnFamilyHandle* cfh_queries;
rocksdb::ColumnFamilyHandle* cfh_foobar;
@ -94,5 +93,7 @@ TEST_F(DBHandleTests, test_scan) {
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
google::InitGoogleLogging(argv[0]);
return RUN_ALL_TESTS();
int status = RUN_ALL_TESTS();
boost::filesystem::remove_all(kTestingDBHandlePath);
return status;
}

View File

@ -14,14 +14,14 @@
using namespace osquery::core;
const std::string kTestingQueryDBPath = "/tmp/rocksdb-osquery-querytests";
namespace osquery {
class QueryTests : public testing::Test {
public:
void SetUp() {
db = DBHandle::getInstanceAtPath("/tmp/rocksdb-osquery-querytests");
}
void TearDown() {
boost::filesystem::remove_all("/tmp/rocksdb-osquery-querytests");
db = DBHandle::getInstanceAtPath(kTestingQueryDBPath);
}
public:
@ -137,5 +137,7 @@ TEST_F(QueryTests, test_get_current_results) {
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
int status = RUN_ALL_TESTS();
boost::filesystem::remove_all(kTestingQueryDBPath);
return status;
}

View File

@ -17,10 +17,9 @@ DEFINE_int32(worker_threads,
kDefaultThreadPoolSize,
"The number of threads to use for the work dispatcher");
std::shared_ptr<Dispatcher> Dispatcher::getInstance() {
static std::shared_ptr<Dispatcher> q =
std::shared_ptr<Dispatcher>(new Dispatcher());
return q;
Dispatcher& Dispatcher::getInstance() {
static Dispatcher d;
return d;
}
Dispatcher::Dispatcher() {

View File

@ -9,9 +9,9 @@ namespace osquery {
class DispatcherTests : public testing::Test {};
TEST_F(DispatcherTests, test_singleton) {
auto one = Dispatcher::getInstance();
auto two = Dispatcher::getInstance();
EXPECT_EQ(one->getThreadManager().get(), two->getThreadManager().get());
auto& one = Dispatcher::getInstance();
auto& two = Dispatcher::getInstance();
EXPECT_EQ(one.getThreadManager().get(), two.getThreadManager().get());
}
class TestRunnable : public apache::thrift::concurrency::Runnable {
@ -22,15 +22,15 @@ class TestRunnable : public apache::thrift::concurrency::Runnable {
};
TEST_F(DispatcherTests, test_add_work) {
auto d = Dispatcher::getInstance();
auto& dispatcher = Dispatcher::getInstance();
int base = 5;
int repetitions = 1;
int i = base;
for (int c = 0; c < repetitions; ++c) {
d->add(std::make_shared<TestRunnable>(&i));
dispatcher.add(std::make_shared<TestRunnable>(&i));
}
while (d->totalTaskCount() > 0) {
while (dispatcher.totalTaskCount() > 0) {
}
EXPECT_EQ(i, base + repetitions);

View File

@ -238,11 +238,11 @@ Status EventModule::add(const Row& r, EventTime time) {
}
void EventFactory::delay() {
auto ef = EventFactory::getInstance();
for (const auto& eventtype : EventFactory::getInstance()->event_types_) {
auto& ef = EventFactory::getInstance();
for (const auto& eventtype : EventFactory::getInstance().event_types_) {
auto thread_ = std::make_shared<boost::thread>(
boost::bind(&EventFactory::run, eventtype.first));
ef->threads_.push_back(thread_);
ef.threads_.push_back(thread_);
}
}
@ -252,13 +252,13 @@ Status EventFactory::run(EventTypeID type_id) {
// Assume it can either make use of an entrypoint poller/selector or
// take care of async callback registrations in setUp/configure/run
// only once and handle event queueing/firing in callbacks.
auto event_type = EventFactory::getInstance()->getEventType(type_id);
auto event_type = EventFactory::getInstance().getEventType(type_id);
if (event_type == nullptr) {
return Status(1, "No Event Type");
}
Status status = Status(0, "OK");
while (!EventFactory::getInstance()->ending_ && status.ok()) {
while (!EventFactory::getInstance().ending_ && status.ok()) {
// Can optionally implement a global cooloff latency here.
status = event_type->run();
}
@ -268,41 +268,41 @@ Status EventFactory::run(EventTypeID type_id) {
}
void EventFactory::end(bool should_end) {
EventFactory::getInstance()->ending_ = should_end;
EventFactory::getInstance().ending_ = should_end;
// Join on the thread group.
::usleep(400);
}
// There's no reason for the event factory to keep multiple instances.
std::shared_ptr<EventFactory> EventFactory::getInstance() {
static auto q = std::shared_ptr<EventFactory>(new EventFactory());
return q;
EventFactory& EventFactory::getInstance() {
static EventFactory ef;
return ef;
}
Status EventFactory::registerEventType(const EventTypeRef event_type) {
EventTypeID type_id = event_type->type();
auto ef = EventFactory::getInstance();
auto& ef = EventFactory::getInstance();
auto type_id = event_type->type();
if (ef->getEventType(type_id) != nullptr) {
if (ef.getEventType(type_id) != nullptr) {
// This is a duplicate type id?
return Status(1, "Duplicate Event Type");
}
ef->event_types_[type_id] = event_type;
ef.event_types_[type_id] = event_type;
event_type->setUp();
return Status(0, "OK");
}
Status EventFactory::registerEventModule(const EventModuleRef event_module) {
auto ef = EventFactory::getInstance();
auto& ef = EventFactory::getInstance();
// Let the module initialize any Monitors.
event_module->init();
ef->event_modules_.push_back(event_module);
ef.event_modules_.push_back(event_module);
return Status(0, "OK");
}
Status EventFactory::addMonitor(EventTypeID type_id, const MonitorRef monitor) {
auto event_type = EventFactory::getInstance()->getEventType(type_id);
auto event_type = EventFactory::getInstance().getEventType(type_id);
if (event_type == nullptr) {
// Cannot create a Monitor for a missing type_id.
return Status(1, "No Event Type");
@ -322,7 +322,7 @@ Status EventFactory::addMonitor(EventTypeID type_id,
}
size_t EventFactory::numMonitors(EventTypeID type_id) {
const auto& event_type = EventFactory::getInstance()->getEventType(type_id);
const auto& event_type = EventFactory::getInstance().getEventType(type_id);
if (event_type != nullptr) {
return event_type->numMonitors();
}
@ -330,10 +330,10 @@ size_t EventFactory::numMonitors(EventTypeID type_id) {
}
std::shared_ptr<EventType> EventFactory::getEventType(EventTypeID type_id) {
const auto& ef = EventFactory::getInstance();
const auto& it = ef->event_types_.find(type_id);
if (it != ef->event_types_.end()) {
return ef->event_types_[type_id];
auto& ef = EventFactory::getInstance();
const auto& it = ef.event_types_.find(type_id);
if (it != ef.event_types_.end()) {
return ef.event_types_[type_id];
}
return nullptr;
}
@ -343,25 +343,25 @@ Status EventFactory::deregisterEventType(const EventTypeRef event_type) {
}
Status EventFactory::deregisterEventType(EventTypeID type_id) {
auto ef = EventFactory::getInstance();
const auto& it = ef->event_types_.find(type_id);
if (it == ef->event_types_.end()) {
auto& ef = EventFactory::getInstance();
const auto& it = ef.event_types_.find(type_id);
if (it == ef.event_types_.end()) {
return Status(1, "No Event Type registered");
}
ef->event_types_[type_id]->tearDown();
ef->event_types_.erase(it);
ef.event_types_[type_id]->tearDown();
ef.event_types_.erase(it);
return Status(0, "OK");
}
Status EventFactory::deregisterEventTypes() {
auto ef = EventFactory::getInstance();
auto it = ef->event_types_.begin();
for (; it != ef->event_types_.end(); it++) {
auto& ef = EventFactory::getInstance();
auto it = ef.event_types_.begin();
for (; it != ef.event_types_.end(); it++) {
it->second->tearDown();
}
ef->event_types_.erase(ef->event_types_.begin(), ef->event_types_.end());
ef.event_types_.erase(ef.event_types_.begin(), ef.event_types_.end());
return Status(0, "OK");
}
}
@ -369,13 +369,13 @@ Status EventFactory::deregisterEventTypes() {
namespace osquery {
namespace registries {
void faucet(EventTypes ets, EventModules ems) {
auto ef = osquery::EventFactory::getInstance();
auto& ef = osquery::EventFactory::getInstance();
for (const auto& event_type : ets) {
ef->registerEventType(event_type.second);
ef.registerEventType(event_type.second);
}
for (const auto& event_module : ems) {
ef->registerEventModule(event_module.second);
ef.registerEventModule(event_module.second);
}
}
}

View File

@ -7,16 +7,15 @@
#include "osquery/events.h"
#include "osquery/core/test_util.h"
const std::string kTestingEventsDBPath = "/tmp/rocksdb-osquery-testevents";
namespace osquery {
class EventsDatabaseTests : public ::testing::Test {
public:
void SetUp() {
// Setup a testing DB instance
DBHandle::getInstanceAtPath("/tmp/rocksdb-osquery-testevents");
}
void TearDown() {
boost::filesystem::remove_all("/tmp/rocksdb-osquery-testevents");
DBHandle::getInstanceAtPath(kTestingEventsDBPath);
}
};
@ -71,5 +70,7 @@ TEST_F(EventsDatabaseTests, test_event_add) {
int main(int argc, char* argv[]) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
int status = RUN_ALL_TESTS();
boost::filesystem::remove_all(kTestingEventsDBPath);
return status;
}

View File

@ -1,26 +1,16 @@
// Copyright 2004-present Facebook. All Rights Reserved.
#include <gtest/gtest.h>
#include "osquery/events.h"
#include <gtest/gtest.h>
namespace osquery {
class EventsTests : public testing::Test {
protected:
virtual void SetUp() { ef = EventFactory::getInstance(); }
virtual void TearDown() { ef->deregisterEventTypes(); }
std::shared_ptr<EventFactory> ef;
public:
void TearDown() { EventFactory::deregisterEventTypes(); }
};
TEST_F(EventsTests, test_singleton) {
auto one = EventFactory::getInstance();
auto two = EventFactory::getInstance();
EXPECT_EQ(one, two);
}
class BasicEventType : public EventType {
DECLARE_EVENTTYPE(BasicEventType, MonitorContext, EventContext);
};

View File

@ -15,8 +15,6 @@ const std::string kRealTestPath = "/tmp/osquery-inotify-trigger";
class INotifyTests : public testing::Test {
protected:
virtual void SetUp() { ef = EventFactory::getInstance(); }
virtual void TearDown() { EventFactory::deregisterEventTypes(); }
void StartEventLoop() {
@ -43,7 +41,6 @@ class INotifyTests : public testing::Test {
}
boost::thread temp_thread_;
std::shared_ptr<EventFactory> ef;
};
// Helper eager wait function.