1 #include "otsdaq/ConfigurationInterface/ConfigurationHandler.h"
2 #include "otsdaq/ConfigurationInterface/TimeFormatter.h"
4 #include "otsdaq/Macros/CoutMacros.h"
5 #include "otsdaq/XmlUtilities/ConvertFromXML.h"
6 #include "otsdaq/XmlUtilities/ConvertToXML.h"
7 #include "otsdaq/XmlUtilities/DOMTreeErrorReporter.h"
9 #include <xercesc/dom/DOMElement.hpp>
10 #include <xercesc/dom/DOMImplementation.hpp>
11 #include <xercesc/dom/DOMImplementationRegistry.hpp>
12 #include <xercesc/dom/DOMLSOutput.hpp>
13 #include <xercesc/dom/DOMLSSerializer.hpp>
14 #include <xercesc/dom/DOMNodeList.hpp>
15 #include <xercesc/dom/DOMText.hpp>
16 #include <xercesc/parsers/XercesDOMParser.hpp>
17 #include <xercesc/util/XMLUni.hpp>
20 #include <xercesc/framework/LocalFileFormatTarget.hpp>
21 #include <xercesc/util/OutOfMemoryException.hpp>
23 #include <sys/types.h>
31 #include "otsdaq/TableCore/TableBase.h"
36 #define __COUT_HDR__ "ConfigHandler"
40 XMLCh* ConfigurationHandler::rootTag_ = 0;
41 XMLCh* ConfigurationHandler::headerTag_ = 0;
42 XMLCh* ConfigurationHandler::typeTag_ = 0;
43 XMLCh* ConfigurationHandler::extensionTableNameTag_ = 0;
44 XMLCh* ConfigurationHandler::nameTag_ = 0;
45 XMLCh* ConfigurationHandler::runTag_ = 0;
46 XMLCh* ConfigurationHandler::runTypeTag_ = 0;
47 XMLCh* ConfigurationHandler::runNumberTag_ = 0;
48 XMLCh* ConfigurationHandler::runBeginTimestampTag_ = 0;
49 XMLCh* ConfigurationHandler::locationTag_ = 0;
50 XMLCh* ConfigurationHandler::datasetTag_ = 0;
51 XMLCh* ConfigurationHandler::versionTag_ = 0;
52 XMLCh* ConfigurationHandler::commentDescriptionTag_ = 0;
53 XMLCh* ConfigurationHandler::createdByUserTag_ = 0;
54 XMLCh* ConfigurationHandler::partTag_ = 0;
55 XMLCh* ConfigurationHandler::nameLabelTag_ = 0;
56 XMLCh* ConfigurationHandler::kindOfPartTag_ = 0;
57 XMLCh* ConfigurationHandler::dataTag_ = 0;
60 ConfigurationHandler::ConfigurationHandler(
void) {}
63 ConfigurationHandler::~ConfigurationHandler(
void) {}
66 void ConfigurationHandler::initPlatform(
void)
70 xercesc::XMLPlatformUtils::Initialize();
72 catch(xercesc::XMLException& e)
74 __MOUT_ERR__ <<
"XML toolkit initialization error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
78 rootTag_ = xercesc::XMLString::transcode(
"ROOT");
79 headerTag_ = xercesc::XMLString::transcode(
"HEADER");
80 typeTag_ = xercesc::XMLString::transcode(
"TYPE");
81 extensionTableNameTag_ = xercesc::XMLString::transcode(
"EXTENSION_TABLE_NAME");
82 nameTag_ = xercesc::XMLString::transcode(
"NAME");
83 runTag_ = xercesc::XMLString::transcode(
"RUN");
84 runTypeTag_ = xercesc::XMLString::transcode(
"RUN_TYPE");
85 runNumberTag_ = xercesc::XMLString::transcode(
"RUN_NUMBER");
86 runBeginTimestampTag_ = xercesc::XMLString::transcode(
"RUN_BEGIN_TIMESTAMP");
87 locationTag_ = xercesc::XMLString::transcode(
"LOCATION");
88 datasetTag_ = xercesc::XMLString::transcode(
"DATA_SET");
89 versionTag_ = xercesc::XMLString::transcode(
"VERSION");
90 commentDescriptionTag_ = xercesc::XMLString::transcode(
"COMMENT_DESCRIPTION");
91 createdByUserTag_ = xercesc::XMLString::transcode(
"CREATED_BY_USER");
92 partTag_ = xercesc::XMLString::transcode(
"PART");
93 nameLabelTag_ = xercesc::XMLString::transcode(
"NAME_LABEL");
94 kindOfPartTag_ = xercesc::XMLString::transcode(
"KIND_OF_PART");
95 dataTag_ = xercesc::XMLString::transcode(
"DATA");
99 void ConfigurationHandler::terminatePlatform(
void)
103 xercesc::XMLString::release(&rootTag_);
104 xercesc::XMLString::release(&headerTag_);
105 xercesc::XMLString::release(&typeTag_);
106 xercesc::XMLString::release(&extensionTableNameTag_);
107 xercesc::XMLString::release(&nameTag_);
108 xercesc::XMLString::release(&runTag_);
109 xercesc::XMLString::release(&runTypeTag_);
110 xercesc::XMLString::release(&runNumberTag_);
111 xercesc::XMLString::release(&runBeginTimestampTag_);
112 xercesc::XMLString::release(&locationTag_);
113 xercesc::XMLString::release(&datasetTag_);
114 xercesc::XMLString::release(&versionTag_);
115 xercesc::XMLString::release(&commentDescriptionTag_);
116 xercesc::XMLString::release(&createdByUserTag_);
117 xercesc::XMLString::release(&partTag_);
118 xercesc::XMLString::release(&nameLabelTag_);
119 xercesc::XMLString::release(&kindOfPartTag_);
120 xercesc::XMLString::release(&dataTag_);
124 __MOUT_ERR__ <<
"Unknown exception encountered in TagNames destructor" << std::endl;
129 xercesc::XMLPlatformUtils::Terminate();
131 catch(xercesc::XMLException& e)
133 __MOUT_ERR__ <<
"XML ttolkit teardown error: " << XML_TO_CHAR(e.getMessage()) << std::endl;
138 bool ConfigurationHandler::validateNode(XMLCh* tagName, xercesc::DOMNode* node,
const std::string& expectedValue)
140 if(node->getFirstChild() == 0)
142 __COUT__ <<
"Tag " << XML_TO_CHAR(tagName) <<
" doesn't have a value!" << std::endl;
146 if(XML_TO_STRING(node->getFirstChild()->getNodeValue()) != expectedValue)
148 __COUT__ <<
"The tag " << XML_TO_CHAR(tagName) <<
" with value " << XML_TO_CHAR(node->getFirstChild()->getNodeValue())
149 <<
" doesn't match the expected value " << expectedValue << std::endl;
157 xercesc::DOMNode* ConfigurationHandler::getNode(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
159 return getNode(tagName, dynamic_cast<xercesc::DOMElement*>(parent), itemNumber);
163 xercesc::DOMNode* ConfigurationHandler::getNode(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
165 xercesc::DOMNodeList* nodeList = parent->getElementsByTagName(tagName);
169 throw(std::runtime_error(std::string(
"Can't find ") + XML_TO_STRING(tagName) +
" tag!"));
170 __COUT__ << (std::string(
"Can't find ") + XML_TO_STRING(tagName) +
" tag!") << std::endl;
178 return nodeList->item(itemNumber);
182 xercesc::DOMElement* ConfigurationHandler::getElement(XMLCh* tagName, xercesc::DOMNode* parent,
unsigned int itemNumber)
184 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
188 xercesc::DOMElement* ConfigurationHandler::getElement(XMLCh* tagName, xercesc::DOMElement* parent,
unsigned int itemNumber)
190 return dynamic_cast<xercesc::DOMElement*
>(getNode(tagName, parent, itemNumber));
194 void ConfigurationHandler::readXML(
TableBase* table,
TableVersion version) { readXML(*table, version); }
200 std::string configFile = getXMLFileName(table, version);
202 __COUT__ <<
"Reading: " << configFile << std::endl;
203 __COUT__ <<
"Into View with Table Name: " << table.getViewP()->getTableName() << std::endl;
204 __COUT__ <<
"Into View with version: " << table.getViewP()->getVersion() <<
" and version-to-read: " << version << std::endl;
206 struct stat fileStatus;
208 if(stat(configFile.c_str(), &fileStatus) < 0)
210 __COUT__ <<
"Error reading path: " << configFile << std::endl;
211 std::stringstream ss;
214 ss << (
"Path file_name does not exist.");
215 else if(errno == ENOTDIR)
216 ss << (
"A component of the path is not a directory.");
217 else if(errno == ELOOP)
218 ss << (
"Too many symbolic links encountered while traversing the path.");
219 else if(errno == EACCES)
220 ss << (
"Permission denied.");
221 else if(errno == ENAMETOOLONG)
222 ss << (
"File name too long.");
224 ss << (
"File can not be read.");
226 __COUT_ERR__ << ss.str();
230 xercesc::XercesDOMParser* parser =
new xercesc::XercesDOMParser;
233 parser->setValidationScheme(xercesc::XercesDOMParser::Val_Auto);
234 parser->setDoNamespaces(
true);
235 parser->setDoSchema(
false);
238 parser->useCachedGrammarInParse(
false);
240 parser->setErrorHandler(errorHandler);
246 parser->parse(configFile.c_str());
250 xercesc::DOMDocument* document = parser->getDocument();
253 xercesc::DOMElement* elementRoot = document->getDocumentElement();
256 throw(std::runtime_error(
"empty XML document"));
259 xercesc::DOMNode* headerNode = getNode(headerTag_, elementRoot, 0);
261 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(headerTag_)));
265 xercesc::DOMElement* typeElement = getElement(typeTag_, headerNode, 0);
267 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(typeTag_)));
268 xercesc::DOMNode* extensionTableNameNode = getNode(extensionTableNameTag_, typeElement, 0);
269 if(!validateNode(extensionTableNameTag_, extensionTableNameNode, table.getView().getTableName()))
270 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(extensionTableNameTag_)));
271 xercesc::DOMNode* nameNode = getNode(nameTag_, typeElement, 0);
272 if(!validateNode(nameTag_, nameNode, table.getTableName()))
273 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(nameTag_)));
279 xercesc::DOMElement* runElement = getElement(runTag_, headerNode, 0);
281 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(runTag_)));
282 [[maybe_unused]] xercesc::DOMNode* runTypeNode = getNode(runTypeTag_, runElement, 0);
283 assert(validateNode(runTypeTag_, runTypeNode, table.getTableName()));
284 xercesc::DOMNode* runNumberNode = getNode(runNumberTag_, runElement, 0);
286 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(runNumberTag_)));
287 xercesc::DOMNode* runBeginTimestampNode = getNode(runBeginTimestampTag_, runElement, 0);
288 if(!runBeginTimestampNode)
289 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(runBeginTimestampTag_)));
290 xercesc::DOMNode* locationNode = getNode(locationTag_, runElement, 0);
292 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(locationTag_)));
300 xercesc::DOMElement* datasetElement = getElement(datasetTag_, elementRoot, 0);
302 throw(std::runtime_error(std::string(
"The document is missing the mandatory tag: ") + XML_TO_STRING(datasetTag_)));
311 xercesc::DOMNode* versionNode = getNode(versionTag_, datasetElement, 0);
313 if(versionNode->getFirstChild() == 0)
315 throw(std::runtime_error(std::string(
"Missing version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())));
319 char tmpVersionStr[100];
320 sprintf(tmpVersionStr,
"%d", version.version());
321 __COUT__ << version <<
"-" << XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) << std::endl;
322 if(strcmp(tmpVersionStr, XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue())) != 0)
323 throw(std::runtime_error(std::string(
"Mis-matched version tag: ") + XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()) +
" vs " +
327 table.getViewP()->setVersion(XML_TO_CHAR(versionNode->getFirstChild()->getNodeValue()));
329 xercesc::DOMNode* commentDescriptionNode = getNode(commentDescriptionTag_, datasetElement, 0);
330 if(commentDescriptionNode->getFirstChild() != 0)
331 table.getViewP()->setComment(XML_TO_CHAR(commentDescriptionNode->getFirstChild()->getNodeValue()));
333 xercesc::DOMNode* createdByUserNode = getNode(createdByUserTag_, datasetElement, 0);
334 if(createdByUserNode->getFirstChild() != 0)
335 table.getViewP()->setAuthor(XML_TO_CHAR(createdByUserNode->getFirstChild()->getNodeValue()));
339 xercesc::DOMNodeList* dataNodeList = datasetElement->getElementsByTagName(dataTag_);
342 throw(std::runtime_error(std::string(
"Can't find ") + XML_TO_STRING(dataTag_) +
" tag!"));
348 if(!dataNodeList->getLength())
350 __SS__ <<
"Must be non-empty data set!";
357 table.getViewP()->resizeDataView(dataNodeList->getLength(), table.getView().getNumberOfColumns());
359 for(XMLSize_t row = 0; row < dataNodeList->getLength(); row++)
363 xercesc::DOMNodeList* columnNodeList = dataNodeList->item(row)->getChildNodes();
364 unsigned int colNumber = 0;
368 for(XMLSize_t col = 0; col < columnNodeList->getLength(); col++)
372 if(!columnNodeList->item(col)->getNodeType() ||
373 columnNodeList->item(col)->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
376 xercesc::DOMElement* columnElement =
dynamic_cast<xercesc::DOMElement*
>(columnNodeList->item(col));
378 if(table.getView().getColumnInfo(colNumber).getStorageName() != XML_TO_STRING(columnElement->getTagName()))
380 std::stringstream error;
381 error << __COUT_HDR__ << std::endl
382 <<
"The column number " << colNumber <<
" named " << table.getView().getColumnInfo(colNumber).getStorageName()
383 <<
" defined in the view " << table.getView().getTableName() <<
" doesn't match the file column order, since the " << colNumber + 1
384 << (colNumber == 0 ?
"st" : (colNumber == 1 ?
"nd" : (colNumber == 2 ?
"rd" :
"th"))) <<
" element found in the file at "
385 << XML_TO_CHAR(dataTag_) <<
" tag number " << row <<
" is " << XML_TO_CHAR(columnElement->getTagName());
386 __MOUT_ERR__ << error.str();
387 throw(std::runtime_error(error.str()));
397 table.getViewP()->setValueAsString(XML_TO_STRING(columnNodeList->item(col)->getFirstChild()->getNodeValue()), row, colNumber);
404 catch(xercesc::XMLException& e)
406 __COUT__ <<
"Error parsing file: " << configFile << std::endl;
407 std::ostringstream errBuf;
408 errBuf <<
"Error parsing file: " << XML_TO_CHAR(e.getMessage()) << std::flush;
411 __COUT__ <<
"Done with table file: " << configFile << std::endl;
419 std::string ConfigurationHandler::writeXML(
const TableBase& table)
423 std::string configFile = getXMLFileName(table,
424 table.getViewVersion());
427 xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"Core"));
428 if(implementation != 0)
433 xercesc::DOMDocument* document = implementation->createDocument(0,
437 xercesc::DOMElement* rootElement = document->getDocumentElement();
438 rootElement->setAttribute(CONVERT_TO_XML(
"xmlns:xsi"), CONVERT_TO_XML(
"http://www.w3.org/2001/XMLSchema-instance"));
439 rootElement->setAttribute(CONVERT_TO_XML(
"xsi:noNamespaceSchemaLocation"),
440 CONVERT_TO_XML(
"TableBase.xsd"));
446 xercesc::DOMElement* headerElement = document->createElement(headerTag_);
447 rootElement->appendChild(headerElement);
450 xercesc::DOMElement* typeElement = document->createElement(typeTag_);
451 headerElement->appendChild(typeElement);
453 xercesc::DOMElement* extensionTableNameElement = document->createElement(extensionTableNameTag_);
454 typeElement->appendChild(extensionTableNameElement);
455 xercesc::DOMText* extensionTableNameValue = document->createTextNode(CONVERT_TO_XML(table.getView().getTableName().c_str()));
456 extensionTableNameElement->appendChild(extensionTableNameValue);
458 xercesc::DOMElement* nameElement = document->createElement(nameTag_);
459 typeElement->appendChild(nameElement);
460 xercesc::DOMText* nameValue = document->createTextNode(CONVERT_TO_XML(table.getTableName().c_str()));
461 nameElement->appendChild(nameValue);
465 xercesc::DOMElement* runElement = document->createElement(runTag_);
466 headerElement->appendChild(runElement);
468 xercesc::DOMElement* runTypeElement = document->createElement(runTypeTag_);
469 runElement->appendChild(runTypeElement);
470 xercesc::DOMText* runTypeValue = document->createTextNode(CONVERT_TO_XML(table.getTableName().c_str()));
471 runTypeElement->appendChild(runTypeValue);
473 xercesc::DOMElement* runNumberElement = document->createElement(runNumberTag_);
474 runElement->appendChild(runNumberElement);
475 xercesc::DOMText* runNumberValue = document->createTextNode(CONVERT_TO_XML(
"1"));
476 runNumberElement->appendChild(runNumberValue);
478 xercesc::DOMElement* runBeginTimestampElement = document->createElement(runBeginTimestampTag_);
479 runElement->appendChild(runBeginTimestampElement);
480 xercesc::DOMText* runBeginTimestampValue = document->createTextNode(CONVERT_TO_XML(TimeFormatter::getTime().c_str()));
484 runBeginTimestampElement->appendChild(runBeginTimestampValue);
486 xercesc::DOMElement* locationElement = document->createElement(locationTag_);
487 runElement->appendChild(locationElement);
488 xercesc::DOMText* locationValue = document->createTextNode(CONVERT_TO_XML(
"CERN P5"));
490 locationElement->appendChild(locationValue);
493 xercesc::DOMElement* datasetElement = document->createElement(datasetTag_);
494 rootElement->appendChild(datasetElement);
496 xercesc::DOMElement* partElement = document->createElement(partTag_);
497 datasetElement->appendChild(partElement);
499 xercesc::DOMElement* nameLabelElement = document->createElement(nameLabelTag_);
500 partElement->appendChild(nameLabelElement);
501 xercesc::DOMText* nameLabelValue = document->createTextNode(CONVERT_TO_XML(
"CMS--ROOT"));
502 nameLabelElement->appendChild(nameLabelValue);
504 xercesc::DOMElement* kindOfPartElement = document->createElement(kindOfPartTag_);
505 partElement->appendChild(kindOfPartElement);
506 xercesc::DOMText* kindOfPartValue = document->createTextNode(CONVERT_TO_XML(
"Detector ROOT"));
507 kindOfPartElement->appendChild(kindOfPartValue);
509 xercesc::DOMElement* versionElement = document->createElement(versionTag_);
510 datasetElement->appendChild(versionElement);
511 xercesc::DOMText* versionValue = document->createTextNode(CONVERT_TO_XML(table.getView().getVersion().version()));
512 versionElement->appendChild(versionValue);
514 xercesc::DOMElement* commentDescriptionElement = document->createElement(commentDescriptionTag_);
515 datasetElement->appendChild(commentDescriptionElement);
516 xercesc::DOMText* commentDescriptionValue = document->createTextNode(CONVERT_TO_XML(table.getView().getComment().c_str()));
517 commentDescriptionElement->appendChild(commentDescriptionValue);
519 xercesc::DOMElement* createdByUserElement = document->createElement(createdByUserTag_);
520 datasetElement->appendChild(createdByUserElement);
521 xercesc::DOMText* createdByUserValue = document->createTextNode(CONVERT_TO_XML(table.getView().getAuthor().c_str()));
522 createdByUserElement->appendChild(createdByUserValue);
526 for(
unsigned int row = 0; row < table.getView().getNumberOfRows(); row++)
528 xercesc::DOMElement* dataElement = document->createElement(dataTag_);
529 datasetElement->appendChild(dataElement);
531 for(
unsigned int col = 0; col < table.getView().getNumberOfColumns(); col++)
533 xercesc::DOMElement* element = document->createElement(CONVERT_TO_XML(table.getView().getColumnInfo(col).getStorageName().c_str()));
534 dataElement->appendChild(element);
535 xercesc::DOMText* value = document->createTextNode(CONVERT_TO_XML(table.getView().getDataView()[row][col].c_str()));
536 element->appendChild(value);
540 outputXML(document, configFile);
544 catch(
const xercesc::OutOfMemoryException&)
546 XERCES_STD_QUALIFIER cerr <<
"OutOfMemoryException" << XERCES_STD_QUALIFIER endl;
549 catch(
const xercesc::DOMException& e)
551 XERCES_STD_QUALIFIER cerr <<
"DOMException code is: " << e.code << XERCES_STD_QUALIFIER endl;
554 catch(
const xercesc::XMLException& e)
556 std::string message = XML_TO_STRING(e.getMessage());
557 __COUT__ <<
"Error Message: " << message << std::endl;
563 XERCES_STD_QUALIFIER cerr <<
"An error occurred creating the document" << XERCES_STD_QUALIFIER endl;
569 XERCES_STD_QUALIFIER cerr <<
"Requested implementation is not supported" << XERCES_STD_QUALIFIER endl;
580 void ConfigurationHandler::outputXML(xercesc::DOMDocument* pmyDOMDocument, std::string fileName)
582 std::string directory = fileName.substr(0, fileName.rfind(
"/") + 1);
583 __COUT__ <<
"Saving XML to " << fileName <<
" in directory: " << directory << std::endl;
585 mkdir(directory.c_str(), 0755);
591 xercesc::DOMImplementation* implementation = xercesc::DOMImplementationRegistry::getDOMImplementation(CONVERT_TO_XML(
"LS"));
593 #if _XERCES_VERSION >= 30000
596 xercesc::DOMLSSerializer* serializer = ((xercesc::DOMImplementationLS*)implementation)->createLSSerializer();
600 if(serializer->getDomConfig()->canSetParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true))
601 serializer->getDomConfig()->setParameter(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
609 xercesc::XMLFormatTarget* formatTarget =
new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName));
612 xercesc::DOMLSOutput* output = ((xercesc::DOMImplementationLS*)implementation)->createLSOutput();
615 output->setByteStream(formatTarget);
618 serializer->write(pmyDOMDocument, output);
621 xercesc::DOMWriter* serializer = ((xercesc::DOMImplementationLS*)implementation)->createDOMWriter();
623 serializer->setFeature(xercesc::XMLUni::fgDOMWRTFormatPrettyPrint,
true);
635 xercesc::XMLFormatTarget* formatTarget =
new xercesc::LocalFileFormatTarget(CONVERT_TO_XML(fileName.c_str()));
638 serializer->writeNode(formatTarget, *pmyDOMDocument);
643 serializer->release();
647 #if _XERCES_VERSION >= 30000
652 __COUT__ <<
"Done writing " << std::endl;
656 std::string ConfigurationHandler::writeXML(
const TableBase* table) {
return writeXML(*table); }
661 std::stringstream fileName;
662 fileName << getXMLDir(&table) << version <<
'/' << table.getTableName() <<
"_v" << version <<
".xml";
663 return fileName.str();
667 std::string ConfigurationHandler::getXMLDir(
const TableBase* table)
669 return std::string(__ENV__(
"CONFIGURATION_DATA_PATH")) +
'/' + table->getTableName() +
'/';