diff --git a/doc/design/dispatch b/doc/design/dispatch new file mode 100644 index 0000000000..72e95b5183 --- /dev/null +++ b/doc/design/dispatch @@ -0,0 +1,140 @@ +UDP receive: + +/* + * General flow: + * + * If I/O result == CANCELED, free the buffer and notify everyone as + * the various queues drain. + * + * If I/O is error (not canceled and not success) log it, free the buffer, + * and restart. + * + * If query: + * if no listeners: free the buffer, restart. + * if listener: allocate event, fill in details. + * If cannot allocate, free buffer, restart. + * if rq event queue is not empty, queue. else, send. + * restart. + * + * If response: + * Allocate event, fill in details. + * If cannot allocate, free buffer, restart. + * find target. If not found, free buffer, restart. + * if event queue is not empty, queue. else, send. + * restart. + */ + + +UDP restart: + +/* + * If too many recv()'s are already running, just return. + * + * If noone is attached to us, just return. + * + * Allocate a new buffer to receive into. + * If no more buffers: + * If there are buffers handed out: wait for one to come back. + * If there are no buffers handed out: + * If there are responses attached to us, just return. + * If there are queries only, send one an error event. + * + * + * start recv() on socket. If this fails: + * Free buffer. + * Set dispatch state to "shutting down" and why to "socket error" + * Start failsafe shutdown. + */ + + +Adding a response: + +/* + * If shutting down, return error. + * + * Allocate an unique messageid and return it. If none can be allocated, + * return that. + * + * Allocate a new structure and fill it in. If no memory, return that. + * + * Insert into the correct linked list. + * + * If the receiver is not running, try to start it. + */ + +Adding a request: + +/* + * If shutting down, return error. + * + * Allocate new structure and fill it in. If no memory, return that. + * + * Insert it into the linked list. + * + * If the incoming query packet queue is not empty, pull an item off and + * send that event to this task. + * + * If the receiver is not running, try to start it. + */ + +Detaching a response: + +/* + * decrement dispatch reference count by one. If zero, remember to kill it + * later. + * + * unlink the response from the hashed list. + * + * Free any buffers and events attached to the response structure. + * + * Free the response structure. + * + * If an event is also being returned, jump to "internal event free" below. + * + * If the ref count became zero above, destroy this dispatch fully, and return. + * + * If the receiver is not running, try to start it. + */ + +Detaching a request: + +/* + * decrement dispatch ref count by one. If zero, remember to kill it later. + * + * unlink from the request list. + * + * Free the response structure. + * + * If an event is also being returned, jump to "internal event free" below. + * + * If the ref count became zero above, destroy the dispatch fully, and return. + * + * If the receiver is not running, try to start it. + */ + +Internal event free (from library space): + +/* + * If it is the failsafe event, send it to the next response/request on the + * dispatcher, and return. + * + * Free buffer. + * + * Free event. + */ + +Returning an event (from application space): + +/* + * If it is the failsafe event, die. + * + * Free associated buffer. + * + * Free event. + * + * If response: do next response on this response's queue, if any. + * If request: do next request on this dispatcher's queue, if any. + * + * If the receiver is not running, try to start it. + */ +