-
-
Couldn't load subscription status.
- Fork 12
file_monitor_analysis.md
Mohamed edited this page Jun 10, 2025
·
1 revision
-
Location:
example/core_io/file_monitor/ -
Objective: This example demonstrates how to build a real-time file system monitoring application using QB actors. It showcases how to leverage
qb-io's asynchronous file watching capabilities to detect changes (creations, modifications, deletions) in specified directories and process these events through a pipeline of actors.
By examining this example, you will learn about:
- Integrating asynchronous file/directory watching (
qb::io::async::directory_watcher) into an actor. - Designing an event-driven workflow triggered by file system events.
- Separating concerns: watching, processing, and client interaction into distinct actors.
- Using custom events for robust inter-actor communication.
- Employing
qb::io::async::callbackfor simulating external interactions or periodic tasks within an actor.
The file_monitor example is structured around three main actor types:
-
Headers:
watcher.h,watcher.cpp - Core Assignment (Typical): Core 0 (often suitable for I/O-bound tasks like file watching).
- Role: The primary component responsible for monitoring specified directory paths for any changes to files or subdirectories.
-
QB Integration & Internal Mechanism:
- Inherits from
qb::Actor. - It internally manages one or more instances of a helper class,
DirectoryMonitor(also defined inwatcher.h/.cpp). - Each
DirectoryMonitorinstance inherits fromqb::io::async::directory_watcher<DirectoryMonitor>, which is a CRTP base class fromqb-io. This base class useslibev'sev_statwatchers to poll for attribute changes on the specified path.
- Inherits from
-
Request Handling:
-
on(WatchDirectoryRequest&): When this event is received (typically fromClientActor), theDirectoryWatcherinitiates monitoring for the requested path. It stores therequestor'sActorIdas a subscriber for events from this path. If recursive watching is requested, it will also set up watchers for subdirectories. -
on(UnwatchDirectoryRequest&): Stops monitoring a previously watched path for a given subscriber.
-
-
Event Detection & Propagation:
- The
DirectoryMonitor::on(qb::io::async::event::file const& os_event)method is invoked by theqb-ioevent loop (listener::current) when the OS (viaev_stat) detects a change in a monitored file or directory's attributes (e.g., size, modification time, link count). - This handler analyzes
os_event.attr(current stat data) andos_event.prev(previous stat data) to determine the nature of the change, categorizing it into aFileEventType(e.g.,CREATED,MODIFIED,DELETED,ATTRIBUTES_CHANGED). - The
DirectoryWatcherthen calls itspublishFileEventmethod. This method identifies all actors subscribed to the affected path andpushes an application-levelFileEvent(containing the path andFileEventType) to each of them.
- The
-
Recursion & State: Manages a tree-like structure (
WatchInfo) to handle recursive directory watching and track subscribers per path.
-
Headers:
processor.h,processor.cpp - Core Assignment (Typical): Core 1 (separating processing logic from I/O watching).
-
Role: Receives
FileEventnotifications from theDirectoryWatcherand performs application-specific actions based on these events. -
QB Integration: Standard
qb::Actor. -
State Management: Maintains a
_tracked_filesmap (std::map<std::string, FileMetadata>) to store information about files it's aware of, such as path, size, content hash, and last modification time. - **Event Handling (
on(FileEvent&)):- This is the primary entry point for this actor.
- Based on
event.event_type, it dispatches to internal methods likeprocessFileCreated,processFileModified, orprocessFileDeleted.
-
Processing Logic:
-
processFileCreated: Adds new file metadata to_tracked_files, potentially calculates an initial hash. -
processFileModified: Updates metadata for an existing file, recalculates hash if content likely changed (e.g., size or mtime differs). -
processFileDeleted: Removes the file from_tracked_files. -
extractMetadata(): A helper that usesqb::io::sys::filefor synchronous read operations to get file size and potentiallyqb::crypto::md5(or another hash) for content hashing. Note: If hashing large files, this synchronous read could block. In a production system, this might be offloaded to anasync::callbackor a dedicated hashing worker actor if performance is critical. - Logs detected changes to the console.
-
-
Configuration & Stats: Also handles
SetProcessingConfigRequest(e.g., to toggle processing of hidden files) andGetProcessingStatsRequest(replying withMonitoringStats).
-
Header:
main.cpp(defined within) -
Core Assignment (Typical): Core 0 (can co-exist with
DirectoryWatcherfor this example). -
Role: Simulates a client application that uses the file monitoring service. It also actively creates, modifies, and deletes files in a test directory to generate file system events for the
DirectoryWatcherto pick up. -
QB Integration: Standard
qb::Actor. -
Interaction Flow:
-
onInit(): Sends aWatchDirectoryRequestto theDirectoryWatcherto start monitoring a specified_test_directory. -
on(WatchDirectoryResponse&): Receives confirmation that watching has started. It then begins its file manipulation tests. -
File Operations (via
qb::io::async::callback): Usesqb::io::async::callbackto schedule a sequence of file operations (createTestFile,modifyTestFile,deleteTestFile). These methods usestd::filesystem(orqb::io::sys::filefor content) to perform actual file system modifications. Usingasync::callbackensures these potentially blocking OS calls don't stall theClientActor'sVirtualCore. -
on(FileEvent&): ReceivesFileEventnotifications from theDirectoryWatcherin response to its own file operations (and any other changes) and logs them. -
Shutdown: Manages a test duration. After the duration, it
broadcast<qb::KillEvent>()to stop all actors and sends anUnwatchDirectoryRequestin its ownon(qb::KillEvent&)handler.
-
-
Asynchronous File System Watching: Demonstrates the practical application of
qb::io::async::directory_watcher(via theDirectoryMonitorhelper) integrated within an actor (DirectoryWatcher) to react to OS-level file system notifications without blocking. -
Event-Driven Pipeline: Shows a clear flow: OS file system event ->
qb::io::async::event::file->DirectoryMonitor->DirectoryWatcher(transforms toFileEvent) ->FileProcessor. -
Separation of Concerns: Responsibilities are well-defined:
-
DirectoryWatcher: Low-level OS interaction and event detection/filtering. -
FileProcessor: Application-specific logic based on file events. -
ClientActor: User interaction, simulation, and system orchestration for the demo.
-
-
Custom Event Types: Effective use of application-specific events (
WatchDirectoryRequest,FileEvent,SetProcessingConfigRequest, etc.) for clear and type-safe communication between actors. -
Asynchronous Task Execution in Actors: The
ClientActorusesqb::io::async::callbackto perform potentially blocking file creation/modification/deletion operations off its main event processing path, maintaining responsiveness. -
Resource Management (Watchers): The
DirectoryWatcheris responsible for creating (startWatching) and cleaning up (stopWatching) the underlyingDirectoryMonitorinstances, which in turn manage theev_statwatchers.
This example provides a solid blueprint for building applications that need to react to file system changes in a robust and asynchronous manner using the QB Actor Framework.
(Next Example Analysis: file_processor Example Analysis**)