Mercurial > hg > heapstats
view agent/src/heapstats-engines/configuration.cpp @ 247:33a77b567b62
Bug 3293: [REFACTORING] Realtime deadlock detector implementation
Reviewed-by: ykubota
https://github.com/HeapStats/heapstats/pull/115
author | Yasumasa Suenaga <yasuenag@gmail.com> |
---|---|
date | Wed, 02 Aug 2017 14:46:00 +0900 |
parents | 03baa55848c2 |
children |
line wrap: on
line source
/*! * \file configuration.cpp * \brief This file treats HeapStats configuration. * Copyright (C) 2014-2017 Yasumasa Suenaga * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include "globals.hpp" #include "fsUtil.hpp" #include "signalManager.hpp" #include "configuration.hpp" #if USE_PCRE #include "pcreRegex.hpp" #else #include "cppRegex.hpp" #endif /* Macro define. */ /*! * \brief Macro of return code length.<br /> * E.g. linux is 1(LF), mac is 1(CR), windows is 2 (CRLF). */ #define RETURN_CODE_LEN 1 /*! * \brief Constructor of TConfiguration. */ TConfiguration::TConfiguration(TJvmInfo *info) { jvmInfo = info; isLoaded = false; firstCollected = false; /* Don't collected yet, */ /* Initialize each configurations. */ initializeConfig(NULL); } /*! * \brief Copy constructor of TConfiguration. */ TConfiguration::TConfiguration(const TConfiguration &src) { jvmInfo = src.jvmInfo; isLoaded = false; // Set to false to load configuration from src. alertThreshold = src.alertThreshold; heapAlertThreshold = src.heapAlertThreshold; /* Initialize each configurations. */ initializeConfig(&src); isLoaded = src.isLoaded; } /*! * \brief Initialize each configurations. * * \param src Source operand of configuration. * If this value is not NULL, each configurations are copied from * src. */ void TConfiguration::initializeConfig(const TConfiguration *src) { configs.clear(); if (src == NULL) { attach = new TBooleanConfig(this, "attach", true); fileName = new TStringConfig(this, "file", (char *)"heapstats_snapshot.dat", &ReadStringValue, (TStringConfig::TFinalizer) & free); heapLogFile = new TStringConfig(this, "heaplogfile", (char *)"heapstats_log.csv", &ReadStringValue, (TStringConfig::TFinalizer) & free); archiveFile = new TStringConfig(this, "archivefile", (char *)"heapstats_analyze.zip", &ReadStringValue, (TStringConfig::TFinalizer) & free); logFile = new TStringConfig(this, "logfile", (char *)"", &ReadStringValue, (TStringConfig::TFinalizer) & free); reduceSnapShot = new TBooleanConfig(this, "reduce_snapshot", true); collectRefTree = new TBooleanConfig(this, "collect_reftree", true); triggerOnFullGC = new TBooleanConfig(this, "trigger_on_fullgc", true, &setOnewayBooleanValue); triggerOnDump = new TBooleanConfig(this, "trigger_on_dump", true, &setOnewayBooleanValue); checkDeadlock = new TBooleanConfig(this, "check_deadlock", false, &setOnewayBooleanValue); triggerOnLogError = new TBooleanConfig(this, "trigger_on_logerror", true, &setOnewayBooleanValue); triggerOnLogSignal = new TBooleanConfig(this, "trigger_on_logsignal", true, &setOnewayBooleanValue); triggerOnLogLock = new TBooleanConfig(this, "trigger_on_loglock", true); rankLevel = new TIntConfig(this, "rank_level", 5); logLevel = new TLogLevelConfig(this, "loglevel", INFO, &setLogLevel); order = new TRankOrderConfig(this, "rank_order", DELTA); alertPercentage = new TIntConfig(this, "alert_percentage", 50); heapAlertPercentage = new TIntConfig(this, "javaheap_alert_percentage", 95); metaspaceThreshold = new TLongConfig(this, "metaspace_alert_threshold", 0); timerInterval = new TLongConfig(this, "snapshot_interval", 0); logInterval = new TLongConfig(this, "log_interval", 300); firstCollect = new TBooleanConfig(this, "first_collect", true); logSignalNormal = new TStringConfig(this, "logsignal_normal", NULL, &setSignalValue, (TStringConfig::TFinalizer) & free); logSignalAll = new TStringConfig(this, "logsignal_all", (char *)"SIGUSR2", &setSignalValue, (TStringConfig::TFinalizer) & free); reloadSignal = new TStringConfig(this, "signal_reload", (char *)"SIGHUP", &setSignalValue, (TStringConfig::TFinalizer) & free); threadRecordEnable = new TBooleanConfig(this, "thread_record_enable", false); threadRecordBufferSize = new TLongConfig(this, "thread_record_buffer_size", 100); threadRecordFileName = new TStringConfig( this, "thread_record_filename", (char *)"heapstats-thread-records.htr", &ReadStringValue, (TStringConfig::TFinalizer) & free); threadRecordIOTracer = new TStringConfig( this, "thread_record_iotracer", (char *)DEFAULT_CONF_DIR "/IoTrace.class", &ReadStringValue, (TStringConfig::TFinalizer) & free); snmpSend = new TBooleanConfig(this, "snmp_send", false, &setOnewayBooleanValue); snmpTarget = new TStringConfig(this, "snmp_target", (char *)"localhost", &setSnmpTarget, (TStringConfig::TFinalizer) & free); snmpComName = new TStringConfig(this, "snmp_comname", (char *)"public", &setSnmpComName, (TStringConfig::TFinalizer) & free); snmpLibPath = new TStringConfig(this, "snmp_libpath", (char *)LIBNETSNMP_PATH, &setSnmpLibPath, (TStringConfig::TFinalizer) & free); logDir = new TStringConfig(this, "logdir", (char *)"./tmp", &ReadStringValue, (TStringConfig::TFinalizer) & free); archiveCommand = new TStringConfig( this, "archive_command", (char *)"/usr/bin/zip %archivefile% -jr %logdir%", &ReadStringValue, (TStringConfig::TFinalizer) & free); killOnError = new TBooleanConfig(this, "kill_on_error", false); } else { attach = new TBooleanConfig(*src->attach); fileName = new TStringConfig(*src->fileName); heapLogFile = new TStringConfig(*src->heapLogFile); archiveFile = new TStringConfig(*src->archiveFile); logFile = new TStringConfig(*src->logFile); reduceSnapShot = new TBooleanConfig(*src->reduceSnapShot); collectRefTree = new TBooleanConfig(*src->collectRefTree); triggerOnFullGC = new TBooleanConfig(*src->triggerOnFullGC); triggerOnDump = new TBooleanConfig(*src->triggerOnDump); checkDeadlock = new TBooleanConfig(*src->checkDeadlock); triggerOnLogError = new TBooleanConfig(*src->triggerOnLogError); triggerOnLogSignal = new TBooleanConfig(*src->triggerOnLogSignal); triggerOnLogLock = new TBooleanConfig(*src->triggerOnLogLock); rankLevel = new TIntConfig(*src->rankLevel); logLevel = new TLogLevelConfig(*src->logLevel); order = new TRankOrderConfig(*src->order); alertPercentage = new TIntConfig(*src->alertPercentage); heapAlertPercentage = new TIntConfig(*src->heapAlertPercentage); metaspaceThreshold = new TLongConfig(*src->metaspaceThreshold); timerInterval = new TLongConfig(*src->timerInterval); logInterval = new TLongConfig(*src->logInterval); firstCollect = new TBooleanConfig(*src->firstCollect); logSignalNormal = new TStringConfig(*src->logSignalNormal); logSignalAll = new TStringConfig(*src->logSignalAll); reloadSignal = new TStringConfig(*src->reloadSignal); threadRecordEnable = new TBooleanConfig(*src->threadRecordEnable); threadRecordBufferSize = new TLongConfig(*src->threadRecordBufferSize); threadRecordFileName = new TStringConfig(*src->threadRecordFileName); threadRecordIOTracer = new TStringConfig(*src->threadRecordIOTracer); snmpSend = new TBooleanConfig(*src->snmpSend); snmpTarget = new TStringConfig(*src->snmpTarget); snmpComName = new TStringConfig(*src->snmpComName); snmpLibPath = new TStringConfig(*src->snmpLibPath); logDir = new TStringConfig(*src->logDir); archiveCommand = new TStringConfig(*src->archiveCommand); killOnError = new TBooleanConfig(*src->killOnError); } configs.push_back(attach); configs.push_back(fileName); configs.push_back(heapLogFile); configs.push_back(archiveFile); configs.push_back(logFile); configs.push_back(reduceSnapShot); configs.push_back(collectRefTree); configs.push_back(triggerOnFullGC); configs.push_back(triggerOnDump); configs.push_back(checkDeadlock); configs.push_back(triggerOnLogError); configs.push_back(triggerOnLogSignal); configs.push_back(triggerOnLogLock); configs.push_back(rankLevel); configs.push_back(logLevel); configs.push_back(order); configs.push_back(alertPercentage); configs.push_back(heapAlertPercentage); configs.push_back(metaspaceThreshold); configs.push_back(timerInterval); configs.push_back(logInterval); configs.push_back(firstCollect); configs.push_back(logSignalNormal); configs.push_back(logSignalAll); configs.push_back(reloadSignal); configs.push_back(threadRecordEnable); configs.push_back(threadRecordBufferSize); configs.push_back(threadRecordFileName); configs.push_back(threadRecordIOTracer); configs.push_back(snmpSend); configs.push_back(snmpTarget); configs.push_back(snmpComName); configs.push_back(snmpLibPath); configs.push_back(logDir); configs.push_back(archiveCommand); configs.push_back(killOnError); } /*! * \brief Destructor of TConfiguration. */ TConfiguration::~TConfiguration() { for (std::list<TConfigElementSuper *>::iterator itr = configs.begin(); itr != configs.end(); itr++) { delete *itr; } } /*! * \brief Read boolean value from configuration. * \param value [in] Value of this configuration. * \return value which is represented by boolean. */ bool TConfiguration::ReadBooleanValue(const char *value) { if (strcmp(value, "true") == 0) { return true; } else if (strcmp(value, "false") == 0) { return false; } else { throw "Illegal boolean value"; } } /*! * \brief Read string value from configuration. * \param value [in] Value of this configuration. * \param dest [in] [out] Destination of this configuration. */ void TConfiguration::ReadStringValue(TConfiguration *inst, char *value, char **dest) { if (*dest != NULL) { free(*dest); } *dest = value == NULL ? NULL : strdup(value); } /*! * \brief Read string value for signal from configuration. * \param value [in] Value of this configuration. * \param dest [in] [out] Destination of this configuration. */ void TConfiguration::ReadSignalValue(const char *value, char **dest) { if ((value == NULL) || (value[0] == '\0')) { if (*dest != NULL) { free(*dest); } *dest = NULL; } else if (TSignalManager::findSignal(value) != -1) { if (*dest != NULL) { free(*dest); } *dest = strdup(value); } else { throw "Illegal signal name"; } } /*! * \brief Read long/int value from configuration. * \param value [in] Value of this configuration. * \param max_val [in] Max value of this parameter. * \return value which is represented by long. */ long TConfiguration::ReadLongValue(const char *value, const jlong max_val) { /* Convert to number from string. */ char *done = NULL; errno = 0; jlong temp = strtoll(value, &done, 10); /* If all string is able to convert to number. */ if ((*done == '\0') && (temp <= max_val) && (temp >= 0)) { return temp; } else if (((temp == LLONG_MIN) || (temp == LLONG_MAX)) && (errno != 0)) { throw errno; } else { throw "Illegal number"; } } /*! * \brief Read order value from configuration. * \param value [in] Value of this configuration. * \return value which is represented by TRankOrder. */ TRankOrder TConfiguration::ReadRankOrderValue(const char *value) { if (strcmp(value, "usage") == 0) { return USAGE; } else if (strcmp(value, "delta") == 0) { return DELTA; } else { throw "Illegal order"; } } /*! * \brief Read log level value from configuration. * \param value [in] Value of this configuration. * \return value which is represented by TLogLevel. */ TLogLevel TConfiguration::ReadLogLevelValue(const char *value) { if (strcmp(value, "CRIT") == 0) { return CRIT; } else if (strcmp(value, "WARN") == 0) { return WARN; } else if (strcmp(value, "INFO") == 0) { return INFO; } else if (strcmp(value, "DEBUG") == 0) { return DEBUG; } else { throw "Illegal level"; } } /*! * \brief Load configuration from file. * \param filename [in] Read configuration file path. */ void TConfiguration::loadConfiguration(const char *filename) { /* Check filename. */ if (filename == NULL || strlen(filename) == 0) { return; } /* Open file. */ FILE *conf = fopen(filename, "r"); if (unlikely(conf == NULL)) { logger->printWarnMsgWithErrno("Could not open configuration file: %s", filename); return; } #if USE_PCRE TPCRERegex confRegex("^\\s*(\\S+?)\\s*=\\s*(\\S+)?\\s*$", 9); #else TCPPRegex confRegex("^\\s*(\\S+?)\\s*=\\s*(\\S+)?\\s*$"); #endif /* Get string line from configure file. */ long lineCnt = 0; char *lineBuff = NULL; size_t lineBuffLen = 0; /* Read line. */ while (likely(getline(&lineBuff, &lineBuffLen, conf) > 0)) { lineCnt++; /* If this line is empty. */ if (unlikely(strlen(lineBuff) <= RETURN_CODE_LEN)) { /* skip this line. */ continue; } /* Remove comments */ char *comment = strchr(lineBuff, '#'); if (comment != NULL) { *comment = '\0'; } /* Check matched pair. */ if (confRegex.find(lineBuff)) { /* Key and value variables. */ char *key = confRegex.group(1); char *value; try { value = confRegex.group(2); } catch (const char *errStr) { logger->printDebugMsg(errStr); value = (char *)calloc(1, sizeof(char)); } /* Check key name. */ try { applyConfig(key, value); } catch (const char *errStr) { logger->printWarnMsg("Configuration error(key=%s, value=%s): %s", key, value, errStr); } catch (int err) { errno = err; logger->printWarnMsgWithErrno("Configuration error(key=%s, value=%s) ", key, value); } /* Cleanup after param setting. */ free(key); free(value); } } /* Cleanup after load file. */ if (likely(lineBuff != NULL)) { free(lineBuff); } fclose(conf); isLoaded = true; firstCollected = false; } /*! * \brief Print setting information. */ void TConfiguration::printSetting(void) { /* Agent attach state. */ logger->printInfoMsg("Agent Attach Enable = %s", attach->get() ? "true" : "false"); /* Output filenames. */ logger->printInfoMsg("SnapShot FileName = %s", fileName->get()); logger->printInfoMsg("Heap Log FileName = %s", heapLogFile->get()); logger->printInfoMsg("Archive FileName = %s", archiveFile->get()); logger->printInfoMsg( "Console Log FileName = %s", strlen(logFile->get()) > 0 ? logFile->get() : "None (output to console)"); /* Output log-level. */ logger->printInfoMsg("LogLevel = %s", getLogLevelAsString()); /* Output about reduce SnapShot. */ logger->printInfoMsg("ReduceSnapShot = %s", reduceSnapShot->get() ? "true" : "false"); /* Output whether collecting reftree. */ logger->printInfoMsg("CollectRefTree = %s", collectRefTree->get() ? "true" : "false"); /* Output status of snapshot triggers. */ logger->printInfoMsg("Trigger on FullGC = %s", triggerOnFullGC->get() ? "true" : "false"); logger->printInfoMsg("Trigger on DumpRequest = %s", triggerOnDump->get() ? "true" : "false"); /* Output status of deadlock check. */ logger->printInfoMsg("Deadlock check = %s", checkDeadlock->get() ? "true" : "false"); /* Output status of logging triggers. */ logger->printInfoMsg("Log trigger on Error = %s", triggerOnLogError->get() ? "true" : "false"); logger->printInfoMsg("Log trigger on Signal = %s", triggerOnLogSignal->get() ? "true" : "false"); logger->printInfoMsg("Log trigger on Deadlock = %s", triggerOnLogLock->get() ? "true" : "false"); /* Output about ranking. */ logger->printInfoMsg("RankingOrder = %s", getRankOrderAsString()); logger->printInfoMsg("RankLevel = %d", rankLevel->get()); /* Output about heap alert. */ if (alertThreshold <= 0) { logger->printInfoMsg("HeapAlert is DISABLED."); } else { logger->printInfoMsg("AlertPercentage = %d ( %lu bytes )", alertPercentage->get(), alertThreshold); } /* Output about heap alert. */ if (heapAlertThreshold <= 0) { logger->printInfoMsg("Java heap usage alert is DISABLED."); } else { logger->printInfoMsg("Java heap usage alert percentage = %d ( %lu MB )", heapAlertPercentage->get(), heapAlertThreshold / 1024 / 1024); } /* Output about metaspace alert. */ const char *label = jvmInfo->isAfterCR6964458() ? "Metaspace" : "PermGen"; if (metaspaceThreshold <= 0) { logger->printInfoMsg("%s usage alert is DISABLED.", label); } else { logger->printInfoMsg("%s usage alert threshold %lu MB", label, metaspaceThreshold->get() / 1024 / 1024); } /* Output about interval snapshot. */ if (timerInterval == 0) { logger->printInfoMsg("Interval SnapShot is DISABLED."); } else { logger->printInfoMsg("SnapShot interval = %d sec", timerInterval->get()); } /* Output about interval logging. */ if (logInterval->get() == 0) { logger->printInfoMsg("Interval Logging is DISABLED."); } else { logger->printInfoMsg("Log interval = %d sec", logInterval->get()); } logger->printInfoMsg("First collect log = %s", firstCollect->get() ? "true" : "false"); /* Output logging signal name. */ char *normalSig = logSignalNormal->get(); if (normalSig == NULL || strlen(normalSig) == 0) { logger->printInfoMsg("Signal for normal logging is DISABLED."); } else { logger->printInfoMsg("Signal for normal logging = %s", normalSig); } char *allSig = logSignalAll->get(); if (allSig == NULL || strlen(allSig) == 0) { logger->printInfoMsg("Signal for all logging is DISABLED."); } else { logger->printInfoMsg("Signal for all logging = %s", allSig); } char *reloadSig = reloadSignal->get(); if (reloadSig == NULL || strlen(reloadSig) == 0) { logger->printInfoMsg("Signal for config reloading is DISABLED."); } else { logger->printInfoMsg("Signal for config reloading = %s", reloadSig); } /* Thread recorder. */ logger->printInfoMsg("Thread recorder = %s", threadRecordEnable->get() ? "true" : "false"); logger->printInfoMsg("Buffer size of thread recorder = %ld MB", threadRecordBufferSize->get()); logger->printInfoMsg("Thread record file name = %s", threadRecordFileName->get()); logger->printInfoMsg("Thread record I/O tracer = %s", threadRecordIOTracer->get()); /* Output about SNMP trap. */ logger->printInfoMsg("Send SNMP Trap = %s", snmpSend->get() ? "true" : "false"); logger->printInfoMsg("SNMP target = %s", snmpTarget->get()); logger->printInfoMsg("SNMP community = %s", snmpComName->get()); logger->printInfoMsg("NET-SNMP client library path = %s", snmpLibPath->get()); /* Output temporary log directory path. */ logger->printInfoMsg("Temporary log directory = %s", logDir->get()); /* Output archive command. */ logger->printInfoMsg("Archive command = \"%s\"", archiveCommand->get()); /* Output about force killing JVM. */ logger->printInfoMsg("Kill on Error = %s", killOnError->get() ? "true" : "false"); } /*! * \brief Validate this configuration.. * \return Return true if all configuration is valid. */ bool TConfiguration::validate(void) { bool result = true; /* File check */ TStringConfig *filenames[] = {fileName, heapLogFile, archiveFile, logFile, logDir, NULL}; for (TStringConfig **elmt = filenames; *elmt != NULL; elmt++) { if (strlen((*elmt)->get()) == 0) { // "" means "disable", not a file path like "./". continue; } try { if (!isValidPath((*elmt)->get())) { throw "Permission denied"; } } catch (const char *message) { logger->printWarnMsg("%s: %s = %s", message, (*elmt)->getConfigName(), (*elmt)->get()); result = false; } catch (int errnum) { logger->printWarnMsgWithErrno("Configuration error: %s = %s", (*elmt)->getConfigName(), (*elmt)->get()); result = false; } } /* Range check */ TIntConfig *percentages[] = {alertPercentage, heapAlertPercentage, NULL}; for (TIntConfig **percentage = percentages; *percentage != NULL; percentage++) { if (((*percentage)->get() < 0) || ((*percentage)->get() > 100)) { logger->printWarnMsg("Out of range: %s = %d", (*percentage)->getConfigName(), (*percentage)->get()); result = false; } } /* Set alert threshold. */ jlong maxMem = this->jvmInfo->getMaxMemory(); alertThreshold = (maxMem == -1) ? -1 : (maxMem * alertPercentage->get() / 100); heapAlertThreshold = (maxMem == -1) ? -1 : (maxMem * heapAlertPercentage->get() / 100); /* Signal check */ char *reloadSig = reloadSignal->get(); char *normalSig = logSignalNormal->get(); char *allSig = logSignalAll->get(); if (reloadSig != NULL) { if ((normalSig != NULL) && (strcmp(normalSig, reloadSig) == 0)) { logger->printWarnMsg( "Cannot set same signal: logsignal_normal & signal_reload"); result = false; } if ((allSig != NULL) && (strcmp(allSig, reloadSig) == 0)) { logger->printWarnMsg( "Cannot set same signal: logsignal_all & signal_reload"); result = false; } } if ((normalSig != NULL) && (allSig != NULL) && (strcmp(normalSig, allSig) == 0)) { logger->printWarnMsg( "Cannot set same signal: logsignal_normal & logsignal_all"); result = false; } /* Thread recorder check */ if (threadRecordEnable->get()) { if (threadRecordBufferSize <= 0) { logger->printWarnMsg("Invalid value: thread_record_buffer_size = %ld", threadRecordBufferSize->get()); result = false; } else if (!isValidPath(threadRecordFileName->get())) { logger->printWarnMsg("Permission denied: thread_record_filename = %s", threadRecordFileName->get()); result = false; } } /* SNMP check */ if (snmpSend->get()) { if (snmpLibPath->get() == NULL) { logger->printWarnMsg("snmp_libpath must be set when snmp_send is set."); result = false; } if ((snmpTarget->get() == NULL) || (strlen(snmpTarget->get()) == 0)) { logger->printWarnMsg("snmp_target have to be set when snmp_send is set"); result = false; } if ((snmpComName->get() == NULL) || (strlen(snmpComName->get()) == 0)) { logger->printWarnMsg("snmp_comname have to be set when snmp_send is set"); result = false; } } return result; } /*! * \brief Merge configuration from others. * \param src Pointer of source configuration. */ void TConfiguration::merge(TConfiguration *src) { attach->set(src->attach->get()); fileName->set(src->fileName->get()); heapLogFile->set(src->heapLogFile->get()); archiveFile->set(src->archiveFile->get()); logFile->set(src->logFile->get()); rankLevel->set(src->rankLevel->get()); logLevel->set(src->logLevel->get()); reduceSnapShot->set(src->reduceSnapShot->get()); collectRefTree->set(src->collectRefTree->get()); triggerOnFullGC->set(triggerOnFullGC->get() && src->triggerOnFullGC->get()); triggerOnDump->set(triggerOnDump->get() && src->triggerOnDump->get()); checkDeadlock->set(checkDeadlock->get() && src->checkDeadlock->get()); triggerOnLogError->set(triggerOnLogError->get() && src->triggerOnLogError->get()); triggerOnLogSignal->set(triggerOnLogSignal->get() && src->triggerOnLogSignal->get()); triggerOnLogLock->set(triggerOnLogLock->get() && src->triggerOnLogLock->get()); order->set(src->order->get()); alertPercentage->set(src->alertPercentage->get()); heapAlertPercentage->set(src->heapAlertPercentage->get()); metaspaceThreshold->set(src->metaspaceThreshold->get()); timerInterval->set(src->timerInterval->get()); logInterval->set(src->logInterval->get()); firstCollect->set(src->firstCollect->get()); threadRecordFileName->set(src->threadRecordFileName->get()); snmpSend->set(snmpSend->get() & src->snmpSend->get()); logDir->set(src->logDir->get()); archiveCommand->set(src->archiveCommand->get()); killOnError->set(src->killOnError->get()); } /*! * \brief Apply value to configuration which is presented by key. * \param key Key of configuration. * \param value New value. * \exception Throws const char * or int which presents error. */ void TConfiguration::applyConfig(char *key, char *value) { for (std::list<TConfigElementSuper *>::iterator itr = configs.begin(); itr != configs.end(); itr++) { if (strcmp((*itr)->getConfigName(), key) == 0) { switch ((*itr)->getConfigDataType()) { case BOOLEAN: ((TBooleanConfig *)*itr)->set(ReadBooleanValue(value)); break; case INTEGER: ((TIntConfig *)*itr)->set(ReadLongValue(value, INT_MAX)); break; case LONG: ((TLongConfig *)*itr)->set(ReadLongValue(value, JLONG_MAX)); break; case STRING: ((TStringConfig *)*itr)->set(value); break; case LOGLEVEL: ((TLogLevelConfig *)*itr)->set(ReadLogLevelValue(value)); break; case RANKORDER: ((TRankOrderConfig *)*itr)->set(ReadRankOrderValue(value)); break; } } } } void TConfiguration::setLogLevel(TConfiguration *inst, TLogLevel val, TLogLevel *dest) { *dest = val; logger->setLogLevel(val); }