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

bug #82673: RFE: Tapebridged and rtcpd should support buffered tape-marks over multiple files

Added new tapebridged configuration parameter:

TAPEBRIDGED USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES
parent 8b188ba7
......@@ -301,6 +301,62 @@ void castor::tape::tapebridge::BridgeProtocolEngine::processSocks()
}
//------------------------------------------------------------------------------
// getNbRtcpdDiskIOThreads
//------------------------------------------------------------------------------
castor::tape::tapebridge::ConfigParamAndSource<uint32_t>
castor::tape::tapebridge::BridgeProtocolEngine::getNbRtcpdDiskIOThreads()
throw(castor::exception::Exception) {
const std::string paramName = "RTCPD/THREAD_POOL";
const char *paramCStr = NULL;
uint32_t paramUInt32 = 0;
std::string paramSource = "UNKNOWN";
// Try to get the number of disk-IO threads from the environment variables
if(NULL != (paramCStr = getenv("RTCPD_THREAD_POOL"))) {
paramSource = "environment variable";
if(!utils::isValidUInt(paramCStr)) {
castor::exception::InvalidArgument ex;
ex.getMessage() <<
"Configuration parameter is not a valid unsigned integer"
": name=" << paramName <<
" value=" << paramCStr <<
" source=" << paramSource;
throw(ex);
}
// Safe to cast to uint32_t as utils::isValidUInt has been performed
paramUInt32 = (uint32_t)atoi(paramCStr);
// Else try to get the number of disk IO threads of castor.conf
} else if(NULL != (paramCStr = getconfent("RTCPD", "THREAD_POOL", 0))) {
paramSource = "castor.conf";
if(!utils::isValidUInt(paramCStr)) {
castor::exception::InvalidArgument ex;
ex.getMessage() <<
"Configuration parameter is not a valid unsigned integer"
": name=" << paramName <<
" value=" << paramCStr <<
" source=" << paramSource;
throw(ex);
}
// Safe to cast to uint32_t as utils::isValidUInt has been performed
paramUInt32 = (uint32_t)atoi(paramCStr);
// Else use the compile-time default
} else {
paramSource = "compile-time default";
paramUInt32 = RTCPD_THREAD_POOL;
}
return ConfigParamAndSource<uint32_t>(paramName, paramUInt32, paramSource);
}
//------------------------------------------------------------------------------
// processAPendingSocket
//------------------------------------------------------------------------------
......@@ -326,27 +382,20 @@ bool castor::tape::tapebridge::BridgeProtocolEngine::processAPendingSocket(
// Throw an exception if connection is not from localhost
checkPeerIsLocalhost(acceptedConnection);
// Determine the number of RTCPD disk IO threads
int nbRtcpdDiskIOThreads = RTCPD_THREAD_POOL; // Compile-time default
char *p = NULL;
if((p = getenv("RTCPD_THREAD_POOL")) ||
(p = getconfent("RTCPD", "THREAD_POOL", 0))) {
if(!utils::isValidUInt(p)) {
castor::exception::InvalidArgument ex;
const ConfigParamAndSource<uint32_t>
nbRtcpdDiskIOThreads(getNbRtcpdDiskIOThreads());
ex.getMessage() <<
"RTCPD THREAD_POOL value is not a valid unsigned integer"
": value=" << p;
throw(ex);
}
nbRtcpdDiskIOThreads = atoi(p);
}
// Log the value and source of the number of rtcpd disk-IO threads
castor::dlf::Param params[] = {
castor::dlf::Param("name" , nbRtcpdDiskIOThreads.name),
castor::dlf::Param("value" , nbRtcpdDiskIOThreads.value),
castor::dlf::Param("source", nbRtcpdDiskIOThreads.source)};
castor::dlf::dlf_writep(m_cuuid, DLF_LVL_SYSTEM, TAPEBRIDGE_CONFIG_PARAM,
params);
// Determine maximum number of RTCPD disk/tape IO control connections
// This is the number of disk IO threads plus 1 for the tape IO thread
const int maxNbDiskTapeIOControlConns = nbRtcpdDiskIOThreads + 1;
const int maxNbDiskTapeIOControlConns = nbRtcpdDiskIOThreads.value + 1;
// Throw an exception if the expected maximum number of disk/tape IO
// control connections has been exceeded
......
......@@ -28,6 +28,7 @@
#include "castor/exception/Exception.hpp"
#include "castor/tape/tapebridge/BoolFunctor.hpp"
#include "castor/tape/tapebridge/BridgeSocketCatalogue.hpp"
#include "castor/tape/tapebridge/ConfigParamAndSource.hpp"
#include "castor/tape/tapebridge/Constants.hpp"
#include "castor/tape/tapebridge/Counter.hpp"
#include "castor/tape/legacymsg/CommonMarshal.hpp"
......@@ -39,6 +40,7 @@
#include "h/Cuuid.h"
#include <map>
#include <stdint.h>
namespace castor {
......@@ -89,6 +91,18 @@ public:
*/
void run() throw(castor::exception::Exception);
/**
* Determines the number of rtcpd disk-IO threads.
*
* This method deteremines the required value by first reading the
* environment variables, then if unsuccessful by reading castor.conf and
* finally if still unsuccessfull by using the compile-time default.
*
* @return The configuration parameter including its source, either
* "environment variable", "castor.conf" or "compile-time default".
*/
ConfigParamAndSource<uint32_t> getNbRtcpdDiskIOThreads()
throw(castor::exception::Exception);
private:
......
/******************************************************************************
* castor/tape/tapebridge/ConfigParamAndSource.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@cern.ch
*****************************************************************************/
#ifndef CASTOR_TAPE_TAPEBRIDGE_CONFIGPARAMANDSOURCE
#define CASTOR_TAPE_TAPEBRIDGE_CONFIGPARAMANDSOURCE
#include <string>
namespace castor {
namespace tape {
namespace tapebridge {
/**
* Data structure used to store the name, value and source of a configuration
* parameter, where source is to be used soley for logging purposes and should
* have user readable values like "environment variable", * "castor.conf" or
* "compile-time constant".
*/
template <typename T> struct ConfigParamAndSource {
/**
* Constructor used to initialise the members of this structure.
*
* @param n The name of the configuration parameter.
* @param v The value of the configuration parameter.
* @param s The source of the configuration parameter.
*/
ConfigParamAndSource(const std::string &n, T v, const std::string &s) :
name(n), value(v), source(s) {
}
/**
* The name of the configuration parameter.
*/
std::string name;
/**
* The value of the configuration parameter.
*/
T value;
/**
* The source of the configuration paremeter.
*/
std::string source;
}; // class ConfigParamAndSource
} // namespace tapebridge
} // namespace tape
} // namespace castor
#endif // CASTOR_TAPE_TAPEBRIDGE_CONFIGPARAMANDSOURCE
......@@ -126,6 +126,12 @@ namespace tapebridge {
*/
const char EMPTYVSN[CA_MAXVSNLEN+1] = "";
/**
* The compile-time default value of the tapebridged configuration parameter
* named TAPEBRIDGED/USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES.
*/
const bool TAPEBRIDGED_USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES = false;
} // namespace tapebridge
} // namespace tape
} // namespace castor
......
/* This file was generated by ./DlfMessagesCodeGenerator on Fri Jun 24 11:22:18 CEST 2011
/* This file was generated by ./DlfMessagesCodeGenerator on Wed Jul 13 15:36:45 CEST 2011
*/
/******************************************************************************
......@@ -148,7 +148,8 @@ TAPEBRIDGE_FAILED_TO_PARSE_TPCONFIG=111, /* "Failed to parse TPCONFIG file" */
TAPEBRIDGE_PARSED_TPCONFIG=112, /* "Parsed TPCONFIG" */
TAPEBRIDGE_CLOSED_RTCPD_DISK_TAPE_CONNECTION_DUE_TO_PEER=113, /* "Closed rtcpd disk/tape IO control connection due to rtcpd closing its end" */
TAPEBRIDGE_TOO_MANY_DRIVES_IN_TPCONFIG=114, /* "There are more drives in the TPCONFIG file than there were when tapebridged was started. Please restart tapebridged." */
TAPEBRIDGE_RECEIVED_TAPEBRIDGE_FLUSHEDTOTAPE=115 /* "Received TAPEBRIDGE_FLUSHEDTOTAPE" */
TAPEBRIDGE_RECEIVED_TAPEBRIDGE_FLUSHEDTOTAPE=115, /* "Received TAPEBRIDGE_FLUSHEDTOTAPE" */
TAPEBRIDGE_CONFIG_PARAM=116 /* "Determined value of configuration parameter" */
}; // enum TapeBridgeDlfMessages
} // namespace tapebridge
} // namespace tape
......
/* This file was generated by ./DlfMessagesCodeGenerator on Fri Jun 24 11:22:18 CEST 2011
/* This file was generated by ./DlfMessagesCodeGenerator on Wed Jul 13 15:36:45 CEST 2011
*/
/******************************************************************************
......@@ -145,4 +145,5 @@ castor::dlf::Message castor::tape::tapebridge::TapeBridgeDaemon::s_dlfMessages[]
{TAPEBRIDGE_CLOSED_RTCPD_DISK_TAPE_CONNECTION_DUE_TO_PEER, "Closed rtcpd disk/tape IO control connection due to rtcpd closing its end"},
{TAPEBRIDGE_TOO_MANY_DRIVES_IN_TPCONFIG, "There are more drives in the TPCONFIG file than there were when tapebridged was started. Please restart tapebridged."},
{TAPEBRIDGE_RECEIVED_TAPEBRIDGE_FLUSHEDTOTAPE, "Received TAPEBRIDGE_FLUSHEDTOTAPE"},
{TAPEBRIDGE_CONFIG_PARAM, "Determined value of configuration parameter"},
{-1, ""}};
......@@ -114,3 +114,4 @@
113,TAPEBRIDGE_CLOSED_RTCPD_DISK_TAPE_CONNECTION_DUE_TO_PEER,"Closed rtcpd disk/tape IO control connection due to rtcpd closing its end"
114,TAPEBRIDGE_TOO_MANY_DRIVES_IN_TPCONFIG,"There are more drives in the TPCONFIG file than there were when tapebridged was started. Please restart tapebridged."
115,TAPEBRIDGE_RECEIVED_TAPEBRIDGE_FLUSHEDTOTAPE,"Received TAPEBRIDGE_FLUSHEDTOTAPE"
116,TAPEBRIDGE_CONFIG_PARAM,"Determined value of configuration parameter"
......@@ -34,6 +34,7 @@
#include "castor/tape/tapebridge/VdqmRequestHandler.hpp"
#include "h/Cgetopt.h"
#include "h/common.h"
#include "h/Cuuid.h"
#include <algorithm>
#include <memory>
......@@ -122,13 +123,13 @@ int castor::tape::tapebridge::TapeBridgeDaemon::exceptionThrowingMain(
// Pass the foreground option to the super class BaseDaemon
m_foreground = m_parsedCommandLine.foregroundOptionSet;
// Extract the tape-drive names from the TPCONFIG file
utils::TpconfigLines tpconfigLines;
utils::parseTpconfigFile(TPCONFIGPATH, tpconfigLines);
std::list<std::string> driveNames;
utils::extractTpconfigDriveNames(tpconfigLines, driveNames);
// Put the drive names into a string stream ready to make a log message
// Put the tape-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++) {
......
......@@ -52,6 +52,7 @@
#include <algorithm>
#include <memory>
#include <string.h>
//-----------------------------------------------------------------------------
......@@ -124,6 +125,32 @@ void castor::tape::tapebridge::VdqmRequestHandler::run(void *param)
param = NULL; /* Will cause a segementation fault if used by accident */
}
// Determine whether or not buffered tape-marks should be used over multiple
// files
ConfigParamAndSource<bool> useBufferedTapeMarksOverMultipleFiles("UNKNOWN",
false, "UNKNOWN");
try {
useBufferedTapeMarksOverMultipleFiles =
getUseBufferedTapeMarksOverMultipleFiles();
} catch(castor::exception::Exception &ex) {
castor::dlf::Param params[] = {
castor::dlf::Param("Message", ex.getMessage().str()),
castor::dlf::Param("Code" , ex.code() )};
CASTOR_DLF_WRITEPC(cuuid, DLF_LVL_ERROR,
TAPEBRIDGE_TRANSFER_FAILED, params);
// Return
return;
}
// Log the whether or not buffered tape-marks will be used over multiple files
castor::dlf::Param params[] = {
castor::dlf::Param("name" , useBufferedTapeMarksOverMultipleFiles.name),
castor::dlf::Param("value" , useBufferedTapeMarksOverMultipleFiles.value),
castor::dlf::Param("source", useBufferedTapeMarksOverMultipleFiles.source)};
castor::dlf::dlf_writep(cuuid, DLF_LVL_SYSTEM, TAPEBRIDGE_CONFIG_PARAM,
params);
// Job request to be received from VDQM
legacymsg::RtcpJobRqstMsgBody jobRequest;
utils::setBytes(jobRequest, '\0');
......@@ -579,3 +606,67 @@ void castor::tape::tapebridge::VdqmRequestHandler::
<< ": Peer Host: " << peerHost);
}
}
//------------------------------------------------------------------------------
// getUseBufferedTapeMarksOverMultipleFiles
//------------------------------------------------------------------------------
castor::tape::tapebridge::ConfigParamAndSource<bool>
castor::tape::tapebridge::VdqmRequestHandler::
getUseBufferedTapeMarksOverMultipleFiles()
throw(castor::exception::Exception) {
const std::string paramName =
"TAPEBRIDGED/USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES";
const char *paramCStr = NULL;
uint32_t paramBool = false;
std::string paramSource = "UNKNOWN";
// Try to get the number of disk-IO threads from the environment variables
if(NULL != (paramCStr = getenv(
"TAPEBRIDGED_USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES"))) {
paramSource = "environment variable";
std::string paramUpperCaseStr = paramCStr;
utils::toUpper(paramUpperCaseStr);
if("FALSE" == paramUpperCaseStr) {
paramBool = false;
} else if("TRUE" == paramUpperCaseStr) {
paramBool = true;
} else {
castor::exception::InvalidArgument ex;
ex.getMessage() <<
"Configuration parameter is not a valid unsigned integer"
": name=" << paramName <<
" value=" << paramCStr <<
" source=" << paramSource;
throw(ex);
}
// Else try to get the number of disk IO threads of castor.conf
} else if(NULL != (paramCStr = getconfent("TAPEBRIDGED",
"USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES", 0))) {
paramSource = "castor.conf";
std::string paramUpperCaseStr = paramCStr;
utils::toUpper(paramUpperCaseStr);
if("FALSE" == paramUpperCaseStr) {
paramBool = false;
} else if("TRUE" == paramUpperCaseStr) {
paramBool = true;
} else {
castor::exception::InvalidArgument ex;
ex.getMessage() <<
"Configuration parameter is not a valid unsigned integer"
": name=" << paramName <<
" value=" << paramCStr <<
" source=" << paramSource;
throw(ex);
}
// Else use the compile-time default
} else {
paramSource = "compile-time default";
paramBool = TAPEBRIDGED_USEBUFFEREDTAPEMARKSOVERMULTIPLEFILES;
}
return ConfigParamAndSource<bool>(paramName, paramBool, paramSource);
}
......@@ -28,6 +28,7 @@
#include "castor/io/ServerSocket.hpp"
#include "castor/server/IThread.hpp"
#include "castor/tape/tapebridge/BoolFunctor.hpp"
#include "castor/tape/tapebridge/ConfigParamAndSource.hpp"
#include "castor/tape/tapebridge/Counter.hpp"
#include "castor/tape/legacymsg/RtcpJobRqstMsgBody.hpp"
#include "castor/tape/tapegateway/Volume.hpp"
......@@ -81,6 +82,20 @@ public:
*/
virtual void stop() throw();
/**
* Determines the whether or not the tapebridged daemon will cause
* tape-migrations to use buffered tape-marks over multiple files.
*
* This method deteremines the required value by first reading the
* environment variables, then if unsuccessful by reading castor.conf and
* finally if still unsuccessfull by using the compile-time default.
*
* @return The configuration parameter including its source, either
* "environment variable", "castor.conf" or "compile-time default".
*/
ConfigParamAndSource<bool>
getUseBufferedTapeMarksOverMultipleFiles()
throw(castor::exception::Exception);
private:
......
/******************************************************************************
* test/castor/tape/tapebridge/BridgeProtocolEngineTest.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@cern.ch
*****************************************************************************/
#ifndef TEST_CASTOR_TAPE_TAPEBRIDGE_BRIDGEPROTOCOLENGINETEST_HPP
#define TEST_CASTOR_TAPE_TAPEBRIDGE_BRIDGEPROTOCOLENGINETEST_HPP 1
#include "test_exception.hpp"
#include "castor/tape/legacymsg/RtcpJobRqstMsgBody.hpp"
#include "castor/tape/tapebridge/BridgeProtocolEngine.hpp"
#include "castor/tape/tapebridge/Counter.hpp"
#include "castor/tape/tapegateway/Volume.hpp"
#include "h/Cuuid.h"
#include "h/rtcpd_constants.h"
#include <cppunit/extensions/HelperMacros.h>
#include <exception>
#include <stdlib.h>
class BridgeProtocolEngineTest: public CppUnit::TestFixture {
private:
/**
* BoolFunctor that always returns false.
*/
class FalseBoolFunctor : public castor::tape::tapebridge::BoolFunctor {
public:
/**
* Always returns false.
*/
bool operator()() {
return false;
}
};
castor::tape::legacymsg::RtcpJobRqstMsgBody m_jobRequest;
castor::tape::tapegateway::Volume m_volume;
FalseBoolFunctor m_stoppingGracefully;
castor::tape::tapebridge::Counter<uint64_t> m_tapebridgeTransactionCounter;
castor::tape::tapebridge::BridgeProtocolEngine *m_engine;
public:
BridgeProtocolEngineTest():
m_tapebridgeTransactionCounter(0), m_engine(NULL) {
memset(&m_jobRequest, '\0', sizeof(m_jobRequest));
}
void setUp() {
const Cuuid_t &cuuid = nullCuuid; // Dummy value
const int listenSock = 0; // Dummy value
const int initialRtcpdSock = 0; // Dummy value
const uint32_t nbFilesOnDestinationTape = 0; // Dummy value
setenv("PATH_CONFIG", "/etc/castor/castor.conf", 1);
unsetenv("RTCPD_THREAD_POOL");
m_tapebridgeTransactionCounter.reset(0);
m_engine = new castor::tape::tapebridge::BridgeProtocolEngine(
cuuid,
listenSock,
initialRtcpdSock,
m_jobRequest,
m_volume,
nbFilesOnDestinationTape,
m_stoppingGracefully,
m_tapebridgeTransactionCounter
);
}
void tearDown() {
setenv("PATH_CONFIG", "/etc/castor/castor.conf", 1);
unsetenv("RTCPD_THREAD_POOL");
delete(m_engine);
}
void testGetNbRtcpdDiskIOThreadsInvalidEnv() {
castor::tape::tapebridge::ConfigParamAndSource<uint32_t>
nbRtcpdDiskIOThreads("UNKNOWN NAME", 0, "UNKNOWN SOURCE");
CPPUNIT_ASSERT_EQUAL_MESSAGE("setenv RTCPD_THREAD_POOL",
0,
setenv("RTCPD_THREAD_POOL", "INVALID_UINT_VALUE", 1));
CPPUNIT_ASSERT_THROW_MESSAGE("Invalid environment variable",
nbRtcpdDiskIOThreads = m_engine->getNbRtcpdDiskIOThreads(),
castor::exception::InvalidArgument);
std::string exceptionMsg = "UNKNOWN";
try {
nbRtcpdDiskIOThreads = m_engine->getNbRtcpdDiskIOThreads();
} catch(castor::exception::InvalidArgument &ex) {
exceptionMsg = ex.getMessage().str();
}
CPPUNIT_ASSERT_EQUAL_MESSAGE("exceptionMsg",
std::string("Configuration parameter is not a valid unsigned integer:"
" name=RTCPD/THREAD_POOL"
" value=INVALID_UINT_VALUE"
" source=environment variable"),
exceptionMsg);
}
void testGetNbRtcpdDiskIOThreadsEnv() {
castor::tape::tapebridge::ConfigParamAndSource<uint32_t>
nbRtcpdDiskIOThreads("UNKNOWN NAME", 0, "UNKNOWN SOURCE");
CPPUNIT_ASSERT_EQUAL_MESSAGE("setenv RTCPD_THREAD_POOL",
0,
setenv("RTCPD_THREAD_POOL", "11111", 1));
CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"getNbRtcpdDiskIOThreads",
nbRtcpdDiskIOThreads = m_engine->getNbRtcpdDiskIOThreads());
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.name",
std::string("RTCPD/THREAD_POOL"),
nbRtcpdDiskIOThreads.name);
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.value",
(uint32_t)11111,
nbRtcpdDiskIOThreads.value);
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.source",
std::string("environment variable"),
nbRtcpdDiskIOThreads.source);
}
void testGetNbRtcpdDiskIOThreadsInvalidPathConfig() {
castor::tape::tapebridge::ConfigParamAndSource<uint32_t>
nbRtcpdDiskIOThreads("UNKNOWN NAME", 0, "UNKNOWN SOURCE");
CPPUNIT_ASSERT_EQUAL_MESSAGE("setenv PATH_CONFIG",
0,
setenv("PATH_CONFIG", "INVALID PATH CONFIG", 1));
CPPUNIT_ASSERT_NO_THROW_MESSAGE(
"getNbRtcpdDiskIOThreads",
nbRtcpdDiskIOThreads = m_engine->getNbRtcpdDiskIOThreads());
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.name",
std::string("RTCPD/THREAD_POOL"),
nbRtcpdDiskIOThreads.name);
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.value",
(uint32_t)RTCPD_THREAD_POOL,
nbRtcpdDiskIOThreads.value);
CPPUNIT_ASSERT_EQUAL_MESSAGE("nbRtcpdDiskIOThreads.source",
std::string("compile-time default"),
nbRtcpdDiskIOThreads.source);
}
void testGetNbRtcpdDiskIOThreadsInvalidLocalCastorConf() {
castor::tape::tapebridge::ConfigParamAndSource<uint32_t>
nbRtcpdDiskIOThreads("UNKNOWN NAME", 0, "UNKNOWN SOURCE");
CPPUNIT_ASSERT_EQUAL_MESSAGE("setenv PATH_CONFIG",