// PoolFileCatalog.cxx #include "dataset_pool/PoolFileCatalog.h" #include #include #include "dataset_util/Environment.h" #include "dataset_util/TempDir.h" #include "dataset_util/SystemCommand.h" #include "dataset_util/FileStatus.h" #include using std::string; using std::cerr; using std::endl; using dset::FileCatalog; using dset::PoolFileCatalog; using dset::Url; typedef PoolFileCatalog::Name Name; typedef std::map PfcMap; typedef FileCatalog::UrlList UrlList; //********************************************************************** // Local definitions. //********************************************************************** namespace { //********************************************************************** // Locator. FileCatalog* plocate(Name intype, Name name) { string type = intype; if ( type == PoolFileCatalog::static_type() ) { } else if ( type == "guid" ) { type = PoolFileCatalog::static_type(); } else { return 0; } if ( type != PoolFileCatalog::static_type() ) return 0; PoolFileCatalog& fc = PoolFileCatalog::instance(name); return &fc; } //********************************************************************** // Register locator. int LOC = FileCatalog:: register_locator(PoolFileCatalog::static_type(), plocate); int LOCG = FileCatalog::register_locator("guid", plocate); //********************************************************************** // Directory to stage files. string stage_dir() { static string val = ""; if ( ! val.size() ) { TempDir td("/tmp/dial_PoolFileCatalog_cache", false); val = td.name(); } return val; } //********************************************************************** // Default name. Name default_name() { static Name val; if ( val.size() == 0 ) { val = Environment::current().value("POOL_CATALOG"); if ( val.size() == 0 ) { val = "file:dial_pool_catalog.xml"; } } return val; } //********************************************************************** } // end unnamed namespace //********************************************************************** // Static member functions. //********************************************************************** // Instance of this class. PoolFileCatalog& PoolFileCatalog::instance(Name inname) { // Special handling for "" so we don't create two instances. Name name = inname; if ( name.size() == 0 ) { name = default_name(); } assert( name.size() ); static PfcMap catalogs; PfcMap::iterator icat = catalogs.find(name); if ( icat == catalogs.end() ) { catalogs[name] = PoolFileCatalog(name); icat = catalogs.find(name); } assert( icat != catalogs.end() ); return icat->second; } //********************************************************************** // Member functions. //********************************************************************** // Default constructor. // Object is invalid. PoolFileCatalog::PoolFileCatalog() { } //********************************************************************** // Constructor. PoolFileCatalog::PoolFileCatalog(Name name) : m_name(name) { if ( m_name.size() == 0 ) { m_name = default_name(); } } //********************************************************************** // Destructor. PoolFileCatalog::~PoolFileCatalog() { } //********************************************************************** void PoolFileCatalog::message(string msg) const { cerr << "PoolFileCatalog: " << msg << endl; } //********************************************************************** // Catalog type. Name PoolFileCatalog::type() const { return static_type(); } //********************************************************************** // Catalog name. Name PoolFileCatalog::name() const { return m_name; } //********************************************************************** // Validity. bool PoolFileCatalog::is_valid() const { return m_name.size(); } //********************************************************************** // Has. bool PoolFileCatalog::has(Url lurl) { if ( ! is_valid() ) return false; string prefix = "PoolFileCatalog::has: "; string senv = "POOL_CATALOG=" + m_name + "; export POOL_CATALOG; "; string prot = lurl.prefix(); if ( prot == "guid" ) { string guid = lurl.suffix(); SystemCommand com1(senv + "FClistPFN -q \"guid='" + guid + "'\""); int stat = com1.runerr(); if ( stat!=0 || com1.out().size()>1 || com1.err().size() ) { cerr << prefix << "Error checking GUID status:" << endl; cerr << com1 << endl; } return com1.out().size() == 1; } else if ( prot == "lfn" ) { string lfn = lurl.suffix(); SystemCommand com2(senv + "FClistPFN -q \"lfname='" + lfn + "'\""); int stat = com2.runerr(); if ( stat!=0 || com2.out().size()>1 || com2.err().size() ) { cerr << prefix << "Error checking LFN status:" << endl; cerr << com2 << endl; } return com2.out().size() == 1; } cerr << prefix << "Unknown protocol: " << prot << endl; return false; } //********************************************************************** // GUID. Url PoolFileCatalog::guid(Url lurl) { string prefix = "PoolFileCatalog::guid: "; string prot = lurl.prefix(); string senv = "POOL_CATALOG=" + m_name + "; export POOL_CATALOG; "; if ( prot == "guid" ) { return lurl; } else if ( prot == "lfn" ) { string lfn = lurl.suffix(); SystemCommand com(senv + "FClistGUID -q \"lfname='" + lfn + "'\""); int stat = com.runerr(); if ( stat!=0 || com.out().size()>1 || com.err().size() ) { cerr << prefix << "Error fetching GUID:" << endl; cerr << com << endl; } string guid = com.out().line(0); return Url("guid:" + guid); } cerr << prefix << "Unknown protocol: " << prot << endl; return Url(); } //********************************************************************** // LFN. Url PoolFileCatalog::lfn(Url lurl) { string prefix = "PoolFileCatalog::lfn: "; string prot = lurl.prefix(); string senv = "POOL_CATALOG=" + m_name + "; export POOL_CATALOG; "; if ( prot == "lfn" ) { return lurl; } else if ( prot == "guid" ) { string guid = lurl.suffix(); SystemCommand com(senv + "FClistLFN -q \"guid='" + guid + "'\""); int stat = com.runerr(); if ( stat!=0 || com.out().size()>1 || com.err().size() ) { cerr << prefix << "Error fetching LFN:" << endl; cerr << com << endl; } string lfn = com.out().line(0); Url outurl(lfn); if ( ! outurl.is_valid() ) { cerr << prefix << "Retrieved LFN URL is invalid" << endl; cerr << com << endl; } return outurl; } cerr << prefix << "Unknown protocol: " << prot << endl; return Url(); } //********************************************************************** // Get replica. // We use command line to avoid library conflicts with MYSQL. UrlList PoolFileCatalog::replicas(Url lurl) { UrlList outurls; if ( ! is_valid() ) return outurls; string prefix = "PoolFileCatalog::replicas: "; string senv = "POOL_CATALOG=" + m_name + "; export POOL_CATALOG; "; Text tpfns; string prot = lurl.prefix(); if ( prot == "guid" ) { string guid = lurl.suffix(); SystemCommand com1(senv + "FClistPFN -q \"guid='" + guid + "'\""); int stat = com1.runerr(); if ( stat!=0 || com1.err().size() ) { cerr << prefix << "Error fetching PFN's with GUID" << endl; cerr << com1 << endl; return outurls; } if ( com1.out().size() == 0 ) { cerr << prefix << "No GUID matches found in pool catalog" << endl; return outurls; } tpfns = com1.out(); } else if ( prot == "lfn" ) { string lfn = lurl.suffix(); SystemCommand com2(senv + "FClistPFN -q \"lfname='" + lfn + "'\""); int stat = com2.runerr(); if ( stat!=0 || com2.err().size() ) { cerr << prefix << "Error fetching PFN's with LFN" << endl; cerr << com2 << endl; return outurls; } if ( com2.out().size() == 0 ) { cerr << prefix << "No LFN matches found in pool catalog" << endl; return outurls; } tpfns = com2.out(); } else { cerr << prefix << "Invalid protocol: " << prot << endl; return outurls; } // Build list of URL's from output replica list. for ( int iline=0; iline