All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
XMLFileCatalog.cpp
Go to the documentation of this file.
1 #include "xercesc/framework/LocalFileFormatTarget.hpp"
2 #include "xercesc/framework/MemBufInputSource.hpp"
3 #include "xercesc/sax/SAXParseException.hpp"
4 #include "xercesc/sax/EntityResolver.hpp"
5 #include "xercesc/sax/InputSource.hpp"
6 #include "xercesc/parsers/XercesDOMParser.hpp"
7 #include "xercesc/util/PlatformUtils.hpp"
8 #include "xercesc/util/XercesDefs.hpp"
9 #include "xercesc/util/XMLUni.hpp"
10 #include "xercesc/util/XMLURL.hpp"
11 #include "xercesc/util/XMLString.hpp"
12 #include "xercesc/dom/DOM.hpp"
13 
14 #include "GaudiKernel/MsgStream.h"
15 #include "GaudiKernel/Service.h"
16 #include <Gaudi/PluginService.h>
17 
18 #include "createGuidAsString.h"
19 #include "XMLFileCatalog.h"
20 
21 #include <fstream>
22 #include <iostream>
23 #include <stdexcept>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 
27 using namespace xercesc;
28 using namespace Gaudi;
29 using namespace std;
30 
31 #if _XERCES_VERSION <= 30000
32 // API change between XercesC 2 and 3
33 #define setIdAttribute(a, b) setIdAttribute(a)
34 #endif
35 
36 
38 
39 namespace {
40 
41  typedef const string& CSTR;
42  inline string _toString(const XMLCh *toTranscode) {
43  char * buff = XMLString::transcode(toTranscode);
44  string tmp(buff==0 ? "" : buff);
45  XMLString::release(&buff);
46  return tmp;
47  }
48  struct __Init {
49  __Init() {
50  try { XMLPlatformUtils::Initialize(); }
51  catch (const XMLException& e) {
52  cout << "Xerces-c error in initialization:" << _toString(e.getMessage()) << endl;
53  }
54  }
55  ~__Init() {
56  XMLPlatformUtils::Terminate();
57  }
58  };
59  __Init __In__;
60 
61  struct XMLStr {
62  XMLCh* m_xml;
63  XMLStr(CSTR c) { m_xml=XMLString::transcode(c.c_str()); }
64  ~XMLStr() { if (m_xml) XMLString::release(&m_xml); }
65  operator const XMLCh*() const { return m_xml; }
66  };
67  struct XMLTag : public XMLStr {
68  string m_str;
69  XMLTag(CSTR s) : XMLStr(s), m_str(s) { }
70  ~XMLTag() { }
71  operator CSTR () const { return m_str; }
72  };
73  // bool operator==(const XMLTag& b, CSTR c) { return c==b.m_str; }
74  bool operator==(CSTR c, const XMLTag& b) { return c==b.m_str; }
75  struct XMLCollection {
76  DOMElement* m_node;
77  XMLCollection(DOMNode* n, bool use_children=true) : m_node((DOMElement*)n) {
78  if ( use_children ) {
79  if ( m_node ) m_node = (DOMElement*)m_node->getFirstChild();
80  if ( m_node && m_node->getNodeType() != DOMNode::ELEMENT_NODE ) ++(*this);
81  }
82  }
83  operator bool() const { return m_node; }
84  operator DOMNode* () const { return m_node; }
85  operator DOMElement* () const { return m_node; }
86  DOMElement* operator->() const { return m_node; }
87  string attr(const XMLTag& tag) const { return _toString(m_node->getAttribute(tag));}
88  string attr(CSTR tag) const { return attr(XMLTag(tag)); }
89  string tag() const { return _toString(m_node->getTagName()); }
90  void operator++() {
91  while(m_node) {
92  m_node = (DOMElement*)m_node->getNextSibling();
93  if ( m_node && m_node->getNodeType() == DOMNode::ELEMENT_NODE ) {
94  return;
95  }
96  }
97  }
98  };
99  struct ErrHandler : public ErrorHandler {
101  IMessageSvc* m_msg;
103  ErrHandler(IMessageSvc* m) : m_msg(m) {}
105  void resetErrors() override { }
107  void warning(const SAXParseException& /* e */) override { }
109  void error(const SAXParseException& e) override;
111  void fatalError(const SAXParseException& e) override;
112  ~ErrHandler() override {}
113  };
114  struct DTDRedirect : public EntityResolver {
115  InputSource* resolveEntity(const XMLCh* const /* pubId */, const XMLCh* const /* sysId */) override {
116  static const char* dtdID = "redirectinmem.dtd";
117  static const char* dtd = \
118  "\
119  <!ELEMENT POOLFILECATALOG (META*,File*)>\
120  <!ELEMENT META EMPTY>\
121  <!ELEMENT File (physical,logical,metadata*)>\
122  <!ATTLIST META name CDATA #REQUIRED>\
123  <!ATTLIST META type CDATA #REQUIRED>\
124  <!ELEMENT physical (pfn)+>\
125  <!ELEMENT logical (lfn)*>\
126  <!ELEMENT metadata EMPTY>\
127  <!ELEMENT lfn EMPTY>\
128  <!ELEMENT pfn EMPTY>\
129  <!ATTLIST File ID ID #REQUIRED>\
130  <!ATTLIST pfn name ID #REQUIRED>\
131  <!ATTLIST pfn filetype CDATA #IMPLIED>\
132  <!ATTLIST pfn se CDATA #IMPLIED>\
133  <!ATTLIST lfn name ID #REQUIRED>\
134  <!ATTLIST metadata att_name CDATA #REQUIRED>\
135  <!ATTLIST metadata att_value CDATA #REQUIRED>\
136  ";
137  static const size_t len = strlen(dtd);
138  return new MemBufInputSource((const XMLByte*)dtd,len,dtdID,false);
139  }
140  ~DTDRedirect() override = default;
141  };
142 
143  void ErrHandler::error(const SAXParseException& e) {
144  string m(_toString(e.getMessage()));
145  if (m.find("The values for attribute 'name' must be names or name tokens")!=string::npos ||
146  m.find("The values for attribute 'ID' must be names or name tokens")!=string::npos ||
147  m.find("for attribute 'name' must be Name or Nmtoken")!=string::npos ||
148  m.find("for attribute 'ID' must be Name or Nmtoken")!=string::npos ||
149  m.find("for attribute 'name' is invalid Name or NMTOKEN value")!=string::npos ||
150  m.find("for attribute 'ID' is invalid Name or NMTOKEN value")!=string::npos )
151  return;
152  string sys(_toString(e.getSystemId()));
153  MsgStream log(m_msg,"XMLCatalog");
154  log << MSG::ERROR << "Error at file \"" << sys
155  << "\", line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endmsg
156  << "Message: " << m << endmsg;
157  }
158  void ErrHandler::fatalError(const SAXParseException& e) {
159  MsgStream log(m_msg,"XMLCatalog");
160  string m(_toString(e.getMessage()));
161  string sys(_toString(e.getSystemId()));
162  log << MSG::ERROR << "Fatal Error at file \"" << sys
163  << "\", line " << e.getLineNumber() << ", column " << e.getColumnNumber() << endmsg
164  << "Message: " << m << endmsg;
165  throw runtime_error( "Standard pool exception : Fatal Error on the DOM Parser" );
166  }
167 
168  const XMLTag EmptyCatalog("<!-- Edited By POOL -->\n"
169  "<!DOCTYPE POOLFILECATALOG SYSTEM \"InMemory\">\n"
170  "<POOLFILECATALOG>\n"
171  "</POOLFILECATALOG>\n");
172  const XMLTag PFNCOLL ("physical");
173  const XMLTag LFNCOLL ("logical");
174  const XMLTag PFNNODE ( "pfn");
175  const XMLTag LFNNODE ( "lfn");
176  const XMLTag Attr_type ( "type");
177  const XMLTag Attr_ID ( "ID");
178  const XMLTag Attr_name ( "name");
179  const XMLTag Attr_ftype ( "filetype");
180  const XMLTag MetaNode ( "metadata");
181  const XMLTag Attr_metaName ( "att_name");
182  const XMLTag Attr_metaValue ( "att_value");
183 }
184 
185 // ----------------------------------------------------------------------------
186 XMLFileCatalog::XMLFileCatalog(CSTR uri, IMessageSvc* m)
187 : m_rdOnly(false),m_update(false),m_doc(0),
188  m_file(uri), m_msgSvc(m)
189 {
190 }
191 // ----------------------------------------------------------------------------
194  return createGuidAsString();
195 }
196 // ----------------------------------------------------------------------------
197 DOMDocument* XMLFileCatalog::getDoc(bool throw_if_no_exists) const {
198  if ( !m_doc && throw_if_no_exists )
199  printError("The XML catalog was not started.",true);
200  return m_doc;
201 }
202 // ----------------------------------------------------------------------------
203 void XMLFileCatalog::printError(CSTR msg, bool rethrow) const {
204  MsgStream log(m_msgSvc,"XMLCatalog");
205  log << MSG::FATAL << msg << endmsg;
206  if ( rethrow ) {
207  throw runtime_error("XMLFileCatalog> "+msg);
208  }
209 }
210 // ----------------------------------------------------------------------------
212  string xmlFile = getfile(false);
213  try{
214  m_parser.reset( new XercesDOMParser );
215  m_parser->setValidationScheme(XercesDOMParser::Val_Auto);
216  m_parser->setDoNamespaces(false);
217  DTDRedirect dtdinmem;
218  m_parser->setEntityResolver(&dtdinmem);
219  if ( ! m_errHdlr ) m_errHdlr.reset( new ErrHandler(m_msgSvc) );
220  m_parser->setErrorHandler(m_errHdlr.get());
221  if ( !xmlFile.empty() ) {
222  m_parser->parse(xmlFile.c_str());
223  }
224  else {
225  const std::string& s = EmptyCatalog;
226  MemBufInputSource src((const XMLByte*)s.c_str(),s.length(),"MemCatalog");
227  m_parser->parse(src);
228  }
229  m_doc = m_parser->getDocument();
230  }
231  catch (const XMLException& e) {
232  printError("XML parse error["+xmlFile+"]: "+_toString(e.getMessage()));
233  }
234  catch (const DOMException& e) {
235  printError("XML parse error["+xmlFile+"]: "+_toString(e.getMessage()));
236  }
237  catch (...) {
238  printError("UNKNOWN XML parse error in file "+xmlFile);
239  }
240 }
241 // ----------------------------------------------------------------------------
242 string XMLFileCatalog::lookupFID(const std::string& fid) const {
243  std::string result;
244  DOMNode* e = element(fid,false);
245  e = e ? e->getParentNode() : 0; // Mode up to <logical>
246  e = e ? e->getParentNode() : 0; // Mode up to <File>
247  if ( e ) {
248  if ( e->getAttributes() ) { // Need to check this. The node may be no DOMElement
249  char* nam = XMLString::transcode(((DOMElement*)e)->getAttribute(Attr_ID));
250  if ( nam ) result = nam;
251  XMLString::release(&nam);
252  }
253  }
254  return result;
255 }
256 // ----------------------------------------------------------------------------
257 void XMLFileCatalog::getFID(Strings& fids) const {
258  fids.clear();
259  DOMNode* fde = getDoc(true)->getElementsByTagName(XMLStr("*"))->item(0);
260  for(XMLCollection c(child(fde,"File"), false); c; ++c)
261  fids.push_back(c.attr(Attr_ID));
262 }
263 // ----------------------------------------------------------------------------
264 void XMLFileCatalog::getPFN(CSTR fid, Files& files) const {
265  files.clear();
266  for(XMLCollection c(child(child(element(fid,false),PFNCOLL),PFNNODE), false); c; ++c)
267  files.emplace_back(c.attr(Attr_name),c.attr(Attr_ftype));
268 }
269 // ----------------------------------------------------------------------------
270 void XMLFileCatalog::getLFN(CSTR fid, Files& files) const {
271  files.clear();
272  for(XMLCollection c(child(child(element(fid,false),LFNCOLL),LFNNODE), false); c; ++c)
273  files.emplace_back(c.attr(Attr_name),fid);
274 }
275 // ----------------------------------------------------------------------------
276 void XMLFileCatalog::getMetaData(CSTR fid, Attributes& attr) const {
277  attr.clear();
278  for(XMLCollection c(child(element(fid),MetaNode), false); c; ++c)
279  attr.emplace_back(c.attr(Attr_metaName),c.attr(Attr_metaValue));
280  if ( attr.size() > 0 )
281  attr.emplace_back("guid",fid);
282 }
283 // ----------------------------------------------------------------------------
284 DOMNode* XMLFileCatalog::child(DOMNode* par,CSTR tag,CSTR attr,CSTR val) const {
285  for(XMLCollection c(par); c; ++c ) {
286  if( c.tag() == tag ) {
287  if( !attr.empty() && c.attr(attr) != val) continue;
288  return c;
289  }
290  }
291  return 0;
292 }
293 // ----------------------------------------------------------------------------
294 void XMLFileCatalog::setMetaData(CSTR fid, CSTR attr, CSTR val) const {
295  if ( !readOnly() ) {
296  DOMNode* node = element(fid);
297  DOMElement* mnod = (DOMElement*)child(node,MetaNode,Attr_metaName,attr);
298  if (!mnod){
299  mnod = getDoc(true)->createElement(MetaNode);
300  node->appendChild(mnod);
301  mnod->setAttribute(Attr_metaName,XMLStr(attr));
302  }
303  mnod->setAttribute(Attr_metaValue,XMLStr(val));
304  m_update = true;
305  return;
306  }
307  printError("Cannot update readonly catalog!");
308 }
309 // ----------------------------------------------------------------------------
310 string XMLFileCatalog::getMetaDataItem(CSTR fid,CSTR attr) const {
311  XMLCollection c(child(getDoc(true)->getElementById(XMLStr(fid)),MetaNode,Attr_metaName,attr));
312  return c ? c.attr(attr) : string("");
313 }
314 // ----------------------------------------------------------------------------
315 void XMLFileCatalog::dropMetaData(CSTR fid,CSTR attr) const {
316  vector<DOMNode*> gbc;
317  DOMNode* fn = getDoc(true)->getElementById(XMLStr(fid));
318  for(XMLCollection c{child(fn,MetaNode)}; c; ++c)
319  if ( attr[0]=='*' || !c.attr(attr).empty() ) gbc.push_back(c);
320  for(const auto &i : gbc)
321  fn->removeChild(i);
322 }
323 // ----------------------------------------------------------------------------
324 DOMNode* XMLFileCatalog::element(CSTR element_name,bool print_err) const {
325  DOMNode* node = getDoc(true)->getElementById(XMLStr(element_name));
326  if ( !node && print_err ) printError("Cannot find element:"+element_name);
327  return node;
328 }
329 // ----------------------------------------------------------------------------
331  DOMNode *pn = nullptr, *fn = element(fid);
332  if ( fn ) pn = fn->getParentNode();
333  if ( pn ) pn->removeChild(fn);
334 }
335 // ----------------------------------------------------------------------------
337  if ( !fid.empty() ) {
339  if ( res.first == 0 || res.second == 0 ) {
340  printError("Failed to register FID:"+fid);
341  }
342  return;
343  }
344  throw runtime_error("XMLFileCatalog> Cannot register LFN for invalid FID:"+fid);
345 }
346 // ----------------------------------------------------------------------------
348  if ( readOnly() ) {
349  printError("Cannot update readonly catalog!");
350  return { nullptr, nullptr};
351  }
352 
354  DOMElement *file = (DOMElement*)element(fid,false), *phyelem = 0, *logelem = 0;
355  DOMDocument* doc = getDoc(true);
356  if ( !file ) {
357  DOMNode* fde = doc->getElementsByTagName(XMLStr("*"))->item(0);
358  file = m_doc->createElement(XMLStr("File"));
359  file->setAttribute(Attr_ID, XMLStr(fid));
360  file->setIdAttribute(Attr_ID, true);
361  fde->appendChild(file);
362  m_update = true;
363  }
364  for(XMLCollection c1(file); c1; ++c1 ) {
365  char* nam = XMLString::transcode(c1->getNodeName());
366  if ( nam == PFNCOLL ) phyelem = c1;
367  if ( nam == LFNCOLL ) logelem = c1;
368  XMLString::release(&nam);
369  }
370  if ( !phyelem ) {
371  phyelem = doc->createElement(PFNCOLL);
372  file->appendChild(phyelem);
373  m_update = true;
374  }
375  if ( !logelem ) {
376  logelem = doc->createElement(LFNCOLL);
377  file->appendChild(logelem);
378  m_update = true;
379  }
380  return {logelem,phyelem};
381 }
382 // ----------------------------------------------------------------------------
383 void XMLFileCatalog::registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const {
384  if ( !fid.empty() ) {
386  DOMElement* phyelem = res.second, *fnelem = 0;
387  for(XMLCollection c(phyelem); c; ++c ) {
388  char* nam = XMLString::transcode(c->getNodeName());
389  if ( nam == PFNNODE ) {
390  XMLString::release(&nam);
391  nam = XMLString::transcode(c->getAttribute(Attr_name));
392  if ( nam == pfn ) {
393  XMLString::release(&nam);
394  fnelem = c;
395  break;
396  }
397  }
398  XMLString::release(&nam);
399  }
400  if ( !fnelem ) {
401  fnelem = getDoc(true)->createElement(PFNNODE);
402  phyelem->appendChild(fnelem);
403  fnelem->setAttribute(Attr_ftype,XMLStr(ftype));
404  fnelem->setAttribute(Attr_name,XMLStr(pfn));
405  fnelem->setIdAttribute(Attr_name, true);
406  m_update = true;
407  }
408  return;
409  }
410  throw runtime_error("XMLFileCatalog> Cannot register PFN for invalid FID:"+fid);
411 }
412 // ----------------------------------------------------------------------------
413 void XMLFileCatalog::registerLFN(CSTR fid, CSTR lfn) const {
414  if ( !fid.empty() ) {
416  DOMElement* logelem = res.first, *fnelem = 0;
417  for(XMLCollection c(logelem); c; ++c ) {
418  char* nam = XMLString::transcode(c->getNodeName());
419  if ( nam == LFNNODE ) {
420  XMLString::release(&nam);
421  nam = XMLString::transcode(c->getAttribute(Attr_name));
422  if ( nam == lfn ) {
423  XMLString::release(&nam);
424  fnelem = c;
425  break;
426  }
427  }
428  }
429  if ( !fnelem ) {
430  fnelem = getDoc(true)->createElement(LFNNODE);
431  logelem->appendChild(fnelem);
432  fnelem->setAttribute(Attr_name,XMLStr(lfn));
433  fnelem->setIdAttribute(Attr_name, true);
434  m_update = true;
435  }
436  return;
437  }
438  throw runtime_error("XMLFileCatalog> Cannot register LFN for invalid FID:"+fid);
439 }
440 // ----------------------------------------------------------------------------
442  try {
443  if ( dirty() && !readOnly() ) {
444  string xmlfile = getfile(true);
445  XMLStr ii("LS");
446  DOMImplementation *imp = DOMImplementationRegistry::getDOMImplementation(ii);
447  std::unique_ptr<XMLFormatTarget> tar{ new LocalFileFormatTarget(xmlfile.c_str()) };
448 #if _XERCES_VERSION <= 30000
449  DOMWriter *wr = imp->createDOMWriter();
450  wr->setFeature(XMLUni::fgDOMWRTFormatPrettyPrint, true);
451  wr->writeNode(tar.get(), *m_doc);
452  wr->release();
453 #else
454  DOMLSOutput *output = imp->createLSOutput();
455  output->setByteStream(tar.get());
456  DOMLSSerializer *wr = imp->createLSSerializer();
457  wr->getDomConfig()->setParameter(XMLStr("format-pretty-print"), true);
458  wr->write(m_doc, output);
459  output->release();
460  wr->release();
461 #endif
462  }
463  }
464  catch ( exception& e ) {
465  printError(string("Cannot open output file:")+e.what());
466  }
467  catch (...) {
468  printError("Unknown IO rrror.");
469  }
470 }
471 // ----------------------------------------------------------------------------
472 string XMLFileCatalog::getfile(bool create) {
473  string protocol, path;
474  XMLURL xerurl;
475  try{
476  xerurl = (const XMLCh*)XMLStr(m_file);
477  protocol = _toString(xerurl.getProtocolName());
478  path = _toString(xerurl.getPath());
479  }
480  catch (const XMLException& e ) {
481  printError(_toString(e.getMessage()));
482  }
483  if ( protocol.empty() ) {
484  printError("Missing protocol.");
485  }
486  else if ( protocol == "http" || protocol == "ftp" ) {
487  m_rdOnly = true;
488  }
489  else if ( protocol == "file" ) {
490  m_rdOnly = false;
491  struct stat buff;
492  int exist = ::stat(path.c_str(),&buff) != -1;
493  if ( create && !exist ) {
494  MsgStream log(m_msgSvc,"XMLCatalog");
495  log << MSG::INFO << "File '" << path << "' does not exist. New file created." << endmsg;
496  ofstream out{path};
497  if( !m_rdOnly && out.is_open() ) {
498  out << (CSTR)EmptyCatalog << endl;
499  }
500  else {
501  printError("Problem creating file "+path);
502  }
503  out.close();
504  }
505  else if ( exist ) {
506  return path;
507  }
508  else if ( !create ) {
509  return "";
510  }
511  }
512  else {
513  printError(protocol + ": protocol not supported.");
514  }
515  return path;
516 }
std::string getMetaDataItem(CSTR fid, CSTR name) const override
Access metadata item.
bool readOnly() const override
Check if the catalog is read-only.
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
T empty(T...args)
void registerPFN(CSTR fid, CSTR pfn, CSTR ftype) const override
Create a FileID and Node of the physical file name with all the attributes.
#define DECLARE_FACTORY(type, factory)
Definition: PluginService.h:25
T endl(T...args)
std::string lookupFID(CSTR lfn) const
Gaudi::PluginService::Factory< IInterface *, const std::string &, IMessageSvc * > Factory
Definition: IFileCatalog.h:33
STL namespace.
std::string getfile(bool create)
xercesc::DOMNode * element(CSTR fid, bool print_err=true) const
std::unique_ptr< xercesc::XercesDOMParser > m_parser
T release(T...args)
STL class.
T push_back(T...args)
STL class.
const std::string & CSTR
T what(T...args)
T strlen(T...args)
xercesc::DOMNode * child(xercesc::DOMNode *par, CSTR tag, CSTR attr="", CSTR val="") const
bool operator==(const GaudiUtils::Allocator< T1 > &, const GaudiUtils::Allocator< T2 > &)
Definition: Allocator.h:249
constexpr double m
Definition: SystemOfUnits.h:93
void getMetaData(CSTR fid, Attributes &attr) const override
Dump all MetaData of the catalog for a given file ID.
void printError(CSTR msg, bool throw_exc=true) const
std::unique_ptr< xercesc::ErrorHandler > m_errHdlr
The IMessage is the interface implemented by the message service.
Definition: IMessageSvc.h:57
xercesc::DOMDocument * m_doc
xercesc::DOMDocument * getDoc(bool throw_if_no_exists=true) const
const std::string CSTR
T reset(T...args)
void getLFN(CSTR fid, Files &files) const override
Dump all logical file names of the catalog associate to the FileID.
STL class.
T get(T...args)
T find(T...args)
T length(T...args)
void setMetaData(CSTR fid, CSTR name, CSTR value) const override
Insert/update metadata item.
STL class.
STL class.
std::string createGuidAsString()
Helper function creating file identifier using the UUID mechanism.
void registerLFN(CSTR fid, CSTR lfn) const override
Create a FileID and Node of the logical file name with all the attributes.
T c_str(T...args)
void commit() override
Save DOM catalog to file.
string s
Definition: gaudirun.py:245
std::pair< xercesc::DOMElement *, xercesc::DOMElement * > i_registerFID(CSTR fid) const
void init() override
Parse the DOM tree of the XML catalog.
IMessageSvc * m_msgSvc
void registerFID(CSTR fid) const override
Create a FileID and Node.
void getPFN(CSTR fid, Files &files) const override
Dump all physical file names of the catalog and their attributes associate to the FileID...
This class constitutes the core of the XML based FileCatalog API for POOL.
bool dirty() const override
Check if the catalog should be updated.
std::string createFID() const override
Catalog interface.
Helper functions to set/get the application return code.
Definition: __init__.py:1
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
void getFID(Strings &fids) const override
Dump all file Identifiers.
void dropMetaData(CSTR fid) const override
Drop all metadata of one FID.
void deleteFID(CSTR FileID) const override
Delete FileID Node from the catalog.