mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-29 13:07:50 +00:00
[trac499] Add logging of errors to IOFetch
This commit is contained in:
parent
d4af3712f3
commit
af01e66fde
@ -13,28 +13,32 @@ CLEANFILES = *.gcno *.gcda
|
||||
# which would make the build fail with -Werror (our default setting).
|
||||
lib_LTLIBRARIES = libasiolink.la
|
||||
libasiolink_la_SOURCES = asiolink.h
|
||||
libasiolink_la_SOURCES += asiodef.cc asiodef.h
|
||||
libasiolink_la_SOURCES += dns_answer.h
|
||||
libasiolink_la_SOURCES += dns_lookup.h
|
||||
libasiolink_la_SOURCES += dns_server.h
|
||||
libasiolink_la_SOURCES += dns_service.h dns_service.cc
|
||||
libasiolink_la_SOURCES += dns_service.cc dns_service.h
|
||||
libasiolink_la_SOURCES += dummy_io_cb.h
|
||||
libasiolink_la_SOURCES += interval_timer.h interval_timer.cc
|
||||
libasiolink_la_SOURCES += io_address.h io_address.cc
|
||||
libasiolink_la_SOURCES += interval_timer.cc interval_timer.h
|
||||
libasiolink_la_SOURCES += io_address.cc io_address.h
|
||||
libasiolink_la_SOURCES += io_asio_socket.h
|
||||
libasiolink_la_SOURCES += io_endpoint.h io_endpoint.cc
|
||||
libasiolink_la_SOURCES += io_endpoint.cc io_endpoint.h
|
||||
libasiolink_la_SOURCES += io_error.h
|
||||
libasiolink_la_SOURCES += io_fetch.h io_fetch.cc
|
||||
libasiolink_la_SOURCES += io_fetch.cc io_fetch.h
|
||||
libasiolink_la_SOURCES += io_message.h
|
||||
libasiolink_la_SOURCES += io_service.h io_service.cc
|
||||
libasiolink_la_SOURCES += io_socket.h io_socket.cc
|
||||
libasiolink_la_SOURCES += recursive_query.h recursive_query.cc
|
||||
libasiolink_la_SOURCES += io_service.cc io_service.h
|
||||
libasiolink_la_SOURCES += io_socket.cc io_socket.h
|
||||
libasiolink_la_SOURCES += recursive_query.cc recursive_query.h
|
||||
libasiolink_la_SOURCES += simple_callback.h
|
||||
libasiolink_la_SOURCES += tcp_endpoint.h
|
||||
libasiolink_la_SOURCES += tcp_server.h tcp_server.cc
|
||||
libasiolink_la_SOURCES += tcp_server.cc tcp_server.h
|
||||
libasiolink_la_SOURCES += tcp_socket.h
|
||||
libasiolink_la_SOURCES += udp_endpoint.h
|
||||
libasiolink_la_SOURCES += udp_server.h udp_server.cc
|
||||
libasiolink_la_SOURCES += udp_server.cc udp_server.h
|
||||
libasiolink_la_SOURCES += udp_socket.h
|
||||
|
||||
EXTRA_DIST = asiodef.msg
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
# B10_CXXFLAGS)
|
||||
libasiolink_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
|
@ -25,8 +25,12 @@
|
||||
#include <dns/opcode.h>
|
||||
#include <dns/rcode.h>
|
||||
#include <log/dummylog.h>
|
||||
#include <log/logger.h>
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <asiolink/asiodef.h>
|
||||
#include <asiolink/io_address.h>
|
||||
#include <asiolink/io_endpoint.h>
|
||||
#include <asiolink/io_fetch.h>
|
||||
|
||||
using namespace asio;
|
||||
@ -36,6 +40,10 @@ using namespace std;
|
||||
|
||||
namespace asiolink {
|
||||
|
||||
/// Use the ASIO logger
|
||||
|
||||
isc::log::Logger logger("asio");
|
||||
|
||||
/// IOFetch Constructor - just initialize the private data
|
||||
|
||||
IOFetch::IOFetch(int protocol, IOService& service,
|
||||
@ -52,7 +60,10 @@ IOFetch::IOFetch(int protocol, IOService& service,
|
||||
|
||||
void
|
||||
IOFetch::operator()(error_code ec, size_t length) {
|
||||
if (ec || data_->stopped) {
|
||||
if (data_->stopped) {
|
||||
return;
|
||||
} else if (ec) {
|
||||
logIOFailure(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -93,11 +104,13 @@ IOFetch::operator()(error_code ec, size_t length) {
|
||||
// Open a connection to the target system. For speed, if the operation
|
||||
// was completed synchronously (i.e. UDP operation) we bypass the yield.
|
||||
if (data_->socket->open(data_->remote.get(), *this)) {
|
||||
data_->origin = OPEN;
|
||||
CORO_YIELD;
|
||||
}
|
||||
|
||||
// Begin an asynchronous send, and then yield. When the send completes
|
||||
// send completes, we will resume immediately after this point.
|
||||
data_->origin = SEND;
|
||||
CORO_YIELD data_->socket->asyncSend(data_->msgbuf->getData(),
|
||||
data_->msgbuf->getLength(), data_->remote.get(), *this);
|
||||
|
||||
@ -108,6 +121,7 @@ IOFetch::operator()(error_code ec, size_t length) {
|
||||
// we need to yield ... and we *really* don't want to set up another
|
||||
// coroutine within that method.) So after each receive (and yield),
|
||||
// we check if the operation is complete and if not, loop to read again.
|
||||
data_->origin = RECEIVE;
|
||||
do {
|
||||
CORO_YIELD data_->socket->asyncReceive(data_->data.get(),
|
||||
static_cast<size_t>(MAX_LENGTH), data_->cumulative,
|
||||
@ -156,20 +170,30 @@ IOFetch::stop(Result result) {
|
||||
// variable should be done inside a mutex (and the stopped_ variable
|
||||
// declared as "volatile").
|
||||
//
|
||||
// Although Logger::debug checks the debug flag internally, doing it
|
||||
// in below avoids the overhead of a string conversion in the common
|
||||
// case when debug is not enabled.
|
||||
//
|
||||
// TODO: Update testing of stopped_ if threads are used.
|
||||
data_->stopped = true;
|
||||
|
||||
switch (result) {
|
||||
case TIME_OUT:
|
||||
dlog("Query timed out");
|
||||
if (logger.isDebugEnabled(1)) {
|
||||
logger.debug(1, ASIO_RECVTMO,
|
||||
data_->remote->getAddress().toText().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case STOPPED:
|
||||
dlog("Query stopped");
|
||||
if (logger.isDebugEnabled(50)) {
|
||||
logger.debug(50, ASIO_FETCOMP,
|
||||
data_->remote->getAddress().toText().c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
logger.error(ASIO_UNKRESULT, static_cast<int>(result));
|
||||
}
|
||||
|
||||
// Stop requested, cancel and I/O's on the socket and shut it down,
|
||||
@ -189,5 +213,37 @@ IOFetch::stop(Result result) {
|
||||
}
|
||||
}
|
||||
|
||||
// Log an error - called on I/O failure
|
||||
|
||||
void IOFetch::logIOFailure(asio::error_code& ec) {
|
||||
|
||||
// Get information that will be in all messages
|
||||
static const char* PROTOCOL[2] = {"TCP", "UDP"};
|
||||
const char* prot = (data_->remote->getProtocol() == IPPROTO_TCP) ?
|
||||
PROTOCOL[0] : PROTOCOL[1];
|
||||
|
||||
int errcode = ec.value();
|
||||
|
||||
std::string str_address = data_->remote->getAddress().toText();
|
||||
const char* address = str_address.c_str();
|
||||
|
||||
switch (data_->origin) {
|
||||
case OPEN:
|
||||
logger.error(ASIO_OPENSOCK, errcode, prot, address);
|
||||
break;
|
||||
|
||||
case SEND:
|
||||
logger.error(ASIO_SENDSOCK, errcode, prot, address);
|
||||
break;
|
||||
|
||||
case RECEIVE:
|
||||
logger.error(ASIO_RECVSOCK, errcode, prot, address);
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.error(ASIO_UNKORIGIN, errcode, prot, address);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace asiolink
|
||||
|
||||
|
@ -51,6 +51,17 @@ namespace asiolink {
|
||||
|
||||
class IOFetch : public coroutine {
|
||||
public:
|
||||
/// \brief Origin of Asynchronous I/O Call
|
||||
///
|
||||
/// Indicates what initiated an asynchronous I/O call and used in deciding
|
||||
/// what error message to output if the I/O fails.
|
||||
enum Origin {
|
||||
NONE = 0, ///< No asynchronous call outstanding
|
||||
OPEN = 1,
|
||||
SEND = 2,
|
||||
RECEIVE = 3,
|
||||
CLOSE = 4
|
||||
};
|
||||
|
||||
/// \brief Result of Upstream Fetch
|
||||
///
|
||||
@ -95,7 +106,12 @@ public:
|
||||
virtual ~Callback()
|
||||
{}
|
||||
|
||||
/// \brief Callback method called when the fetch completes
|
||||
/// \brief Callback method called when the fetch completes /// \brief Origin of Asynchronous I/O Call
|
||||
///
|
||||
|
||||
// The next enum is a "trick" to allow constants to be defined in a class
|
||||
// declaration.
|
||||
|
||||
///
|
||||
/// \brief result Result of the fetch
|
||||
virtual void operator()(Result result) = 0;
|
||||
@ -127,12 +143,13 @@ public:
|
||||
bool stopped; ///< Have we stopped running?
|
||||
asio::deadline_timer timer; ///< Timer to measure timeouts
|
||||
int timeout; ///< Timeout in ms
|
||||
Origin origin; ///< Origin of last asynchronous I/O
|
||||
|
||||
/// \brief Constructor
|
||||
///
|
||||
/// Just fills in the data members of the IOFetchData structure
|
||||
///
|
||||
/// \param protocol either IPPROTO_UDP or IPPROTO_TCP
|
||||
/// \param proto either IPPROTO_UDP or IPPROTO_TCP
|
||||
/// \param service I/O Service object to handle the asynchronous
|
||||
/// operations.
|
||||
/// \param query DNS question to send to the upstream server.
|
||||
@ -146,18 +163,18 @@ public:
|
||||
/// \param wait Timeout for the fetch (in ms).
|
||||
///
|
||||
/// TODO: May need to alter constructor (see comment 4 in Trac ticket #554)
|
||||
IOFetchData(int protocol, IOService& service,
|
||||
IOFetchData(int proto, IOService& service,
|
||||
const isc::dns::Question& query, const IOAddress& address,
|
||||
uint16_t port, isc::dns::OutputBufferPtr& buff, Callback* cb,
|
||||
int wait)
|
||||
:
|
||||
socket((protocol == IPPROTO_UDP) ?
|
||||
socket((proto == IPPROTO_UDP) ?
|
||||
static_cast<IOAsioSocket<IOFetch>*>(
|
||||
new UDPSocket<IOFetch>(service)) :
|
||||
static_cast<IOAsioSocket<IOFetch>*>(
|
||||
new TCPSocket<IOFetch>(service))
|
||||
),
|
||||
remote((protocol == IPPROTO_UDP) ?
|
||||
remote((proto == IPPROTO_UDP) ?
|
||||
static_cast<IOEndpoint*>(new UDPEndpoint(address, port)) :
|
||||
static_cast<IOEndpoint*>(new TCPEndpoint(address, port))
|
||||
),
|
||||
@ -169,7 +186,8 @@ public:
|
||||
cumulative(0),
|
||||
stopped(false),
|
||||
timer(service.get_io_service()),
|
||||
timeout(wait)
|
||||
timeout(wait),
|
||||
origin(NONE)
|
||||
{}
|
||||
};
|
||||
|
||||
@ -217,6 +235,13 @@ public:
|
||||
void stop(Result reason = STOPPED);
|
||||
|
||||
private:
|
||||
/// \brief Log I/O Failure
|
||||
///
|
||||
/// Records an I/O failure to the log file
|
||||
///
|
||||
/// \param ec ASIO error code
|
||||
void logIOFailure(asio::error_code& ec);
|
||||
|
||||
boost::shared_ptr<IOFetchData> data_; ///< Private data
|
||||
|
||||
};
|
||||
|
@ -70,8 +70,15 @@ public:
|
||||
/// \brief Destructor
|
||||
virtual ~UDPSocket();
|
||||
|
||||
virtual int getNative() const { return (socket_.native()); }
|
||||
virtual int getProtocol() const { return (IPPROTO_UDP); }
|
||||
/// \brief Return file descriptor of underlying socket
|
||||
virtual int getNative() const {
|
||||
return (socket_.native());
|
||||
}
|
||||
|
||||
/// \brief Return protocol of socket
|
||||
virtual int getProtocol() const {
|
||||
return (IPPROTO_UDP);
|
||||
}
|
||||
|
||||
/// \brief Open Socket
|
||||
///
|
||||
|
@ -24,6 +24,8 @@ liblog_la_SOURCES += message_types.h
|
||||
liblog_la_SOURCES += root_logger_name.cc root_logger_name.h
|
||||
liblog_la_SOURCES += strutil.h strutil.cc
|
||||
|
||||
EXTRA_DIST = messagedef.mes
|
||||
|
||||
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
|
||||
# B10_CXXFLAGS)
|
||||
liblog_la_CXXFLAGS = $(AM_CXXFLAGS)
|
||||
|
Loading…
x
Reference in New Issue
Block a user