diff --git a/packaging/rhel/xrootd.spec.in b/packaging/rhel/xrootd.spec.in index 8c925b05140..27e59e4d110 100644 --- a/packaging/rhel/xrootd.spec.in +++ b/packaging/rhel/xrootd.spec.in @@ -681,6 +681,7 @@ fi %{_libdir}/libXrdPss-4.so %{_libdir}/libXrdXrootd-4.so %{_libdir}/libXrdFileCache-4.so +%{_libdir}/libXrdBlacklistDecision-4.so %{_libdir}/libXrdHttp-4.so %{_libdir}/libXrdOssSIgpfsT-4.so %{_libdir}/libXrdServer.so.* diff --git a/src/XrdFileCache.cmake b/src/XrdFileCache.cmake index 7032087ee4b..e86beee43f5 100644 --- a/src/XrdFileCache.cmake +++ b/src/XrdFileCache.cmake @@ -4,6 +4,7 @@ include( XRootDCommon ) # Modules #------------------------------------------------------------------------------- set( LIB_XRD_FILECACHE XrdFileCache-${PLUGIN_VERSION} ) +set( LIB_XRD_BLACKLIST XrdBlacklistDecision-${PLUGIN_VERSION} ) #------------------------------------------------------------------------------- # Shared library version @@ -38,6 +39,24 @@ set_target_properties( INTERFACE_LINK_LIBRARIES "" LINK_INTERFACE_LIBRARIES "" ) +#------------------------------------------------------------------------------- +# The XrdBlacklistDecision library +#------------------------------------------------------------------------------- +add_library( + ${LIB_XRD_BLACKLIST} + MODULE + XrdFileCache/XrdFileCacheBlacklistDecision.cc) + +target_link_libraries( + ${LIB_XRD_BLACKLIST} + ) + +set_target_properties( + ${LIB_XRD_BLACKLIST} + PROPERTIES + INTERFACE_LINK_LIBRARIES "" + LINK_INTERFACE_LIBRARIES "" ) + #------------------------------------------------------------------------------- # xrdpfc_print #------------------------------------------------------------------------------- @@ -59,6 +78,10 @@ install( TARGETS ${LIB_XRD_FILECACHE} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) +install( + TARGETS ${LIB_XRD_BLACKLIST} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) + install( TARGETS xrdpfc_print RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) diff --git a/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc b/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc new file mode 100644 index 00000000000..6e22a35c934 --- /dev/null +++ b/src/XrdFileCache/XrdFileCacheBlacklistDecision.cc @@ -0,0 +1,130 @@ +//---------------------------------------------------------------------------------- +// Copyright (c) 2015 by Board of Trustees of the Leland Stanford, Jr., University +// Author: Alja Mrak-Tadel, Matevz Tadel, Brian Bockelman +//---------------------------------------------------------------------------------- +// XRootD is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// XRootD 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 Lesser General Public License +// along with XRootD. If not, see . +//---------------------------------------------------------------------------------- + +#include "XrdFileCacheDecision.hh" +#include "XrdSys/XrdSysError.hh" + +#include +#include +#include +#include + +class BlacklistDecision : public XrdFileCache::Decision +{ + //---------------------------------------------------------------------------- + //! A decision library that allows all files to be cached except for a blacklist + //---------------------------------------------------------------------------- + + public: + virtual bool Decide(const std::string & url, XrdOss &) const + { + size_t slashslash = url.find("//"); + const char *fname = url.c_str(); + if (slashslash != std::string::npos) + { + fname += slashslash+2; + fname = strchr(fname, '/'); + if (!fname) {return true;} + } + std::string url_path = fname; + size_t question = url_path.find("?"); + if (question != std::string::npos) + { + url_path[question] = '\0'; + fname = url_path.c_str(); + } + if ((strlen(fname) > 1) && (fname[0] == '/') && (fname[1] == '/')) + { + fname++; + } + //m_log.Emsg("BlacklistDecide", "Deciding whether to cache file", fname); + for (std::vector::const_iterator it = m_blacklist.begin(); it != m_blacklist.end(); it++) + { + if (!fnmatch(it->c_str(), fname, FNM_PATHNAME)) + { + //m_log.Emsg("BlacklistDecide", "Not caching file as it matches blacklist entry", it->c_str()); + return false; + } + } + //m_log.Emsg("BlacklistDecide", "Caching file", fname); + return true; + } + + BlacklistDecision(XrdSysError &log) + : m_log(log) + { + } + + virtual bool ConfigDecision(const char * parms) + { + if (!parms || !parms[0] || (strlen(parms) == 0)) + { + m_log.Emsg("ConfigDecision", "Blacklist file not specified."); + return false; + } + m_log.Emsg("ConfigDecision", "Using blacklist", parms); + FILE * fp = fopen(parms, "r"); + if (fp == 0) + { + m_log.Emsg("ConfigDecision", errno, "Failed to open blacklist:", parms); + return false; + } + + ssize_t read; + size_t len =0; + char *line = NULL; + while (-1 != (read=getline(&line, &len, fp))) + { + char *trimmed = line; + while (trimmed[0] && isspace(trimmed[0])) {trimmed++;} + if (trimmed[0] == 0) {continue;} + size_t filelen = strlen(trimmed); + if (trimmed[filelen-1] == '\n') {trimmed[filelen-1] = '\0';} + m_blacklist.push_back(trimmed); + } + free(line); + fclose(fp); + if (!feof(fp)) + { + m_log.Emsg("ConfigDecision", errno, "Failed to parse blacklist"); + } + for (std::vector::const_iterator it=m_blacklist.begin(); it!=m_blacklist.end(); it++) + { + m_log.Emsg("ConfigDecision", "Cache is blacklisting paths matching", it->c_str()); + } + return true; + } + + private: + std::vector m_blacklist; + XrdSysError &m_log; +}; + +/******************************************************************************/ +/* XrdFileCacheGetDecision */ +/******************************************************************************/ + +// Return a decision object to use. +extern "C" +{ +XrdFileCache::Decision *XrdFileCacheGetDecision(XrdSysError &err) +{ + return new BlacklistDecision(err); +} +} + diff --git a/src/XrdFileCache/XrdFileCacheDecision.hh b/src/XrdFileCache/XrdFileCacheDecision.hh index 3f36d0a1d4c..b59bf8d295a 100644 --- a/src/XrdFileCache/XrdFileCacheDecision.hh +++ b/src/XrdFileCache/XrdFileCacheDecision.hh @@ -46,7 +46,7 @@ namespace XrdFileCache //! //! @return decision //--------------------------------------------------------------------- - virtual bool Decide(std::string &, XrdOss &) const = 0; + virtual bool Decide(const std::string &, XrdOss &) const = 0; //------------------------------------------------------------------------------ //! Parse configuration arguments. diff --git a/src/XrdFileCache/XrdFileCacheFactory.cc b/src/XrdFileCache/XrdFileCacheFactory.cc index 276844a56fb..c1b31ac13f4 100644 --- a/src/XrdFileCache/XrdFileCacheFactory.cc +++ b/src/XrdFileCache/XrdFileCacheFactory.cc @@ -121,7 +121,7 @@ bool Factory::xdlib(XrdOucStream &Config) std::string libp; if (!(val = Config.GetWord()) || !val[0]) { - clLog()->Info(XrdCl::AppMsg, " Factory:;Config() decisionlib not specified; always caching files"); + clLog()->Info(XrdCl::AppMsg, " Factory::Config() decisionlib not specified; always caching files"); return true; } else @@ -150,6 +150,7 @@ bool Factory::xdlib(XrdOucStream &Config) d->ConfigDecision(params); m_decisionpoints.push_back(d); + clLog()->Info(XrdCl::AppMsg, "Factory::Config() successfully created decision lib from %s", libp.c_str()); return true; } //______________________________________________________________________________