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;
}
//______________________________________________________________________________