Kea 2.7.5
|
Abstract interface for sending NameChangeRequests. More...
#include <ncr_io.h>
Classes | |
class | RequestSendHandler |
Abstract class for defining application layer send callbacks. More... | |
Public Types | |
typedef boost::shared_ptr< RequestSendHandler > | RequestSendHandlerPtr |
Defines a smart pointer to an instance of a request send handler. | |
enum | Result { SUCCESS , TIME_OUT , STOPPED , ERROR } |
Defines the outcome of an asynchronous NCR send. More... | |
typedef std::deque< NameChangeRequestPtr > | SendQueue |
Defines the type used for the request send queue. | |
Public Member Functions | |
NameChangeSender (RequestSendHandlerPtr send_handler, size_t send_queue_max=MAX_QUEUE_DEFAULT) | |
Constructor. | |
virtual | ~NameChangeSender () |
Destructor. | |
bool | amSending () const |
Returns true if the sender is in send mode, false otherwise. | |
void | assumeQueue (NameChangeSender &source_sender) |
Move all queued requests from a given sender into the send queue. | |
void | clearSendQueue () |
Flushes all entries in the send queue. | |
size_t | getQueueMaxSize () const |
Returns the maximum number of entries allowed in the send queue. | |
size_t | getQueueSize () const |
Returns the number of entries currently in the send queue. | |
virtual int | getSelectFd ()=0 |
Returns a file descriptor suitable for use with select. | |
virtual bool | ioReady ()=0 |
Returns whether or not the sender has IO ready to process. | |
bool | isSendInProgress () const |
Returns true when a send is in progress. | |
const NameChangeRequestPtr & | peekAt (const size_t index) const |
Returns the entry at a given position in the queue. | |
virtual void | runReadyIO () |
Processes sender IO events. | |
void | sendRequest (NameChangeRequestPtr &ncr) |
Queues the given request to be sent. | |
void | setQueueMaxSize (const size_t new_max) |
Sets the maximum queue size to the given value. | |
void | skipNext () |
Removes the request at the front of the send queue. | |
void | startSending (const isc::asiolink::IOServicePtr &io_service) |
Prepares the IO for transmission. | |
void | stopSending () |
Closes the IO sink and stops send logic. | |
Static Public Attributes | |
static const size_t | MAX_QUEUE_DEFAULT = 1024 |
Defines a default maximum number of entries in the send queue. | |
Protected Member Functions | |
virtual void | close ()=0 |
Abstract method which closes the IO sink. | |
virtual void | doSend (NameChangeRequestPtr &ncr)=0 |
Initiates an IO layer asynchronous send. | |
SendQueue & | getSendQueue () |
Returns a reference to the send queue. | |
void | invokeSendHandler (const NameChangeSender::Result result) |
Calls the NCR send completion handler registered with the sender. | |
virtual void | open (const isc::asiolink::IOServicePtr &io_service)=0 |
Abstract method which opens the IO sink for transmission. | |
void | sendNext () |
Dequeues and sends the next request on the send queue in a thread safe context. | |
Protected Attributes | |
asiolink::IOServicePtr | io_service_ |
Pointer to the IOService currently being used by the sender. | |
Abstract interface for sending NameChangeRequests.
NameChangeSender provides the means to:
It implements the high level logic flow to queue requests for delivery, and ship them one at a time, waiting for the send to complete prior to sending the next request in the queue. If a send fails, the request will remain at the front of queue and the send will be retried endlessly unless the caller dequeues the request. Note, it is presumed that a send failure is some form of IO error such as loss of connectivity and not a message content error. It should not be possible to queue an invalid message.
It should be noted that once a request is placed onto the send queue it will remain there until one of three things occur:
NameChangeSender::skipNext()
is calledNameChangeSender::clearSendQueue()
is calledThe queue contents are preserved across start and stop listening transitions. This is to provide for error recovery without losing undelivered requests. It provides virtual methods so derivations may supply implementations to open the appropriate IO sink, perform a send, and close the IO sink.
The overall design is based on a callback chain. The sender's caller (the application) supplies an "application" layer callback through which it will be given send completion notifications. The sender derivation will employ its own callback at the IO layer to process send events from its IO sink. This callback is expected to forward the outcome of each asynchronous send to the application layer by invoking the application layer callback registered with the sender.
The application layer callback is structured around a nested class, RequestSendHandler. It consists of single, abstract operator() which accepts a result code and a pointer to a NameChangeRequest as parameters. In order to receive send completion notifications, a caller implements a derivation of the RequestSendHandler and supplies an instance of this derivation to the NameChangeSender constructor. This "registers" the handler with the sender.
To begin sending, the caller invokes the listener's startSending() method, passing in an IOService instance. This in turn will pass the IOService into the virtual method, open(). The open method is where the sender derivation performs the steps necessary to prepare its IO sink for output (e.g. opening a socket, connecting to a database). At this point, the sender is ready to send messages.
In order to send a request, the application layer invokes the sender method, sendRequest(), passing in the NameChangeRequest to send. This method places the request onto the back of the send queue, and then invokes the sender method, sendNext().
If there is already a send in progress when sendNext() is called, the method will return immediately rather than initiate the next send. This is to ensure that sends are processed sequentially.
If there is not a send in progress and the send queue is not empty, the sendNext method will pass the NCR at the front of the send queue into the virtual doSend() method.
The sender derivation uses this doSend() method to instigate an IO layer asynchronous send with its IO layer callback to handle send events from its IO sink.
As stated earlier, the derivation's IO layer callback MUST invoke the application layer handler registered with the sender. This is done by passing in a status indicating the outcome of the send into the sender's invokeSendHandler method. This is the mechanism by which the sender's caller is handed outbound notifications. After invoking the application layer handler, the invokeSendHandler method will call the sendNext() method to initiate the next send. This ensures that requests continue to dequeue and ship.
typedef boost::shared_ptr<RequestSendHandler> isc::dhcp_ddns::NameChangeSender::RequestSendHandlerPtr |
typedef std::deque<NameChangeRequestPtr> isc::dhcp_ddns::NameChangeSender::SendQueue |
isc::dhcp_ddns::NameChangeSender::NameChangeSender | ( | RequestSendHandlerPtr | send_handler, |
size_t | send_queue_max = MAX_QUEUE_DEFAULT ) |
Constructor.
send_handler | is a pointer the application layer handler to be invoked each time a NCR send attempt completes. |
send_queue_max | is the maximum number of entries allowed in the send queue. Once the maximum number is reached, all calls to sendRequest will fail with an exception. |
Definition at line 157 of file ncr_io.cc.
References setQueueMaxSize().
|
inlinevirtual |
|
inline |
Returns true if the sender is in send mode, false otherwise.
A true value indicates that the IO sink has been opened successfully, and that send loop logic is active.
Definition at line 738 of file ncr_io.h.
Referenced by assumeQueue(), clearSendQueue(), isc::dhcp_ddns::NameChangeUDPSender::getSelectFd(), sendRequest(), and startSending().
void isc::dhcp_ddns::NameChangeSender::assumeQueue | ( | NameChangeSender & | source_sender | ) |
Move all queued requests from a given sender into the send queue.
Moves all of the entries in the given sender's queue and places them into send queue. This provides a mechanism of reassigning queued messages from one sender to another. This is useful for dealing with dynamic configuration changes.
source_sender | from whom the queued messages will be taken |
NcrSenderError | if either sender is in send mode, if the number of messages in the source sender's queue is larger than this sender's maximum queue size, or if this sender's queue is not empty. |
Definition at line 453 of file ncr_io.cc.
References amSending(), getQueueMaxSize(), isc::util::MultiThreadingMgr::instance(), and isc_throw.
void isc::dhcp_ddns::NameChangeSender::clearSendQueue | ( | ) |
Flushes all entries in the send queue.
This method can be used to discard all of the NCRs currently in the the send queue. Note it may not be called while the sender is in the sending state.
NcrSenderError | if called and sender is in sending state. |
Definition at line 382 of file ncr_io.cc.
References amSending(), isc::util::MultiThreadingMgr::instance(), and isc_throw.
|
protectedpure virtual |
Abstract method which closes the IO sink.
The derivation uses this method to perform the steps needed to "close" the IO sink.
If | the implementation encounters an error it MUST throw it as an isc::Exception or derivative. |
Implemented in isc::dhcp_ddns::NameChangeUDPSender.
Referenced by stopSending().
|
protectedpure virtual |
Initiates an IO layer asynchronous send.
The derivation uses this method to perform the steps needed to initiate an asynchronous send through the IO sink of the given NCR.
ncr | is a pointer to the NameChangeRequest to send. derivation's IO layer handler as the IO completion callback. |
If | the implementation encounters an error it MUST throw it as an isc::Exception or derivative. |
Implemented in isc::dhcp_ddns::NameChangeUDPSender.
Referenced by sendNext().
|
inline |
Returns the maximum number of entries allowed in the send queue.
Definition at line 753 of file ncr_io.h.
Referenced by assumeQueue().
size_t isc::dhcp_ddns::NameChangeSender::getQueueSize | ( | ) | const |
Returns the number of entries currently in the send queue.
Definition at line 406 of file ncr_io.cc.
References isc::util::MultiThreadingMgr::instance().
|
pure virtual |
Returns a file descriptor suitable for use with select.
The value returned is an open file descriptor which can be used with select() system call to monitor the sender for IO events. This allows NameChangeSenders to be used in applications which use select, rather than IOService to wait for IO events to occur.
NcrSenderError | if the sender is not in send mode, |
Implemented in isc::dhcp_ddns::NameChangeUDPSender.
Definition at line 488 of file ncr_io.cc.
References isc_throw.
|
inlineprotected |
|
protected |
Calls the NCR send completion handler registered with the sender.
This is the hook by which the sender's caller's NCR send completion handler is called. This method MUST be invoked by the derivation's implementation of doSend. Note that if the send was a success, the entry at the front of the queue is removed from the queue. If not we leave it there so we can retry it. After we invoke the handler we clear the pending ncr value and queue up the next send.
NOTE: The handler invoked by this method MUST NOT THROW. The handler is application level logic and should trap and handle any errors at that level, rather than throw exceptions. If IO errors have occurred prior to invoking the handler, they are expressed in terms a failed result being passed to the handler. Therefore any exceptions at the handler level are application issues and should be dealt with at that level.
This method does wrap the handler invocation within a try-catch block as a fail-safe. The exception will be logged but the send logic will continue. What this implies is that continued operation may or may not succeed as the application has violated the interface contract.
result | contains that send outcome status. |
Definition at line 303 of file ncr_io.cc.
References isc::util::MultiThreadingMgr::instance().
Referenced by isc::dhcp_ddns::NameChangeUDPSender::sendCompletionHandler().
|
pure virtual |
Returns whether or not the sender has IO ready to process.
Implemented in isc::dhcp_ddns::NameChangeUDPSender.
Referenced by stopSending().
bool isc::dhcp_ddns::NameChangeSender::isSendInProgress | ( | ) | const |
Returns true when a send is in progress.
A true value indicates that a request is actively in the process of being delivered.
Definition at line 443 of file ncr_io.cc.
References isc::util::MultiThreadingMgr::instance().
|
protectedpure virtual |
Abstract method which opens the IO sink for transmission.
The derivation uses this method to perform the steps needed to prepare the IO sink to send requests.
io_service | is the IOService that process IO events. |
If | the implementation encounters an error it MUST throw it as an isc::Exception or derivative. |
Implemented in isc::dhcp_ddns::NameChangeUDPSender.
const NameChangeRequestPtr & isc::dhcp_ddns::NameChangeSender::peekAt | ( | const size_t | index | ) | const |
Returns the entry at a given position in the queue.
Note that the entry is not removed from the queue.
index | the index of the entry in the queue to fetch. Valid values are 0 (front of the queue) to (queue size - 1). |
NcrSenderError | if the given index is beyond the end of the queue. |
Definition at line 421 of file ncr_io.cc.
References isc::util::MultiThreadingMgr::instance().
|
virtual |
Processes sender IO events.
Executes at most one ready handler on the sender's IO service. If no handlers are ready it returns immediately.
NameChangeSender daisy chains requests together in its completion by one message completion's handler initiating the next message's send. When using UDP, a send immediately marks its event handler as ready to run. If this occurs inside a call to ioservice::poll() or run(), that event will also be run. If that handler calls UDP send then that send's handler will be marked ready and executed and so on. If there were 1000 messages in the queue then all them would be sent from within the context of one call to runReadyIO(). By running only one handler at time, we ensure that NCR IO activity doesn't starve other processing. It is unclear how much of a real threat this poses but for now it is best to err on the side of caution.
Definition at line 493 of file ncr_io.cc.
References io_service_, and isc_throw.
Referenced by stopSending().
|
protected |
Dequeues and sends the next request on the send queue in a thread safe context.
If there is already a send in progress just return. If there is not a send in progress and the send queue is not empty the grab the next message on the front of the queue and call doSend().
Definition at line 280 of file ncr_io.cc.
References doSend().
void isc::dhcp_ddns::NameChangeSender::sendRequest | ( | NameChangeRequestPtr & | ncr | ) |
Queues the given request to be sent.
The given request is placed at the back of the send queue and then sendNext is invoked.
ncr | is the NameChangeRequest to send. |
NcrSenderError | if the sender is not in sending state or the request is empty; NcrSenderQueueFull if the send queue has reached capacity. |
Definition at line 247 of file ncr_io.cc.
References amSending(), isc::util::MultiThreadingMgr::instance(), and isc_throw.
void isc::dhcp_ddns::NameChangeSender::setQueueMaxSize | ( | const size_t | new_max | ) |
Sets the maximum queue size to the given value.
Sets the maximum number of entries allowed in the queue to the the given value.
new_max | the new value to use as the maximum |
NcrSenderError | if the value is less than one. |
Definition at line 396 of file ncr_io.cc.
References isc_throw.
Referenced by NameChangeSender().
void isc::dhcp_ddns::NameChangeSender::skipNext | ( | ) |
Removes the request at the front of the send queue.
This method can be used to avoid further retries of a failed send. It is provided primarily as a just-in-case measure. Since a failed send results in the same request being retried continuously this method makes it possible to remove that entry, causing the subsequent entry in the queue to be attempted on the next send. It is presumed that sends will only fail due to some sort of communications issue. In the unlikely event that a request is somehow tainted and causes an send failure based on its content, this method provides a means to remove the message.
Definition at line 364 of file ncr_io.cc.
References isc::util::MultiThreadingMgr::instance().
void isc::dhcp_ddns::NameChangeSender::startSending | ( | const isc::asiolink::IOServicePtr & | io_service | ) |
Prepares the IO for transmission.
Calls the derivation's open implementation to initialize the IO layer sink for sending outbound requests.
io_service | is the IOService that will handle IO event processing. |
NcrSenderError | if the sender is already "sending" or NcrSenderOpenError if the open fails. |
Definition at line 167 of file ncr_io.cc.
References amSending(), isc::util::MultiThreadingMgr::instance(), isc_throw, stopSending(), and isc::Exception::what().
void isc::dhcp_ddns::NameChangeSender::stopSending | ( | ) |
Closes the IO sink and stops send logic.
Calls the derivation's implementation of close and marks the state as not sending.
Definition at line 204 of file ncr_io.cc.
References close(), isc::dhcp_ddns::dhcp_ddns_logger, isc::dhcp_ddns::DHCP_DDNS_NCR_FLUSH_IO_ERROR, isc::dhcp_ddns::DHCP_DDNS_NCR_SEND_CLOSE_ERROR, io_service_, ioReady(), LOG_ERROR, and runReadyIO().
Referenced by isc::dhcp_ddns::NameChangeUDPSender::~NameChangeUDPSender(), and startSending().
|
protected |
Pointer to the IOService currently being used by the sender.
Definition at line 833 of file ncr_io.h.
Referenced by isc::dhcp_ddns::NameChangeUDPSender::open(), runReadyIO(), and stopSending().
|
static |