Commit 05258737 authored by Will Buttinger's avatar Will Buttinger Committed by Graeme Stewart
Browse files

'restored gaudis envvar method for athena users' (PathResolver-00-02-02)

parent b6119b2b
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#ifndef PATHRESOLVER_PATHRESOLVER_H
#define PATHRESOLVER_PATHRESOLVER_H
#include <string>
class PathResolver
{
public:
typedef enum
{
Ok,
EnvironmentVariableUndefined,
UnknownDirectory
} SearchPathStatus;
typedef enum
{
LocalSearch,
RecursiveSearch
} SearchType;
/*
static std::string find_package_file ( const std::string& logical_file_name, const std::string& search_repo = "atlasoff",
SearchType search_type = LocalSearch) {
return find_file( search_repo + "/" + PACKAGE_OFFSET + "/" + PACKAGE_NAME + "/" + PACKAGE_VERSION + "/" + logical_file_name, "CALIBPATH", search_type );
}
*/
/**
@arg @c logical_file_name the name of the file to locate in the search path
@arg @c search_path the name of a path-like environment variable
@arg @c search_type characterizes the type of search. Can be either @c LocalSearch or @c RecursiveSearch
@return the physical name of the located file or empty string if not found
*/
static std::string find_file (const std::string& logical_file_name,
const std::string& search_path,
SearchType search_type = LocalSearch);
/**
@arg @c logical_file_name the name of the file to locate in the search path
@arg @c search_list the prioritized list of possible locations separated by the usual path separator
@arg @c search_type characterizes the type of search. Can be either @c LocalSearch or @c RecursiveSearch
@return the physical name of the located file or empty string if not found
*/
static std::string find_file_from_list (const std::string& logical_file_name,
const std::string& search_list,
SearchType search_type = LocalSearch);
/**
@arg @c logical_file_name the name of the directory to locate in the search path
@arg @c search_path the name of a path-like environment variable
@arg @c search_type characterizes the type of search. Can be either LocalSearch or RecursiveSearch
@return the physical name of the located directory or empty string if not found
*/
static std::string find_directory (const std::string& logical_file_name,
const std::string& search_path,
SearchType search_type = LocalSearch);
/**
@arg @c logical_file_name the name of the directory to locate in the search path
@arg @c search_list the prioritized list of possible locations separated by the usual path separator
@arg @c search_type characterizes the type of search. Can be either LocalSearch or RecursiveSearch
@return the physical name of the located directory or empty string if not found
*/
static std::string find_directory_from_list (const std::string& logical_file_name,
const std::string& search_list,
SearchType search_type = LocalSearch);
/**
@arg @c search_path the name of a path-like environment variable
@return the result of the verification. Can be one of @c Ok, @c EnvironmentVariableUndefined, @c UnknownDirectory
*/
static SearchPathStatus check_search_path (const std::string& search_path);
};
std::string PathResolverFindXMLFile (const std::string& logical_file_name);
std::string PathResolverFindDataFile (const std::string& logical_file_name);
std::string PathResolverFindCalibFile (const std::string& logical_file_name);
#endif
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#include "PathResolver/PathResolver.h"
#ifndef XAOD_STANDALONE
#include "GaudiKernel/System.h"
#endif
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
#include <stdlib.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/filesystem.hpp>
#include "TFile.h"
#include "TSystem.h"
namespace bf = boost::filesystem;
using namespace std;
static const char* path_separator = ",:";
//
///////////////////////////////////////////////////////////////////////////
//
typedef enum {
PR_regular_file,
PR_directory
} PR_file_type;
typedef enum {
PR_local,
PR_recursive
} PR_search_type;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static bool
PR_find( const bf::path& file, const string& search_list,
PR_file_type file_type, PathResolver::SearchType search_type,
string& result ) {
bool found(false);
// look for file as specified first
try {
if ( ( file_type == PR_regular_file && is_regular_file( file ) ) ||
( file_type == PR_directory && is_directory( file ) ) ) {
result = bf::system_complete(file).string();
return true;
}
} catch (bf::filesystem_error /*err*/) {
}
// assume that "." is always part of the search path, so check locally first
try {
bf::path local = bf::initial_path() / file;
if ( ( file_type == PR_regular_file && is_regular_file( local ) ) ||
( file_type == PR_directory && is_directory( local ) ) ) {
result = bf::system_complete(file).string();
return true;
}
} catch (bf::filesystem_error /*err*/) {
}
std::string locationToDownloadTo = "."; //will replace with first search location
// iterate through search list
vector<string> spv;
split(spv, search_list, boost::is_any_of( path_separator), boost::token_compress_on);
for (vector<string>::const_iterator itr = spv.begin();
itr != spv.end(); ++itr ) {
if( itr->find("http//")==0 && file_type==PR_regular_file ) { //only http download files, not directories
//try to do an http download to the local location
//restore the proper http protocal (had to remove for sake of env var splitting)
std::string addr = "http://"; addr += itr->substr(6,itr->length());
bf::path lp = locationToDownloadTo/file;
bf::path lpd = lp; lpd.remove_filename();
std::cout << "PathResolver INFO Attempting http download of " << addr << "/" << file.string() << " to " << lp << std::endl;
if(!is_directory(lpd)) {
std::cout << "PathResolver INFO Creating directory: " << lpd << std::endl;
if(!boost::filesystem::create_directories(lpd)) {
std::cerr << "PathResolver ERROR Unable to create directories to write file to : " << lp << std::endl;
throw std::runtime_error("Unable to download calibration file");
}
}
std::string fileToDownload = addr + "/" + file.string();
if(!TFile::Cp(fileToDownload.c_str(),(locationToDownloadTo+"/"+file.string()).c_str())) {
std::cerr << "PathResolver ERROR Unable to download file : " << fileToDownload << std::endl;
} else {
std::cout << "PathResolver INFO Successfully downloaded." << std::endl;
itr = spv.begin(); //reset to first element, which is where we downloaded to
}
} else if(locationToDownloadTo==".") {
//prefer first non-pwd location for downloading to. This should be the local InstallArea in cmt
locationToDownloadTo=*itr;
}
//std::cout << "searching path: " << *itr << std::endl;
bf::path fp = *itr / file;
try {
if ( ( file_type == PR_regular_file && is_regular_file( fp ) ) ||
( file_type == PR_directory && is_directory( fp ) ) ) {
result = bf::system_complete(fp).string();
return true;
}
} catch (bf::filesystem_error /*err*/) {
}
// if recursive searching requested, drill down
if (search_type == PathResolver::RecursiveSearch &&
is_directory( bf::path(*itr) ) ) {
bf::recursive_directory_iterator end_itr;
try {
for ( bf::recursive_directory_iterator ritr( *itr );
ritr != end_itr; ++ritr) {
// skip if not a directory
if (! is_directory( bf::path(*ritr) ) ) { continue; }
bf::path fp2 = bf::path(*ritr) / file;
if ( ( file_type == PR_regular_file && is_regular_file( fp2 ) ) ||
( file_type == PR_directory && is_directory( fp2 ) ) ) {
result = bf::system_complete( fp2 ).string();
return true;
}
}
} catch (bf::filesystem_error /*err*/) {
}
}
}
return found;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
string
PathResolver::find_file(const std::string& logical_file_name,
const std::string& search_path,
SearchType search_type) {
//std::cout << "finding file: " <<logical_file_name << " in path=" << search_path << std::endl;
std::string path_list;
#ifdef XAOD_STANDALONE
const char* envVarVal = gSystem->Getenv(search_path.c_str());
if(envVarVal == NULL) {
std::cout << "PathResolver ERROR " << search_path.c_str() << " environment variable not defined!" << std::endl;
path_list = ""; //this will allow search in pwd ... maybe we should throw exception though!
}
else { path_list = envVarVal; }
#else
System::getEnv(search_path, path_list);
#endif
return (find_file_from_list (logical_file_name, path_list, search_type));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
std::string
PathResolver::find_file_from_list (const std::string& logical_file_name,
const std::string& search_list,
SearchType search_type)
{
std::string result("");
bf::path lfn( logical_file_name );
/* bool found = */
PR_find (lfn, search_list, PR_regular_file, search_type, result);
// The following functionality was in the original PathResolver, but I believe
// that it's WRONG. It extracts the filename of the requested item, and searches
// for that if the preceding search fails. i.e., if you're looking for "B/a.txt",
// and that fails, it will look for just "a.txt" in the search list.
// if (! found && lfn.filename() != lfn ) {
// result = "";
// PR_find (lfn.filename(), search_list, PR_regular_file, search_type, result);
// }
return (result);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
string PathResolver::find_directory (const std::string& logical_file_name,
const std::string& search_path,
SearchType search_type)
{
std::string path_list = gSystem->Getenv(search_path.c_str());
return (find_directory_from_list (logical_file_name, path_list, search_type));
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
string
PathResolver::find_directory_from_list (const std::string& logical_file_name,
const std::string& search_list,
SearchType search_type)
{
std::string result;
if (!PR_find (logical_file_name, search_list, PR_directory, search_type, result))
{
result = "";
}
return (result);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
PathResolver::SearchPathStatus
PathResolver::check_search_path (const std::string& search_path)
{
std::string path_list = gSystem->Getenv(search_path.c_str());
if ( path_list.empty() )
return (EnvironmentVariableUndefined);
vector<string> spv;
boost::split( spv, path_list, boost::is_any_of( path_separator ), boost::token_compress_on);
vector<string>::iterator itr=spv.begin();
try {
for (; itr!= spv.end(); ++itr) {
bf::path pp(*itr);
if (!is_directory(pp)) {
return (UnknownDirectory);
}
}
} catch(bf::filesystem_error /*err*/) {
return (UnknownDirectory);
}
return ( Ok );
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
std::string PathResolverFindXMLFile (const std::string& logical_file_name)
{
return PathResolver::find_file (logical_file_name, "XMLPATH");
}
std::string PathResolverFindDataFile (const std::string& logical_file_name)
{
return PathResolver::find_file (logical_file_name, "DATAPATH");
}
std::string PathResolverFindCalibFile (const std::string& logical_file_name)
{
return PathResolver::find_file (logical_file_name, "CALIBPATH");
}
PACKAGE = PathResolver
PACKAGE_CXXFLAGS =
PACKAGE_LDFLAGS =
PACKAGE_PRELOAD = Hist boost_filesystem
PACKAGE_DEP = Asg_Boost
include $(ROOTCOREDIR)/Makefile-common
package PathResolver
author NLAA
use AtlasPolicy AtlasPolicy-*
use GaudiInterface GaudiInterface-* External
##Define the CALIBPATH environment variable ... is DATAPATH plus a few extra paths
path CALIBPATH "`echo ${DATAPATH}`"
cmtpath_pattern \
path_prepend CALIBPATH "/afs/cern.ch/atlas/www/GROUPS/DATABASE/GroupData" ; \
path_prepend CALIBPATH "/cvmfs/atlas.cern.ch/repo/sw/database/GroupData" ; \
path_prepend CALIBPATH "<path>/InstallArea/share" ; \
path_prepend CALIBPATH "${TestArea}/InstallArea/share" ; \
path_append CALIBPATH "http//atlas.web.cern.ch/Atlas/GROUPS/DATABASE/GroupData"
# path_remove CALIBPATH "$(cmt_installarea_prefix)" ; \ this line was first above
#path_remove CALIBPATH "${CMTINSTALLAREA}/share"
#path_append CALIBPATH "http//atlas.web.cern.ch/Atlas/GROUPS/DATABASE/GroupData"
#path_prepend CALIBPATH "/afs/cern.ch/atlas/www/GROUPS/DATABASE/GroupData"
#path_prepend CALIBPATH "/cvmfs/atlas.cern.ch/repo/sw/database/GroupData"
#path_prepend CALIBPATH "${CMTINSTALLAREA}/share"
private
use AtlasBoost AtlasBoost-* External
use AtlasROOT AtlasROOT-* External
#unit test code... kept in case something depends on it
use TestTools TestTools-* AtlasTest
apply_pattern UnitTest_run unit_test=PathResolver
path_prepend DATAPATH ../test
path_prepend DATAPATH ../test/B
path_prepend DATAPATH ../test/A
end_private
library PathResolver ../Root/*.cxx
apply_pattern installed_library
#Next three lines kept for possible future developments
#macro_append pp_cppflags " '-DPACKAGE_NAME=$(q2)$(package)$(q2)' '-DPACKAGE_OFFSET=$(q2)$($(package)_offset)$(q2)' "
#pattern declare_calib \
# apply_pattern generic_declare_for_link files="<files>" prefix="share/atlasoff/$(<package>_offset)/<package>/<version>" name="<name>"
if test -z "${CALIBPATH:+x}"
then
export CALIBPATH
fi
export CALIBPATH="$HOME/AtlasCalib:$ROOTCOREBIN/data:/cvmfs/atlas.cern.ch/repo/sw/database/GroupData:/afs/cern.ch/atlas/www/GROUPS/DATABASE/GroupData:http//atlas.web.cern.ch/Atlas/GROUPS/DATABASE/GroupData:$CALIBPATH"
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
/**
@mainpage
<center><b>This utility finds files or directories from a search path list.</b></center>
<hr />
@section Principle Principle
Assuming that a path-like environment variable is defined and
filled in with the possible prioritized locations where a category
of files is to be looked for, this utility will locate any file of
that category from those possible locations.
<p>
The following properties are implemented:
<ul>
<li>a directory offset can be specified. In this case, the file
search will detect files either right in every search path or in
the offset directory in every search path.</li>
<li>the effective physical location of the file is returned,
possibly with symbolic link resolution</li>
<li>it is possible to locate regular files or directories </li>
<li>the search can be local in every search path or recursive to
all subdirectories below every serach path.</li>
<li>it is possible to simply verify a search path against non
existing entries</li>
<li>Search paths can be specified either by giving the name of a
path-like environment variable or by a text string containing
the path list. In both cases the list follows the specific
syntax convention of the operating system (ie <b>':'</b> on Unix
systems and <b>';'</b> on DOS ones).</li>
</ul>
</p>
<hr />
@section Using Using the PathResolver
@subsection Accessing Accessing the PathResolver package.
One needs to add to the requirements file the following use statement:
@code
use PathResolver PathResolver-00-* Tools
@endcode
@subsection FindingFile Finding a file
<ol>
<li> <i>Finding a data file from the DATAPATH search list:</i>
@code
#include <PathResolver/PathResolver.h>
int main ()
{
std::string name;
name = PathResolver::find_file ("a.dat", "DATAPATH");
if (name == "")
{
std::cerr << "Cannot locate a.dat from ${DATAPATH}" << std::endl;
}
return (0);
}
@endcode
</li>
<li> <i>Recursively finding a data file from the DATAPATH search list:</i>
@code
#include <PathResolver/PathResolver.h>
int main ()
{
std::string name;
name = PathResolver::find_file ("a.dat", "DATAPATH", PathResolver::RecursiveSearch);
if (name == "")
{
std::cerr << "Cannot locate a.dat from any subdirectory of ${DATAPATH}" << std::endl;
}
return (0);
}
@endcode
</li>
<li> <i>Finding a data file from an explicit search list:</i>
@code
#include <PathResolver/PathResolver.h>
int main ()
{
std::string name;
name = PathResolver::find_file_from_list ("a.dat", "/here/data:/there/data");
if (name == "")
{
std::cerr << "Cannot locate a.dat from either /here/data or /there/data" << std::endl;
}
return (0);
}
@endcode
</li>
</ol>
@subsection FindingDir Finding a directory
<ol>
<li> <i>Finding a directory from the DATAPATH search list:</i>
@code
#include <PathResolver/PathResolver.h>
int main ()
{
std::string name;
name = PathResolver::find_directory ("data", "DATAPATH");
if (name == "")
{
std::cerr << "Cannot locate data directory from ${DATAPATH}" << std::endl;
}
return (0);
}
@endcode
</li>