Auto-tools/Projects/SUTAgentImplementation: Difference between revisions

(Created page with "= Overall Design = The SUTAgent must handle multiple connections and concurrent events. It is expected, however, that often only one or two connections will be established. Thre...")
 
 
Line 13: Line 13:
== BufferedSocket ==
== BufferedSocket ==


BufferedSocket is just a wrapper around a socket that allows buffering in userspace. Significantly, it supports an unget() method that can return data to the buffer, in case a handler overreads.
BufferedSocket is just a wrapper around a socket that allows buffering in userspace.


== Reactor ==
== Reactor ==
Line 24: Line 24:


An abstract class with three functions, all used by the Reactor:
An abstract class with three functions, all used by the Reactor:
* get_handles(): returns any events for which the handler would like notifications
* getPollDescs(): returns any descriptors for which the handler would like notifications
* handle_events(): takes a list of events for which the Reactor received a notification in the last iteration. The Handler does application-specific processing here. This function returns 'true' if the EventHandler did anything with the data, or 'false' otherwise. This is used to see if the loop should iterate again before going back to waiting for events (when all EventHandlers' handle_events() return false).
* handleEvent(): takes a list of events for which the Reactor received a notification in the last iteration. The Handler does application-specific processing here.
* closed(): indicates if a handler is finished, which means it should be deleted by the Reactor (or proxy, see below).
* closed(): indicates if a handler is finished, which means it should be deleted by the Reactor (or proxy, see below).


== SocketAcceptorEventHandler ==
== SocketAcceptorEventHandler ==


An EventHandler that listens for connections on the given socket and creates BufferedSockets and SessionEventHandlers, passing the latter to the Reactor.
An EventHandler that listens for connections on the given socket and creates CommandEventHandlers, adding them to the Reactor.


== SessionEventHandler ==
== CommandEventHandler ==
 
A SessionEventHandler represents one session, e.g. the duration of a connection. Because connections can have two states--commands and data--it is essentially a proxy to a stack of EventHandlers, which will normally be one or two. It redirects all requests for handles and event notifications to the top-most EventHandler. It also maintains any session state, such as the current working directory.
 
When created, it immediately creates a CommandEventHandler and pushes it into the EventHandler stack. The CommandEventHandler takes a pointed to the SessionEventHandler so that it can alter the current working directory and push other EventHandlers onto its stack.
 
Its handle_events() implementation passes the notifications onto the top-most EventHandler on its stack. It also flushes the BufferedSocket output buffer, if needed.


Similarly, its get_handles() implementation returns the handles from the top-most EventHandler on its stack. It also adds a write event for the BufferedSocket, if there is buffered, unsent data.
A CommandEventHandler represents one session, e.g. the duration of a connection. Because connections can have two states--commands and data--it may act as a proxy to another EventHandler, for potentially long-running commands like 'push' or 'pull' that require some state.


If it detects that an EventHandler is closed, it deletes it. When the stack is empty, and all buffered data has been sent, it closes itself so that the Reactor can delete it.
Its handleEvent() implementation either reads a line and passes it to handleLine(), if in command mode, or just passes the event to the data event handler. It also flushes the BufferedSocket output buffer, if needed.
 
== CommandEventHandler ==


Looks for socket read events, and reads a line from the socket, breaks it up into command and arguments, and services the command. For shorter commands, it writes the response directly to the BufferedSocket (which may cause it to be buffered, in which case the SessionEventHandler is responsible for flushing). For longer commands, it pushes a new EventHandler onto the stack. In any case, if it reads more than a line of data, it unget()s the extra data.
Similarly, its getPollDescs() implementation returns either just a read event for the socket, if in command mode, or collects descriptors from the data event handler. It also adds a write event for the BufferedSocket, if there is buffered, unsent data.


== DataEventHandler ==
== PushFileEventHandler / PullFileEventHandler ==


Represents a data stream. Used for push and pull commands. Maintains some state, i.e. how much of the file has been received or sent. When finished, closes itself, so that the SessionEventHandler pops it off the stack and deletes it, returning to regular command processing. As with the CommandEventHandler, if it reads too much data, it unget()s the extra data.
Represents a data stream. Used for push and pull commands. Maintains some state, i.e. how much of the file has been received or sent. When finished, closes itself, so that the CommandEventHandler deletes it, returning to regular command processing.


== SubprocessEventHandler ==
== SubprocessEventHandler ==


Represents a subprocess. Its get_handles() just returns a timeout, since, for platform-independence, we have to poll subprocesses to determine when they are complete. It may also write data to the BufferedSocket. It is expected that this will have to be subclassed for each platform and probably created via a platform-specific factory object. When the process exits, this EventHandler closes, so that the SessionEventHandler can return to command processing.
Represents a subprocess. Its getPollDescs() just returns a timeout, since, for platform-independence, we have to poll subprocesses to determine when they are complete. It may also write data to the BufferedSocket. It is expected that this will have to be subclassed for each platform and probably created via a platform-specific factory object. When the process exits, this EventHandler closes, so that the CommandEventHandler can delete it and return to command processing.
Confirmed users
1,927

edits