Kea  1.9.9-git
isc::dhcp_ddns::NameChangeSender Class Referenceabstract

Abstract interface for sending NameChangeRequests. More...

#include <ncr_io.h>

+ Inheritance diagram for isc::dhcp_ddns::NameChangeSender:

Classes

class  RequestSendHandler
 Abstract class for defining application layer send callbacks. More...
 

Public Types

enum  Result { SUCCESS, TIME_OUT, STOPPED, ERROR }
 Defines the outcome of an asynchronous NCR send. More...
 
typedef std::deque< NameChangeRequestPtrSendQueue
 Defines the type used for the request send queue. More...
 

Public Member Functions

 NameChangeSender (RequestSendHandler &send_handler, size_t send_queue_max=MAX_QUEUE_DEFAULT)
 Constructor. More...
 
virtual ~NameChangeSender ()
 Destructor. More...
 
bool amSending () const
 Returns true if the sender is in send mode, false otherwise. More...
 
void assumeQueue (NameChangeSender &source_sender)
 Move all queued requests from a given sender into the send queue. More...
 
void clearSendQueue ()
 Flushes all entries in the send queue. More...
 
size_t getQueueMaxSize () const
 Returns the maximum number of entries allowed in the send queue. More...
 
size_t getQueueSize () const
 Returns the number of entries currently in the send queue. More...
 
virtual int getSelectFd ()=0
 Returns a file descriptor suitable for use with select. More...
 
virtual bool ioReady ()=0
 Returns whether or not the sender has IO ready to process. More...
 
bool isSendInProgress () const
 Returns true when a send is in progress. More...
 
const NameChangeRequestPtrpeekAt (const size_t index) const
 Returns the entry at a given position in the queue. More...
 
virtual void runReadyIO ()
 Processes sender IO events. More...
 
void sendRequest (NameChangeRequestPtr &ncr)
 Queues the given request to be sent. More...
 
void setQueueMaxSize (const size_t new_max)
 Sets the maximum queue size to the given value. More...
 
void skipNext ()
 Removes the request at the front of the send queue. More...
 
void startSending (isc::asiolink::IOService &io_service)
 Prepares the IO for transmission. More...
 
void stopSending ()
 Closes the IO sink and stops send logic. More...
 

Static Public Attributes

static const size_t MAX_QUEUE_DEFAULT = 1024
 Defines a default maximum number of entries in the send queue. More...
 

Protected Member Functions

virtual void close ()=0
 Abstract method which closes the IO sink. More...
 
virtual void doSend (NameChangeRequestPtr &ncr)=0
 Initiates an IO layer asynchronous send. More...
 
SendQueuegetSendQueue ()
 Returns a reference to the send queue. More...
 
void invokeSendHandler (const NameChangeSender::Result result)
 Calls the NCR send completion handler registered with the sender. More...
 
virtual void open (isc::asiolink::IOService &io_service)=0
 Abstract method which opens the IO sink for transmission. More...
 
void sendNext ()
 Dequeues and sends the next request on the send queue in a thread safe context. More...
 

Detailed Description

Abstract interface for sending NameChangeRequests.

NameChangeSender provides the means to:

  • Supply a callback to invoke upon completing the delivery of an NCR or a send error
  • Start sending using a given IOService instance to process events
  • Queue NCRs for delivery
  • Stop sending

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:

The 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.

Definition at line 466 of file ncr_io.h.

Member Typedef Documentation

Defines the type used for the request send queue.

Definition at line 470 of file ncr_io.h.

Member Enumeration Documentation

Defines the outcome of an asynchronous NCR send.

Enumerator
SUCCESS 
TIME_OUT 
STOPPED 
ERROR 

Definition at line 476 of file ncr_io.h.

Constructor & Destructor Documentation

isc::dhcp_ddns::NameChangeSender::NameChangeSender ( RequestSendHandler send_handler,
size_t  send_queue_max = MAX_QUEUE_DEFAULT 
)

Constructor.

Parameters
send_handleris a pointer the application layer handler to be invoked each time a NCR send attempt completes.
send_queue_maxis 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 160 of file ncr_io.cc.

References setQueueMaxSize().

+ Here is the call graph for this function:

virtual isc::dhcp_ddns::NameChangeSender::~NameChangeSender ( )
inlinevirtual

Destructor.

Definition at line 520 of file ncr_io.h.

Member Function Documentation

bool isc::dhcp_ddns::NameChangeSender::amSending ( ) const
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.

Returns
The send mode.

Definition at line 733 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.

Parameters
source_senderfrom whom the queued messages will be taken
Exceptions
NcrSenderErrorif 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 445 of file ncr_io.cc.

References amSending(), getQueueMaxSize(), getQueueSize(), isc::util::MultiThreadingMgr::instance(), and isc_throw.

+ Here is the call graph for this function:

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.

Exceptions
NcrSenderErrorif called and sender is in sending state.

Definition at line 374 of file ncr_io.cc.

References amSending(), isc::util::MultiThreadingMgr::instance(), and isc_throw.

+ Here is the call graph for this function:

virtual void isc::dhcp_ddns::NameChangeSender::close ( )
protectedpure virtual

Abstract method which closes the IO sink.

The derivation uses this method to perform the steps needed to "close" the IO sink.

Exceptions
Ifthe implementation encounters an error it MUST throw it as an isc::Exception or derivative.

Implemented in isc::dhcp_ddns::NameChangeUDPSender.

Referenced by stopSending().

virtual void isc::dhcp_ddns::NameChangeSender::doSend ( NameChangeRequestPtr ncr)
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.

Parameters
ncris a pointer to the NameChangeRequest to send. derivation's IO layer handler as the IO completion callback.
Exceptions
Ifthe implementation encounters an error it MUST throw it as an isc::Exception or derivative.

Implemented in isc::dhcp_ddns::NameChangeUDPSender.

Referenced by sendNext().

size_t isc::dhcp_ddns::NameChangeSender::getQueueMaxSize ( ) const
inline

Returns the maximum number of entries allowed in the send queue.

Returns
The queue maximum size.

Definition at line 748 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.

Returns
The queue size.

Definition at line 398 of file ncr_io.cc.

References isc::util::MultiThreadingMgr::instance().

Referenced by assumeQueue().

+ Here is the call graph for this function:

int isc::dhcp_ddns::NameChangeSender::getSelectFd ( )
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.

Warning
Attempting other use of this value may lead to unpredictable behavior in the sender.
Returns
Returns an "open" file descriptor
Exceptions
NcrSenderErrorif the sender is not in send mode,

Implemented in isc::dhcp_ddns::NameChangeUDPSender.

Definition at line 480 of file ncr_io.cc.

References isc_throw.

SendQueue& isc::dhcp_ddns::NameChangeSender::getSendQueue ( )
inlineprotected

Returns a reference to the send queue.

Returns
The send queue.

Definition at line 806 of file ncr_io.h.

void isc::dhcp_ddns::NameChangeSender::invokeSendHandler ( const NameChangeSender::Result  result)
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.

Parameters
resultcontains that send outcome status.

Definition at line 295 of file ncr_io.cc.

References isc::util::MultiThreadingMgr::instance().

Referenced by isc::dhcp_ddns::NameChangeUDPSender::sendCompletionHandler().

+ Here is the call graph for this function:

virtual bool isc::dhcp_ddns::NameChangeSender::ioReady ( )
pure virtual

Returns whether or not the sender has IO ready to process.

Returns
true if the sender has at IO ready, false otherwise.

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.

Returns
The send in progress flag.

Definition at line 435 of file ncr_io.cc.

References isc::util::MultiThreadingMgr::instance().

+ Here is the call graph for this function:

virtual void isc::dhcp_ddns::NameChangeSender::open ( isc::asiolink::IOService io_service)
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.

Parameters
io_serviceis the IOService that process IO events.
Exceptions
Ifthe 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.

Parameters
indexthe index of the entry in the queue to fetch. Valid values are 0 (front of the queue) to (queue size - 1).
Returns
Pointer reference to the queue entry.
Exceptions
NcrSenderErrorif the given index is beyond the end of the queue.

Definition at line 413 of file ncr_io.cc.

References isc::util::MultiThreadingMgr::instance().

+ Here is the call graph for this function:

void isc::dhcp_ddns::NameChangeSender::runReadyIO ( )
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.

Warning
- Running all ready handlers, in theory, could process all messages currently queued.

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.

Todo:
Trac# 3325 requests that asiolink::IOService provide a wrapper for poll().

Definition at line 485 of file ncr_io.cc.

References isc::asiolink::IOService::get_io_service(), and isc_throw.

Referenced by stopSending().

+ Here is the call graph for this function:

void isc::dhcp_ddns::NameChangeSender::sendNext ( )
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 272 of file ncr_io.cc.

References doSend().

+ Here is the call graph for this function:

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.

Parameters
ncris the NameChangeRequest to send.
Exceptions
NcrSenderErrorif the sender is not in sending state or the request is empty; NcrSenderQueueFull if the send queue has reached capacity.

Definition at line 239 of file ncr_io.cc.

References amSending(), isc::util::MultiThreadingMgr::instance(), and isc_throw.

+ Here is the call graph for this function:

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.

Parameters
new_maxthe new value to use as the maximum
Exceptions
NcrSenderErrorif the value is less than one.

Definition at line 388 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 356 of file ncr_io.cc.

References isc::util::MultiThreadingMgr::instance().

+ Here is the call graph for this function:

void isc::dhcp_ddns::NameChangeSender::startSending ( isc::asiolink::IOService io_service)

Prepares the IO for transmission.

Calls the derivation's open implementation to initialize the IO layer sink for sending outbound requests.

Parameters
io_serviceis the IOService that will handle IO event processing.
Exceptions
NcrSenderErrorif the sender is already "sending" or NcrSenderOpenError if the open fails.

Definition at line 170 of file ncr_io.cc.

References amSending(), isc::util::MultiThreadingMgr::instance(), isc_throw, stopSending(), and isc::Exception::what().

+ Here is the call graph for this function:

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 207 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, ioReady(), LOG_ERROR, runReadyIO(), and isc::Exception::what().

Referenced by startSending(), and isc::dhcp_ddns::NameChangeUDPSender::~NameChangeUDPSender().

+ Here is the call graph for this function:

Member Data Documentation

const size_t isc::dhcp_ddns::NameChangeSender::MAX_QUEUE_DEFAULT = 1024
static

Defines a default maximum number of entries in the send queue.

Definition at line 473 of file ncr_io.h.


The documentation for this class was generated from the following files: