// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/rib/register_server.cc,v 1.20 2007/02/16 22:47:08 pavlin Exp $"
// #define DEBUG_LOGGING
// #define DEBUG_PRINT_FUNCTION_NAME
#include "rib_module.h"
#include "libxorp/xorp.h"
#include "libxorp/xlog.h"
#include "libxorp/debug.h"
#include "libxipc/xrl_router.hh"
#include "register_server.hh"
NotifyQueue::NotifyQueue(const string& module_name)
: _module_name(module_name),
_active(false),
_response_sender(NULL)
{
}
void
NotifyQueue::add_entry(NotifyQueueEntry* e)
{
_queue.push_back(e);
}
void
NotifyQueue::send_next()
{
XrlCompleteCB cb = callback(this, &NotifyQueue::xrl_done);
_queue.front()->send(_response_sender, _module_name, cb);
_queue.pop_front();
if (_queue.empty()) {
_active = false;
_response_sender = NULL;
}
}
void
NotifyQueue::flush(ResponseSender* response_sender)
{
debug_msg("NQ: flush\n");
if (_queue.empty()) {
debug_msg("flush called on empty queue\n");
return;
}
_response_sender = response_sender;
//
// This isn't really the best way to do this, because when the
// queue is active it won't force transaction batching, but it's
// better than nothing.
//
if (_active) {
debug_msg("queue is already active\n");
return;
}
_active = true;
send_next();
}
void
NotifyQueue::xrl_done(const XrlError& e)
{
debug_msg("NQ: xrl_done\n");
if (e == XrlError::OKAY()) {
if (!_queue.empty() && _active)
send_next();
} else {
XLOG_ERROR("Failed to send registration update to RIB client");
}
}
template <>
void
NotifyQueueChangedEntry<IPv4>::send(ResponseSender* response_sender,
const string& module_name,
NotifyQueue::XrlCompleteCB& cb)
{
response_sender->send_route_info_changed4(module_name.c_str(),
_net.masked_addr(),
_net.prefix_len(), _nexthop,
_metric, _admin_distance,
_protocol_origin.c_str(), cb);
}
template <>
void
NotifyQueueChangedEntry<IPv6>::send(ResponseSender* response_sender,
const string& module_name,
NotifyQueue::XrlCompleteCB& cb)
{
response_sender->send_route_info_changed6(module_name.c_str(),
_net.masked_addr(),
_net.prefix_len(), _nexthop,
_metric, _admin_distance,
_protocol_origin.c_str(), cb);
}
template <>
void
NotifyQueueInvalidateEntry<IPv4>::send(ResponseSender* response_sender,
const string& module_name,
NotifyQueue::XrlCompleteCB& cb)
{
debug_msg("Sending route_info_invalid4\n");
response_sender->send_route_info_invalid4(module_name.c_str(),
_net.masked_addr(),
_net.prefix_len(), cb);
}
template <>
void
NotifyQueueInvalidateEntry<IPv6>::send(ResponseSender* response_sender,
const string& module_name,
NotifyQueue::XrlCompleteCB& cb)
{
response_sender->send_route_info_invalid6(module_name.c_str(),
_net.masked_addr(),
_net.prefix_len(), cb);
}
RegisterServer::RegisterServer(XrlRouter* xrl_router)
: _response_sender(xrl_router)
{
}
void
RegisterServer::add_entry_to_queue(const string& module_name,
NotifyQueueEntry* e)
{
debug_msg("REGSERV: add_entry_to_queue\n");
NotifyQueue* queue;
map<string, NotifyQueue* >::iterator qmi;
bool new_queue;
qmi = _queuemap.find(module_name);
if (qmi == _queuemap.end()) {
_queuemap[module_name] = new NotifyQueue(module_name);
queue = _queuemap[module_name];
new_queue = true;
} else {
new_queue = false;
queue = qmi->second;
}
queue->add_entry(e);
}
void
RegisterServer::send_route_changed(const string& module_name,
const IPv4Net& net,
const IPv4& nexthop,
uint32_t metric,
uint32_t admin_distance,
const string& protocol_origin,
bool multicast)
{
NotifyQueueChangedEntry<IPv4>* q_entry;
q_entry = new NotifyQueueChangedEntry<IPv4>(net, nexthop,
metric, admin_distance,
protocol_origin, multicast);
add_entry_to_queue(module_name,
reinterpret_cast<NotifyQueueEntry *>(q_entry));
}
void
RegisterServer::send_invalidate(const string& module_name,
const IPv4Net& net,
bool multicast)
{
NotifyQueueInvalidateEntry<IPv4>* q_entry;
q_entry = new NotifyQueueInvalidateEntry<IPv4>(net, multicast);
add_entry_to_queue(module_name,
reinterpret_cast<NotifyQueueEntry *>(q_entry));
}
void
RegisterServer::send_route_changed(const string& module_name,
const IPv6Net& net,
const IPv6& nexthop,
uint32_t metric,
uint32_t admin_distance,
const string& protocol_origin,
bool multicast)
{
NotifyQueueChangedEntry<IPv6>* q_entry;
q_entry = new NotifyQueueChangedEntry<IPv6>(net, nexthop,
metric, admin_distance,
protocol_origin, multicast);
add_entry_to_queue(module_name,
reinterpret_cast<NotifyQueueEntry* >(q_entry));
}
void
RegisterServer::send_invalidate(const string& module_name,
const IPv6Net& net,
bool multicast)
{
NotifyQueueInvalidateEntry<IPv6>* q_entry;
q_entry = new NotifyQueueInvalidateEntry<IPv6>(net, multicast);
add_entry_to_queue(module_name,
reinterpret_cast<NotifyQueueEntry *>(q_entry));
}
void
RegisterServer::flush()
{
debug_msg("REGSERV: flush\n");
map<string, NotifyQueue* >::iterator iter;
for (iter = _queuemap.begin(); iter != _queuemap.end(); ++iter) {
iter->second->flush(&_response_sender);
}
}
syntax highlighted by Code2HTML, v. 0.9.1