diff --git a/producer/event_monitor_producer/src/common.h b/producer/event_monitor_producer/src/common.h index 374caa9019adfbf04cf682eb9a8c65c2fceefded..e3a192c6bca880671bb9b59542943345d4ec677d 100644 --- a/producer/event_monitor_producer/src/common.h +++ b/producer/event_monitor_producer/src/common.h @@ -9,7 +9,7 @@ namespace asapo { enum class EventType { closed, - renamed_from + renamed_to }; struct FileEvent { diff --git a/producer/event_monitor_producer/src/eventmon_config.cpp b/producer/event_monitor_producer/src/eventmon_config.cpp index 66082225ff0a0e29806f0468369e6cd77834d0eb..e4ee00fa3d8f2be519b648373ddaa3562a120a48 100644 --- a/producer/event_monitor_producer/src/eventmon_config.cpp +++ b/producer/event_monitor_producer/src/eventmon_config.cpp @@ -19,8 +19,9 @@ Error EventMonConfigFactory::ParseConfigFile(std::string file_name) { (err = parser.GetString("BeamtimeID", &config.beamtime_id)) || (err = parser.GetString("Mode", &config.mode_str)) || (err = parser.GetUInt64("NThreads", &config.nthreads)) || - (err = parser.GetString("LogLevel", &config.log_level_str)); - (err = parser.GetArrayString("MonitoredFolders", &config.monitored_folders)); + (err = parser.GetString("LogLevel", &config.log_level_str)) || + (err = parser.GetArrayString("MonitoredFolders", &config.monitored_folders)) || + (err = parser.GetArrayString("IgnoreExtentions", &config.ignored_extentions)); return err; } diff --git a/producer/event_monitor_producer/src/eventmon_config.h b/producer/event_monitor_producer/src/eventmon_config.h index 90f986fa2f4992fda71f9f0d6fd31c72a4350627..9066df3c7c7c5686f7ec897b63186186ebbb6585 100644 --- a/producer/event_monitor_producer/src/eventmon_config.h +++ b/producer/event_monitor_producer/src/eventmon_config.h @@ -17,6 +17,7 @@ struct EventMonConfig { std::string beamtime_id; RequestHandlerType mode = RequestHandlerType::kTcp; std::vector<std::string> monitored_folders; + std::vector<std::string> ignored_extentions; private: std::string log_level_str; std::string mode_str; diff --git a/producer/event_monitor_producer/src/folder_event_detector.cpp b/producer/event_monitor_producer/src/folder_event_detector.cpp index ff62551caec7cd03831ccd6f46e2a77b86e779a7..bca5e7273d416302b886622219ae5c0821e061f4 100644 --- a/producer/event_monitor_producer/src/folder_event_detector.cpp +++ b/producer/event_monitor_producer/src/folder_event_detector.cpp @@ -9,27 +9,64 @@ FolderEventDetector::FolderEventDetector(const EventMonConfig* config) : system_ config_{config}{ } -Error FolderEventDetector::GetNextEvent(EventHeader* event_header) { - if (!monitoring_started_) { - auto err = TextError("monitoring is not started yet"); - return err; +inline bool ends_with(std::string const & value, std::string const & ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + + +bool FolderEventDetector::IgnoreEvent(const FileEvent &event) { + for (auto& ext: config_->ignored_extentions) { + if (ends_with(event.name,ext)) { + return true; + } } + return false; +} + +Error FolderEventDetector::UpdateEventsBuffer() { Error err; auto file_events = system_folder_watch__->GetFileEventList(&err); if (err) { return err; } + if (file_events.size() == 0) { return EventMonitorErrorTemplates::kNoNewEvent.Generate(); } - FileEvent file_event = file_events[0]; - event_header->file_size = file_event.size; - event_header->file_name = std::move(file_event.name); + for (auto& event : file_events) { + if (!IgnoreEvent(event)) { + events_buffer_.emplace_back(EventHeader{0,event.size,event.name}); + } + } + return nullptr; } + +Error FolderEventDetector::GetNextEvent(EventHeader* event_header) { + if (!monitoring_started_) { + auto err = TextError("monitoring is not started yet"); + return err; + } + + if (BufferIsEmpty()) { + if (auto err = UpdateEventsBuffer()) { + return err; + } + } + + return GetHeaderFromBuffer(event_header); +} + +bool FolderEventDetector::BufferIsEmpty() const +{ + return events_buffer_.size() == 0; +} + Error FolderEventDetector::StartMonitoring() { if (monitoring_started_) { return nullptr; @@ -44,4 +81,13 @@ Error FolderEventDetector::StartMonitoring() { return nullptr; } +Error FolderEventDetector::GetHeaderFromBuffer(EventHeader* event_header) { + if (events_buffer_.size() == 0) { + return EventMonitorErrorTemplates::kNoNewEvent.Generate(); + } + *event_header = std::move(events_buffer_.front()); + events_buffer_.pop_front(); + return nullptr; +} + } \ No newline at end of file diff --git a/producer/event_monitor_producer/src/folder_event_detector.h b/producer/event_monitor_producer/src/folder_event_detector.h index c6748aa69b1a65a49098f93a3b03aa5e3e668a4d..fc479c694efb7c2a5d3551ed5fb7b6db8c38a3e9 100644 --- a/producer/event_monitor_producer/src/folder_event_detector.h +++ b/producer/event_monitor_producer/src/folder_event_detector.h @@ -1,6 +1,9 @@ #ifndef ASAPO_INOTOFY_EVENT_DETECTOR_H #define ASAPO_INOTOFY_EVENT_DETECTOR_H +#include <deque> + + #include "event_detector.h" #include "eventmon_config.h" #include "io/io.h" @@ -18,6 +21,11 @@ class FolderEventDetector : public AbstractEventDetector { private: const EventMonConfig* config_; bool monitoring_started_= false; + std::deque<EventHeader> events_buffer_; + Error UpdateEventsBuffer(); + Error GetHeaderFromBuffer(EventHeader* event_header); + bool IgnoreEvent(const FileEvent& event); + bool BufferIsEmpty() const; }; } diff --git a/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp b/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp index a031b4889b70c0a95f881a99bfb74f59ba70f980..1fd953a3665dd9f69c5ccf1324aa4024275d325f 100644 --- a/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp +++ b/producer/event_monitor_producer/unittests/mock_eventmon_config.cpp @@ -56,7 +56,17 @@ Error SetFolderMonConfig (const EventMonConfig& config) { mon_folders.pop_back(); } + std::string ignored_exts; + for (auto ext:config.ignored_extentions) { + ignored_exts+="\""+ext+"\""+","; + } + if (ignored_exts.size()) { + ignored_exts.pop_back(); + } + + config_string += "," + std::string("\"MonitoredFolders\":") + "[" + mon_folders + "]"; + config_string += "," + std::string("\"IgnoreExtentions\":") + "[" + ignored_exts + "]"; config_string += "," + std::string("\"Tag\":") + "\"" + config.tag + "\""; config_string += "," + std::string("\"AsapoEndpoint\":") + "\"" + config.asapo_endpoint + "\""; diff --git a/producer/event_monitor_producer/unittests/test_eventmon_config.cpp b/producer/event_monitor_producer/unittests/test_eventmon_config.cpp index 7b65865eecc7ada780a27788c8808f52e3f28633..f789cd40837f129d64a98692d78e01098ac2d688 100644 --- a/producer/event_monitor_producer/unittests/test_eventmon_config.cpp +++ b/producer/event_monitor_producer/unittests/test_eventmon_config.cpp @@ -57,6 +57,7 @@ TEST_F(ConfigTests, ReadSettingsOK) { test_config.asapo_endpoint = "uri:001"; test_config.mode = asapo::RequestHandlerType::kTcp; test_config.monitored_folders={"test1","test2"}; + test_config.ignored_extentions={"tmp","test"}; auto err = asapo::SetFolderMonConfig(test_config); auto config = asapo::GetEventMonConfig(); @@ -69,6 +70,7 @@ TEST_F(ConfigTests, ReadSettingsOK) { ASSERT_THAT(config->asapo_endpoint, Eq("uri:001")); ASSERT_THAT(config->mode, Eq(asapo::RequestHandlerType::kTcp)); ASSERT_THAT(config->monitored_folders, ElementsAre("test1","test2")); + ASSERT_THAT(config->ignored_extentions, ElementsAre("tmp","test")); } diff --git a/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp b/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp index 868a9a6bbe4efce6e8df4b35dd6bdfa741d7efd8..df73f8aaf48aa67d93f8543b1f2ed859f4e7b7b3 100644 --- a/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp +++ b/producer/event_monitor_producer/unittests/test_folder_event_detector.cpp @@ -28,7 +28,8 @@ using ::asapo::Error; using ::asapo::FileDescriptor; using ::asapo::ErrorInterface; using asapo::FileEvents; - +using asapo::FileEvent; +using asapo::EventType; using asapo::FolderEventDetector; namespace { @@ -48,6 +49,11 @@ class FolderEventDetectorTests : public testing::Test { asapo::EventMonConfig test_config; FolderEventDetector detector{&test_config}; std::vector<std::string> expected_folders{"test1","test2"}; + FileEvent expected_event1{EventType::closed,10,"test1.dat"}; + FileEvent expected_event2{EventType::renamed_to,11,"test2.dat"}; + FileEvent expected_event3{EventType::renamed_to,11,"test3.tmp"}; + FileEvent expected_event4{EventType::closed,12,"test4.tmp"}; + FileEvents expected_events{expected_event1,expected_event2,expected_event3,expected_event4}; void SetUp() override { test_config.monitored_folders = expected_folders; err = nullptr; @@ -57,8 +63,9 @@ class FolderEventDetectorTests : public testing::Test { detector.system_folder_watch__.release(); } void MockStartMonitoring(); - - }; + void MockGetEvents(); + void InitiateAndReadSingleEvent(); +}; void FolderEventDetectorTests::MockStartMonitoring() { EXPECT_CALL(mock_system_folder_watch, StartFolderMonitor_t(expected_folders)) @@ -124,43 +131,97 @@ TEST_F(FolderEventDetectorTests, GetNextCallsSystemGetNextFirstTimeNoEvents) { TEST_F(FolderEventDetectorTests, GetNextEventError) { MockStartMonitoring(); - asapo::EventHeader event_header; EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).WillOnce( DoAll( SetArgPointee<0>(asapo::EventMonitorErrorTemplates::kSystemError.Generate().release()), Return(FileEvents{}) )); - - detector.StartMonitoring(); + asapo::EventHeader event_header; auto err = detector.GetNextEvent(&event_header); ASSERT_THAT(err, Eq(asapo::EventMonitorErrorTemplates::kSystemError)); } - -TEST_F(FolderEventDetectorTests, GetNextEventOK) { - MockStartMonitoring(); - asapo::EventHeader event_header; +void FolderEventDetectorTests::MockGetEvents(){ EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).WillOnce( DoAll( SetArgPointee<0>(nullptr), - Return(FileEvents{asapo::FileEvent{asapo::EventType::closed,10,"test"}}) + Return(expected_events) )); +} +void FolderEventDetectorTests::InitiateAndReadSingleEvent() { + MockStartMonitoring(); + MockGetEvents(); + detector.StartMonitoring(); + asapo::EventHeader event_header; + detector.GetNextEvent(&event_header); + Mock::VerifyAndClearExpectations(&mock_system_folder_watch); +}; +TEST_F(FolderEventDetectorTests, GetNextEventOK) { + MockStartMonitoring(); + MockGetEvents(); + detector.StartMonitoring(); + asapo::EventHeader event_header; auto err = detector.GetNextEvent(&event_header); - ASSERT_THAT(err, Eq(nullptr)); - ASSERT_THAT(event_header.file_name, Eq("test")); + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(event_header.file_name, Eq("test1.dat")); ASSERT_THAT(event_header.file_size, Eq(10)); +} + + +TEST_F(FolderEventDetectorTests, GetNextEventDoesDoSystemCallIfListNotEmpty) { + InitiateAndReadSingleEvent(); + + EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).Times(0); + + + asapo::EventHeader event_header; + auto err = detector.GetNextEvent(&event_header); + + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(event_header.file_name, Eq("test2.dat")); + ASSERT_THAT(event_header.file_size, Eq(11)); +} + + +TEST_F(FolderEventDetectorTests, GetNextEventDoesSystemCallIfListEmpty) { + InitiateAndReadSingleEvent(); + EXPECT_CALL(mock_system_folder_watch, GetFileEventList_t(_)).Times(1); + +// read events 2 to 4 + asapo::EventHeader event_header; + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(nullptr)); + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(nullptr)); + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(nullptr)); +// read events - should initiate system call since the buffer is empty now + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(asapo::EventMonitorErrorTemplates::kNoNewEvent)); } +TEST_F(FolderEventDetectorTests, GetNextIgnoresTmpFiles) { + test_config.ignored_extentions={"tmp"}; + InitiateAndReadSingleEvent(); + asapo::EventHeader event_header; + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(nullptr)); + ASSERT_THAT(event_header.file_name, Eq("test2.dat")); + +// try read event 3 test3.tmp sould be ignored + err = detector.GetNextEvent(&event_header); + ASSERT_THAT(err, Eq(asapo::EventMonitorErrorTemplates::kNoNewEvent)); +} }