ENT-14195 2. cf-reactor data structure and polling - #6354
Open
victormlg wants to merge 2 commits into
Open
Conversation
Signed-off-by: Victor Moene <victor.moene@northern.tech>
Signed-off-by: Victor Moene <victor.moene@northern.tech>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Spec
In order to track all the events promises, we use two datastructures: a global list of
"Watcher", which is a struct associated with an event type and the promise name (also calledkey) and a global hashmap mapping thiskeyto abundlewhich is parsed from the policy.On an agent run, cf-agent makes cf-reactor read the policy, and rebuilds the list of watchers and the hashmap using the single function
WatcherRegister(key, event_type, payload, bundle, interval). Each events promise is associated with an event type, which is defined inwhenbodies:Every event type is must have defined:
check_fninWatcher): This is a function defined specifically for the event that checks if the conditions holds. For example, in case of file deletion, we check if the file doesn't exist anymore compare to the last time we checked. If yes, then it returnstrue."payload"): This is a struct whose interpretation depends on the event type (thus being declared asvoid *). We typically need some state that we compare between each event-check. In the case of file deletion, we need to know the name of the file we are watching, and whether the file existed last time we checked.destroy_payload): This is simply a function to free the state associated with the event type.Polling
ReactorContextInitialize()sets up all the necessary data structures for polling, and then startsWatcherThreadMain, which polls for events as follows:interval, it runscheck_fnto determine whether an event has been triggered.key(the promise name) onto a thread-safe queue, then signals the file descriptor viaWakeupChannelNotify, whichselect(2)will pick up on its next iteration. It then goes back to sleep.In parallel,
EventWatcherHandleEvents, called from withinReactorContextHandleEvents, reads from the file descriptor withWakeupChannelReadFd()once notified that an event has occurred, and pops the thread-safe queue until it's empty. Each key popped from the queue is looked up in the global hashmap to retrieve the corresponding bundle, whichcf-reactorthen runs (in another thread or subprocess)