Commit e566927c authored by Steven Murray's avatar Steven Murray
Browse files

Second attempt at renaming the tape aggregator. This time it will have the

less specific name of tapeserver daemon therefore decoupling the name from the
decision of whether or not to perform aggregations.
parent 1cc61c57
/******************************************************************************
* castor/tape/aggregator/AggregatorDaemon.cpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Nicola.Bessone@cern.ch Steven.Murray@cern.ch
*****************************************************************************/
#include "castor/PortNumbers.hpp"
#include "castor/exception/Internal.hpp"
#include "castor/exception/InvalidArgument.hpp"
#include "castor/server/TCPListenerThreadPool.hpp"
#include "castor/tape/aggregator/AggregatorDlfMessageConstants.hpp"
#include "castor/tape/aggregator/AggregatorDaemon.hpp"
#include "castor/tape/aggregator/Constants.hpp"
#include "castor/tape/utils/utils.hpp"
#include "castor/tape/aggregator/VdqmRequestHandler.hpp"
#include "h/Cgetopt.h"
#include "h/common.h"
#include <algorithm>
#include <memory>
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::tape::aggregator::AggregatorDaemon::AggregatorDaemon()
throw(castor::exception::Exception) :
castor::server::BaseDaemon("aggregatord") {
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::tape::aggregator::AggregatorDaemon::~AggregatorDaemon() throw() {
}
//------------------------------------------------------------------------------
// main
//------------------------------------------------------------------------------
int castor::tape::aggregator::AggregatorDaemon::main(const int argc,
char **argv) {
// Try to initialize the DLF logging system, quitting with an error message
// to stderr if the initialization fails
try {
castor::server::BaseServer::dlfInit(s_dlfMessages);
} catch(castor::exception::Exception &ex) {
std::cerr << std::endl <<
"Failed to start daemon"
": Failed to initialize DLF"
": " << ex.getMessage().str() << std::endl << std::endl;
return 1;
}
// Try to start the daemon, quitting with an error message to stderr and DLF
// if the start fails
try {
exceptionThrowingMain(argc, argv);
} catch (castor::exception::Exception &ex) {
std::cerr << std::endl << "Failed to start daemon: "
<< ex.getMessage().str() << std::endl << std::endl;
usage(std::cerr, AGGREGATORPROGRAMNAME);
std::cerr << std::endl;
castor::dlf::Param params[] = {
castor::dlf::Param("Message", ex.getMessage().str()),
castor::dlf::Param("Code" , ex.code() )};
CASTOR_DLF_WRITEPC(nullCuuid, DLF_LVL_ERROR,
AGGREGATOR_FAILED_TO_START, params);
return 1;
}
return 0;
}
//------------------------------------------------------------------------------
// exceptionThrowingMain
//------------------------------------------------------------------------------
int castor::tape::aggregator::AggregatorDaemon::exceptionThrowingMain(
const int argc, char **argv) throw(castor::exception::Exception) {
// Log the start of the daemon
logStart(argc, argv);
// Parse the command line
try {
parseCommandLine(argc, argv);
} catch (castor::exception::Exception &ex) {
castor::exception::InvalidArgument ex2;
ex2.getMessage() <<
"Failed to parse the command-line"
": " << ex.getMessage().str();
throw(ex2);
}
// Display usage message and exit if help option found on command-line
if(m_parsedCommandLine.helpOptionSet) {
std::cout << std::endl;
castor::tape::aggregator::AggregatorDaemon::usage(std::cout,
AGGREGATORPROGRAMNAME);
std::cout << std::endl;
return 0;
}
// Pass the foreground option to the super class BaseDaemon
m_foreground = m_parsedCommandLine.foregroundOptionSet;
// Parse the TPCONFIG file
utils::TpconfigLines tpconfigLines;
try {
utils::parseTpconfig(TPCONFIGPATH, tpconfigLines);
} catch (castor::exception::Exception &ex) {
castor::exception::Exception ex2(ex.code());
ex2.getMessage() <<
"Failed to parse TPCONFIG file"
": " << ex.getMessage().str();
throw(ex2);
}
// Extract the drive units names
std::list<std::string> driveNames;
utils::extractTpconfigDriveNames(tpconfigLines, driveNames);
// Put the drive names into a string stream ready to make a log message
std::stringstream driveNamesStream;
for(std::list<std::string>::const_iterator itor = driveNames.begin();
itor != driveNames.end(); itor++) {
if(itor != driveNames.begin()) {
driveNamesStream << ",";
}
driveNamesStream << *itor;
}
// Log the result of parsing the TPCONFIG file to extract the drive unit
// names
castor::dlf::Param params[] = {
castor::dlf::Param("filename" , TPCONFIGPATH ),
castor::dlf::Param("nbDrives" , driveNames.size() ),
castor::dlf::Param("unitNames", driveNamesStream.str())};
castor::dlf::dlf_writep(nullCuuid, DLF_LVL_SYSTEM,
AGGREGATOR_PARSED_TPCONFIG, params);
createVdqmRequestHandlerPool(driveNames.size());
// Start the threads
start();
return 0;
}
//------------------------------------------------------------------------------
// usage
//------------------------------------------------------------------------------
void castor::tape::aggregator::AggregatorDaemon::usage(std::ostream &os,
const char *const programName) throw() {
os << "\nUsage: "<< programName << " [options]\n"
"\n"
"where options can be:\n"
"\n"
"\t-f, --foreground Remain in the Foreground\n"
"\t-c, --config config-file Configuration file\n"
"\t-h, --help Print this help and exit\n"
"\n"
"Comments to: Castor.Support@cern.ch" << std::endl;
}
//------------------------------------------------------------------------------
// logStart
//------------------------------------------------------------------------------
void castor::tape::aggregator::AggregatorDaemon::logStart(const int argc,
const char *const *const argv) throw() {
std::string concatenatedArgs;
// Concatenate all of the command-line arguments into one string
for(int i=0; i < argc; i++) {
if(i != 0) {
concatenatedArgs += " ";
}
concatenatedArgs += argv[i];
}
castor::dlf::Param params[] = {
castor::dlf::Param("argv" , concatenatedArgs)};
castor::dlf::dlf_writep(nullCuuid, DLF_LVL_SYSTEM, AGGREGATOR_STARTED,
params);
}
//------------------------------------------------------------------------------
// parseCommandLine
//------------------------------------------------------------------------------
void castor::tape::aggregator::AggregatorDaemon::parseCommandLine(
const int argc, char **argv) throw(castor::exception::Exception) {
static struct Coptions longopts[] = {
{"foreground", NO_ARGUMENT, NULL, 'f'},
{"help" , NO_ARGUMENT, NULL, 'h'},
{NULL , 0 , NULL, 0 }
};
Coptind = 1;
Copterr = 0;
char c;
while ((c = Cgetopt_long(argc, argv, "fc:p:h", longopts, NULL)) != -1) {
switch (c) {
case 'f':
m_parsedCommandLine.foregroundOptionSet = true;
break;
case 'h':
m_parsedCommandLine.helpOptionSet = true;
break;
case '?':
{
std::stringstream oss;
oss << "Unknown command-line option: " << (char)Coptopt;
// Throw an exception
castor::exception::InvalidArgument ex;
ex.getMessage() << oss.str();
throw(ex);
}
break;
case ':':
{
std::stringstream oss;
oss << "An option is missing a parameter";
// Throw an exception
castor::exception::InvalidArgument ex;
ex.getMessage() << oss.str();
throw(ex);
}
break;
default:
{
std::stringstream oss;
oss << "Cgetopt_long returned the following unknown value: 0x"
<< std::hex << (int)c;
// Throw an exception
TAPE_THROW_EX(castor::exception::Internal,
": " << oss.str());
}
}
}
if(Coptind > argc) {
std::stringstream oss;
oss << "Internal error. Invalid value for Coptind: " << Coptind;
// Throw an exception
TAPE_THROW_EX(castor::exception::Internal,
": " << oss.str());
}
// If there is some extra text on the command-line which has not been parsed
if(Coptind < argc)
{
std::stringstream oss;
oss << "Unexpected command-line argument: " << argv[Coptind]
<< std::endl;
// Throw an exception
castor::exception::InvalidArgument ex;
ex.getMessage() << oss.str();
throw(ex);
}
}
//------------------------------------------------------------------------------
// createVdqmRequestHandlerPool
//------------------------------------------------------------------------------
void castor::tape::aggregator::AggregatorDaemon::
createVdqmRequestHandlerPool(const uint32_t nbDrives)
throw(castor::exception::Exception) {
const int vdqmListenPort = utils::getPortFromConfig("AGGREGATOR", "VDQMPORT",
AGGREGATOR_VDQMPORT);
std::auto_ptr<server::IThread>
thread(new castor::tape::aggregator::VdqmRequestHandler(nbDrives));
std::auto_ptr<server::BaseThreadPool>
threadPool(new castor::server::TCPListenerThreadPool(
"VdqmRequestHandlerPool", thread.release(), vdqmListenPort));
addThreadPool(threadPool.release());
m_vdqmRequestHandlerThreadPool = getThreadPool('V');
if(m_vdqmRequestHandlerThreadPool == NULL) {
TAPE_THROW_EX(castor::exception::Internal,
": Failed to get VdqmRequestHandlerPool");
}
m_vdqmRequestHandlerThreadPool->setNbThreads(nbDrives);
}
/******************************************************************************
* castor/tape/aggregator/AggregatorDaemon.hpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Nicola.Bessone@cern.ch Steven.Murray@cern.ch
*****************************************************************************/
#ifndef CASTOR_TAPE_AGGREGATOR_AGGREGATORDAEMON_HPP
#define CASTOR_TAPE_AGGREGATOR_AGGREGATORDAEMON_HPP 1
#include "castor/exception/Exception.hpp"
#include "castor/exception/InvalidConfigEntry.hpp"
#include "castor/server/BaseDaemon.hpp"
#include "castor/server/BaseThreadPool.hpp"
#include <stdint.h>
#include <iostream>
#include <list>
#include <map>
#include <string>
namespace castor {
namespace tape {
namespace aggregator {
/**
* The aggregator daemon.
*/
class AggregatorDaemon : public castor::server::BaseDaemon {
public:
/**
* Constructor.
*/
AggregatorDaemon() throw(castor::exception::Exception);
/**
* Destructor.
*/
~AggregatorDaemon() throw();
/**
* The main entry function of the aggregator daemon.
*/
int main(const int argc, char **argv);
private:
/**
* Exception throwing main() function which basically implements the
* non-exception throwing main() function except for the initialisation of
* DLF and the "exception catch and log" logic.
*/
int exceptionThrowingMain(const int argc, char **argv)
throw(castor::exception::Exception);
/**
* Logs the start of the daemon.
*/
void logStart(const int argc, const char *const *const argv) throw();
/**
* Data type used to store the results of parsing the command-line.
*/
struct ParsedCommandLine {
bool foregroundOptionSet;
bool helpOptionSet;
ParsedCommandLine() :
foregroundOptionSet(false),
helpOptionSet(false) {
}
};
/**
* The results of parsing the command-line.
*/
ParsedCommandLine m_parsedCommandLine;
/**
* The VDQM request handler thread pool which should contain as many threads
* as there are drives per tape server.
*/
server::BaseThreadPool *m_vdqmRequestHandlerThreadPool;
/**
* Parses the command-line arguments and sets the daemon options accordingly.
*
* @param argc Argument count from the executable's entry function: main().
* @param argv Argument vector from the executable's entry function: main().
*/
void parseCommandLine(const int argc, char **argv)
throw(castor::exception::Exception);
/**
* Writes the command-line usage message of the aggregator daemon onto the
* specified output stream.
*
* @param os Output stream to be written to.
* @param programName The program name to be used in the message.
*/
void usage(std::ostream &os, const char *const programName) throw();
/**
* Creates the VDQM request handler thread pool.
*
* @param nbDrives The number of tape drives attached to the tape server
* aggregatord is running on.
*/
void createVdqmRequestHandlerPool(const uint32_t nbDrives)
throw (castor::exception::Exception);
/**
* DLF message strings.
*/
static castor::dlf::Message s_dlfMessages[];
}; // class AggregatorDaemon
} // namespace aggregator
} // namespace tape
} // namespace castor
#endif // CASTOR_TAPE_AGGREGATOR_AGGREGATORDAEMON_HPP
/* This file was generated by ./AggregatorDlfMessagesCodeGenerator on Thu Feb 11 09:50:23 CET 2010
*/
/******************************************************************************
* castor/tape/aggregator/AggregatorDlfMessageConstants.hpp
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 CERN
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
*
* @author Steven Murray Steven.Murray@cern.ch
*****************************************************************************/
#ifndef CASTOR_TAPE_AGGREGATOR_AGGREGATORDLFMESSAGECONSTANTS_HPP
#define CASTOR_TAPE_AGGREGATOR_AGGREGATORDLFMESSAGECONSTANTS_HPP 1
namespace castor {
namespace tape {
namespace aggregator {
enum AggregatorDlfMessages {
AGGREGATOR_NULL=0, /* " - " */
AGGREGATOR_STARTED=1, /* "aggregatord started" */
AGGREGATOR_FAILED_TO_START=2, /* "aggregatord failed to start" */
AGGREGATOR_RECEIVED_VDQM_CONNECTION=3, /* "Received a connection from VDQM" */
AGGREGATOR_HANDLE_VDQM_REQUEST_EXCEPT=4, /* "Exception raised when handling a request from the VDQM" */
AGGREGATOR_FAILED_TO_READ_MESSAGE_HEADER=5, /* "Failed to read message header" */
AGGREGATOR_UNKNOWN_MAGIC=6, /* "Unknown magic number" */
AGGREGATOR_UNKNOWN_REQUEST_TYPE=7, /* "Unknown request type" */
AGGREGATOR_FAILED_TO_READ_MESSAGE_BODY=8, /* "Failed to read message body" */
AGGREGATOR_RECEIVE_RTCOPY_JOB=9, /* "Receiving remote-copy job" */
AGGREGATOR_RECEIVED_RTCOPY_JOB=10, /* "Received remote-copy job" */
AGGREGATOR_SUBMITTING_RTCOPY_JOB_TO_RTCPD=11, /* "Submitting remote-copy job to RTCPD" */
AGGREGATOR_FAILED_TO_SUBMIT_JOB_TO_RTCPD=12, /* "Failed to submit remote-copy job to RTCPD" */
AGGREGATOR_FAILED_TO_MARSHALL_RTCP_ACKN=13, /* "Failed to marshall RTCP acknowledge message" */
AGGREGATOR_FAILED_TO_SEND_RTCOPY_JOB_REPLY_TO_VDQM=14, /* "Failed to send remote-copy job reply to VDQM" */
AGGREGATOR_FAILED_TO_PROCESS_RCOPY_JOB_SUBMISSION=15, /* "Failed to process remote-copy job submission message" */
AGGREGATOR_RTCPD_HANDLER_SOCKET_IS_NULL=16, /* "The RtcpdHandlerThread has been passed a NULL socket pointer" */
AGGREGATOR_INITIAL_RTCPD_CALLBACK=17, /* "Received initial callback connection from RTCPD" */
AGGREGATOR_RTCPD_CALLBACK=18, /* "Received a callback connection from RTCPD" */
AGGREGATOR_GOT_VOLREQID=19, /* "Got volume request ID from RTCPD" */
AGGREGATOR_FAILED_TO_GET_VOLREQID=20, /* "Failed to get volume request ID from RTCPD" */
AGGREGATOR_FAILED_TO_MARSHALL_RTCOPY_JOB_REPLY_MESSAGE=21, /* "Failed to marshall remote-copy job reply message" */
AGGREGATOR_SIGNALLED_NO_MORE_REQUESTS=22, /* "Signalled no more requests to RTCPD" */
AGGREGATOR_FAILED_TO_COORDINATE_REMOTE_COPY=23, /* "Failed to coordinate remote-copy" */
AGGREGATOR_TRANSFER_FAILED=24, /* "Transfer failed" */
AGGREGATOR_GAVE_REQUEST_FOR_MORE_WORK=25, /* "Gave request for more work to RTCPD" */
AGGREGATOR_DATA_ON_INITIAL_RTCPD_CONNECTION=26, /* "Data has arrived on the initial RTCPD connection" */
AGGREGATOR_RECEIVED_RTCP_ENDOF_REQ=27, /* "Received RTCP_ENDOF_REQ" */
AGGREGATOR_TAPE_POSITIONED=28, /* "Tape positioned" */
AGGREGATOR_FILE_TRANSFERED=29, /* "File transfered" */
AGGREGATOR_GET_REQUEST_INFO_FROM_RTCPD=30, /* "Getting request information from RTCPD" */
AGGREGATOR_GOT_REQUEST_INFO_FROM_RTCPD=31, /* "Got request information from RTCPD" */
AGGREGATOR_TOLD_CLIENT_TO_START_TRANSFER=32, /* "Told client to start the transfer protocol" */
AGGREGATOR_GET_VOLUME_FROM_CLIENT=33, /* "Getting volume from client" */
AGGREGATOR_GOT_VOLUME_FROM_CLIENT=34, /* "Got volume from client" */
AGGREGATOR_GOT_NO_MORE_FILES_FROM_CLIENT=35, /* "Got no more files from client" */
AGGREGATOR_GET_FILE_TO_MIGRATE_FROM_CLIENT=36, /* "Getting file to migrate from client" */
AGGREGATOR_GOT_FILE_TO_MIGRATE_FROM_CLIENT=37, /* "Got file to migrate from client" */
AGGREGATOR_GET_FILE_TO_RECALL_FROM_CLIENT=38, /* "Getting file to recall from client" */
AGGREGATOR_GOT_FILE_TO_RECALL_FROM_CLIENT=39, /* "Got file to recall from client" */
AGGREGATOR_GIVE_VOLUME_TO_RTCPD=40, /* "Giving volume to RTCPD" */
AGGREGATOR_GAVE_VOLUME_TO_RTCPD=41, /* "Gave volume to RTCPD" */
AGGREGATOR_ASK_RTCPD_TO_RQST_MORE_RECALL_WORK=42, /* "Asking RTCPD to request more recall work" */
AGGREGATOR_ASKED_RTCPD_TO_RQST_MORE_RECALL_WORK=43, /* "Asked RTCPD to request more recall work" */
AGGREGATOR_ASK_RTCPD_TO_RQST_MORE_MIGRATE_WORK=44, /* "Asking RTCPD to request more migrate work" */
AGGREGATOR_ASKED_RTCPD_TO_RQST_MORE_MIGRATE_WORK=45, /* "Asked RTCPD to request more migrate work" */
AGGREGATOR_TELL_RTCPD_DUMP_TAPE=46, /* "Telling RTCPD to dump tape" */
AGGREGATOR_TOLD_RTCPD_DUMP_TAPE=47, /* "Told RTCPD to dump tape" */
AGGREGATOR_TELL_RTCPD_END_OF_FILE_LIST=48, /* "Telling RTCPD end of file list" */
AGGREGATOR_TOLD_RTCPD_END_OF_FILE_LIST=49, /* "Told RTCPD end of file list" */
AGGREGATOR_TELL_RTCPD_TO_ABORT=50, /* "Telling RTCPD to abort" */
AGGREGATOR_TOLD_RTCPD_TO_ABORT=51, /* "Told RTCPD to abort" */
AGGREGATOR_GIVE_RECALL_FILE_TO_RTCPD=52, /* "Giving recall file to RTCPD" */
AGGREGATOR_GAVE_RECALL_FILE_TO_RTCPD=53, /* "Gave recall file to RTCPD" */
AGGREGATOR_GIVE_MIGRATE_FILE_TO_RTCPD=54, /* "Giving migrate file to RTCPD" */
AGGREGATOR_GAVE_MIGRATE_FILE_TO_RTCPD=55, /* "Gave migrate file to RTCPD" */
AGGREGATOR_RECEIVE_MSGBODY_FROM_RTCPD=56, /* "Receiving message body from RTCPD" */
AGGREGATOR_RECEIVED_MSGBODY_FROM_RTCPD=57, /* "Received message body from RTCPD" */
AGGREGATOR_RECEIVE_FILERQSTBODY_FROM_RTCPD=58, /* "Receiving FileRqstBody from RTCPD" */
AGGREGATOR_RECEIVED_FILERQSTBODY_FROM_RTCPD=59, /* "Received FileRqstBody from RTCPD" */
AGGREGATOR_RECEIVE_FILERQSTERRBODY_FROM_RTCPD=60, /* "Receiving FileRqstErrBody from RTCPD" */
AGGREGATOR_RECEIVED_FILERQSTERRBODY_FROM_RTCPD=61, /* "Received FileRqstErrBody from RTCPD" */
AGGREGATOR_PROCESSING_TAPE_DISK_RQST=62, /* "Processing a tape/disk IO request from RTCPD" */
AGGREGATOR_PING_RTCPD=63, /* "Pinging RTCPD" */
AGGREGATOR_PINGED_RTCPD=64, /* "Pinged RTCPD" */
AGGREGATOR_SEND_ACK_TO_RTCPD=65, /* "Sending acknowledge to RTCPD" */
AGGREGATOR_SENT_ACK_TO_RTCPD=66, /* "Sent acknowledge to RTCPD" */
AGGREGATOR_SEND_HEADER_TO_RTCPD=67, /* "Sending message header to RTCPD" */
AGGREGATOR_SENT_HEADER_TO_RTCPD=68, /* "Sent message header to RTCPD" */
AGGREGATOR_RECEIVE_TAPERQSTBODY=69, /* "Receiving tape request message body" */
AGGREGATOR_RECEIVED_TAPERQSTBODY=70, /* "Received tape request message body" */
AGGREGATOR_RECEIVE_GIVEOUTPBODY=71, /* "Receiving GIVE_OUTP message body" */
AGGREGATOR_RECEIVED_GIVEOUTPBODY=72, /* "Received GIVE_OUTP message body" */
AGGREGATOR_RECEIVE_TAPERQSTERRBODY=73, /* "Receiving tape request message body with error appendix" */
AGGREGATOR_RECEIVED_TAPERQSTERRBODY=74, /* "Received tape request message body with error appendix" */
AGGREGATOR_SEND_DELAYED_REQUEST_MORE_WORK_ACK_TO_RTCPD=75, /* "Sending delayed acknowledge of request for more work to RTCPD" */
AGGREGATOR_SENT_DELAYED_REQUEST_MORE_WORK_ACK_TO_RTCPD=76, /* "Sent delayed acknowledge of request for more work to RTCPD" */
AGGREGATOR_CREATED_RTCPD_CALLBACK_PORT=77, /* "Created TCP/IP port for RTCPD callbacks" */
AGGREGATOR_CONNECTION_CLOSED_BY_RTCPD=78, /* "Connection closed by RTCPD" */
AGGREGATOR_CLOSED_CONNECTION=79, /* "Connection closed by aggregator" */
AGGREGATOR_NOTIFY_CLIENT_FILE_MIGRATED=80, /* "Notifying client file migrated" */
AGGREGATOR_NOTIFIED_CLIENT_FILE_MIGRATED=81, /* "Notified client file migrated" */
AGGREGATOR_NOTIFY_CLIENT_FILE_RECALLED=82, /* "Notifying client file recalled" */