// ----------------------------------------------------------------------
// File: XrdFstOfs.hh
// Author: Andreas-Joachim Peters - CERN
// ----------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program 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 General Public License *
* along with this program. If not, see .*
************************************************************************/
#ifndef __XRDFSTOFS_FSTOFS_HH__
#define __XRDFSTOFS_FSTOFS_HH__
#include "fst/Namespace.hh"
#include "fst/utils/OpenFileTracker.hh"
#include "fst/utils/TpcInfo.hh"
#include "common/Fmd.hh"
#include "common/Logging.hh"
#include "common/XrdConnPool.hh"
#include "common/ThreadPool.hh"
#include "mq/XrdMqMessaging.hh"
#include "mq/XrdMqSharedObject.hh"
#include "mq/MessagingRealm.hh"
#include "XrdOfs/XrdOfs.hh"
#include "XrdOfs/XrdOfsTrace.hh"
#include "XrdOuc/XrdOucString.hh"
#include "namespace/ns_quarkdb/QdbContactDetails.hh"
#include "qclient/shared/SharedManager.hh"
#include
#include
#include
#include
#include
//------------------------------------------------------------------------------
//! Apple does not know these errnos
//------------------------------------------------------------------------------
#ifdef __APPLE__
#define EBADE 52
#define EBADR 53
#define EADV 68
#define EREMOTEIO 121
#define ENOKEY 126
#endif
namespace qclient
{
class QClient;
}
namespace eos::common
{
class ExecutorMgr;
}
class XrdOucEnv;
class XrdScheduler;
EOSFSTNAMESPACE_BEGIN
// Forward declarations
class ReplicaParLayout;
class RainMetaLayout;
class HttpServer;
class Storage;
class Messaging;
class XrdFstOfsFile;
class FmdHandler;
//------------------------------------------------------------------------------
//! Class XrdFstOfs
//------------------------------------------------------------------------------
class XrdFstOfs : public XrdOfs, public eos::common::LogId
{
friend class XrdFstOfsFile;
friend class ReplicaParLayout;
friend class RainMetaLayout;
public:
std::atomic sShutdown; ///< True if shutdown procedure is running
//----------------------------------------------------------------------------
//! FST shutdown procedure
//!
//! @param sig
//----------------------------------------------------------------------------
static void xrdfstofs_shutdown(int sig);
//----------------------------------------------------------------------------
//! Get stacktrace from crashing process
//!
//! @param sig
//----------------------------------------------------------------------------
static void xrdfstofs_stacktrace(int sig);
//----------------------------------------------------------------------------
//! Print coverage data
//!
//! @param sig
//----------------------------------------------------------------------------
static void xrdfstofs_coverage(int sig);
//----------------------------------------------------------------------------
//! FST "graceful" shutdown procedure. The FST will wait for a configurable
//! amount of time for readers and writers before shutting down.
//!
//! @param sig signal to trigger this handler
//----------------------------------------------------------------------------
static void xrdfstofs_graceful_shutdown(int sig);
//----------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------
XrdFstOfs();
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
virtual ~XrdFstOfs();
//----------------------------------------------------------------------------
//! Get new OFS directory object
//!
//! @param user User information
//! @param MonID Monitoring ID
//!
//! @return OFS directory object (NULL)
//----------------------------------------------------------------------------
XrdSfsDirectory* newDir(char* user = 0, int MonID = 0);
//----------------------------------------------------------------------------
//! Get new OFS file object
//!
//! @param user User information
//! @param MonID Monitoring ID
//!
//! @return OFS file object
//----------------------------------------------------------------------------
XrdSfsFile* newFile(char* user = 0, int MonID = 0);
//----------------------------------------------------------------------------
//! Configure OFS object
//!
//! @param error error output object
//! @param envP environment for the configuration
//!
//! @return 0 if successful, otherwise -1
//----------------------------------------------------------------------------
int Configure(XrdSysError& error, XrdOucEnv* envP);
//----------------------------------------------------------------------------
//! fsctl command
//----------------------------------------------------------------------------
int fsctl(const int cmd, const char* args, XrdOucErrInfo& out_error,
const XrdSecEntity* client);
//----------------------------------------------------------------------------
// ****** Here we mask all illegal operations ******
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//! Return memory mapping for file, if any.
//!
//! @param Addr Address of memory location
//! @param Size Size of the file or zero if not memory mapped.
//----------------------------------------------------------------------------
int
getMap(void** Addr, off_t& Size)
{
return SFS_OK;
}
//----------------------------------------------------------------------------
//! Chmod
//----------------------------------------------------------------------------
int
chmod(const char* path,
XrdSfsMode Mode,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* opaque = 0)
{
EPNAME("chmod");
return Emsg(epname, out_error, ENOSYS, epname, path);
}
//----------------------------------------------------------------------------
//! File exists
//----------------------------------------------------------------------------
int
exists(const char* path,
XrdSfsFileExistence& exists_flag,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* opaque = 0)
{
EPNAME("exists");
return Emsg(epname, out_error, ENOSYS, epname, path);
}
//----------------------------------------------------------------------------
//! Mkdir
//----------------------------------------------------------------------------
int mkdir(const char* path,
XrdSfsMode Mode,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* opaque = 0)
{
EPNAME("mkdir");
return Emsg(epname, out_error, ENOSYS, epname, path);
}
//----------------------------------------------------------------------------
//! Prepare request
//----------------------------------------------------------------------------
int
prepare(XrdSfsPrep& pargs,
XrdOucErrInfo& out_error,
const XrdSecEntity* client = 0)
{
EPNAME("prepare");
return Emsg(epname, out_error, ENOSYS, epname);
}
//----------------------------------------------------------------------------
//! Remove directory
//----------------------------------------------------------------------------
int remdir(const char* path,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* info = 0)
{
EPNAME("remdir");
return Emsg(epname, out_error, ENOSYS, epname, path);
}
//----------------------------------------------------------------------------
//! Rename
//----------------------------------------------------------------------------
int rename(const char* oldFileName,
const char* newFileName,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* infoO = 0,
const char* infoN = 0)
{
EPNAME("rename");
return Emsg(epname, out_error, ENOSYS, epname, oldFileName);
}
//----------------------------------------------------------------------------
//! Remove path - interface function
//----------------------------------------------------------------------------
int rem(const char* path,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* info = 0);
//----------------------------------------------------------------------------
//! Remove path - low-level function
//----------------------------------------------------------------------------
int _rem(const char* path,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
XrdOucEnv* info = 0,
const char* fstPath = 0,
unsigned long long fid = 0,
unsigned long fsid = 0,
bool ignoreifnotexist = false,
std::string* deletion_report = 0);
//----------------------------------------------------------------------------
//! Get checksum - we publish checksums at the MGM
//! @brief retrieve a checksum
//!
//! @param func function to be performed 'csCalc','csGet' or 'csSize'
//! @param csName name of the checksum
//! @param error error object
//! @param client XRootD authentication object
//! @param ininfo CGI
//!
//! @return SFS_OK on success otherwise SFS_ERROR
//----------------------------------------------------------------------------
int chksum(XrdSfsFileSystem::csFunc Func,
const char* csName,
const char* Path,
XrdOucErrInfo& out_error,
const XrdSecEntity* client = 0,
const char* opaque = 0);
//----------------------------------------------------------------------------
//! Stat path
//----------------------------------------------------------------------------
int stat(const char* path,
struct stat* buf,
XrdOucErrInfo& out_error,
const XrdSecEntity* client,
const char* opaque = 0);
//----------------------------------------------------------------------------
//! Call back to MGM node
//----------------------------------------------------------------------------
int CallManager(XrdOucErrInfo* error,
const char* path,
const char* manager,
XrdOucString& capOpaqueFile,
XrdOucString* return_result = 0,
unsigned short timeout = 0,
bool use_xrd_conn_pool = false,
bool retry = true);
//----------------------------------------------------------------------------
//! Function dealing with plugin calls
//----------------------------------------------------------------------------
int FSctl(int, XrdSfsFSctl&, XrdOucErrInfo&, const XrdSecEntity*);
//----------------------------------------------------------------------------
//! Wait for ongoing IO operations to finish
//!
//! @param timeout maximum timeout you're willing to wait
//!
//! @return true if all operations finished within the timeout, otherwise
//! false
//----------------------------------------------------------------------------
bool WaitForOngoingIO(std::chrono::seconds timeout);
//----------------------------------------------------------------------------
//! Allows to switch on error simulation in the OFS stack
//!
//! @param tag type of simulation error
//----------------------------------------------------------------------------
void SetSimulationError(const std::string& tag);
//----------------------------------------------------------------------------
//! Request broadcasts from all the registered queues
//----------------------------------------------------------------------------
void RequestBroadcasts();
//----------------------------------------------------------------------------
//! Get node geotag (each token needs to be less then 8 characters)
//!
//! @return geotag value
//----------------------------------------------------------------------------
inline std::string GetGeoTag() const
{
return mGeoTag;
}
//----------------------------------------------------------------------------
//! Query MGM for the list of deletions
//!
//! @param return SFS_ERROR if failed, otherwise SFS_OK
//----------------------------------------------------------------------------
int Query2Delete();
int Stall(XrdOucErrInfo& error, int stime, const char* msg);
int Redirect(XrdOucErrInfo& error, const char* host, int& port);
std::string MakeDeletionReport(eos::common::FileSystem::fsid_t fsid,
unsigned long long fid,
struct stat& deletion_stat,
bool viamq = true);
XrdSysError* Eroute;
eos::fst::Messaging* mFstMessaging; ///< messaging interface class
eos::fst::Storage* Storage; ///< Meta data & filesystem store object
mutable XrdSysMutex OpenFidMutex;
eos::fst::OpenFileTracker openedForWriting;
eos::fst::OpenFileTracker openedForReading;
eos::fst::OpenFileTracker runningCreation;
//! Map to forbid deleteOnClose for creates if 1+X open had a successful close
google::sparse_hash_map > WNoDeleteOnCloseFid;
XrdSysMutex XSLockFidMutex;
google::sparse_hash_map > XSLockFid;
//! Queue where file transaction reports get stored and picked up by a
//! thread running in the Storage class.
XrdSysMutex ReportQueueMutex;
std::queue ReportQueue;
//! Queue where log error are stored and picked up by a thread running in Storage
XrdSysMutex ErrorReportQueueMutex;
std::queue ErrorReportQueue;
XrdSysMutex WrittenFilesQueueMutex;
std::queue WrittenFilesQueue;
XrdMqSharedObjectManager ObjectManager; ///< Managing shared objects
//! Notifying any shared object changes
XrdMqSharedObjectChangeNotifier ObjectNotifier;
std::unique_ptr mMessagingRealm;
XrdScheduler* TransferScheduler; ///< TransferScheduler
XrdSysMutex TransferSchedulerMutex; ///< protecting the TransferScheduler
XrdOucString eoscpTransferLog; ///< eoscp.log full path
const char* mHostName; ///< FST hostname
QdbContactDetails mQdbContactDetails; ///< QDB contact details
std::shared_ptr mFsckQcl; ///< Qclient used for fsck
bool mMqOnQdb; ///< Are we using QDB as an MQ?
int mHttpdPort; ///< listening port of the http server
//! Embedded http server if available
std::unique_ptr mHttpd;
std::chrono::seconds mTpcKeyMinValidity {2 * 60}; ///< TPC key minimum validity
std::chrono::seconds mTpcKeyMaxValidity {15 * 60}; ///< TPC key maximum validity
std::string mMgmAlias; ///< MGM alias
std::shared_ptr mFmdHandler; // = 2kb
XrdOucBuffPool mXrdBuffPool;
//! Thread pool for async file close operations
eos::common::ThreadPool mCloseThreadPool;
//! Xrd connection pool for interaction with the MGM, used from CallManager
std::unique_ptr mMgmXrdPool;
std::atomic mSimIoReadErr; ///< simulate an IO error on read
std::atomic mSimIoWriteErr; ///< simulate an IO error on write
std::atomic mSimXsReadErr; ///< simulate a checksum error on read
std::atomic mSimXsWriteErr; ///< simulate a checksum error on write
std::atomic mSimFmdOpenErr; ///< simulate a fmd mismatch error on open
std::atomic mSimErrIoReadOff; ///< Simulate IO error offset on rd
std::atomic mSimErrIoWriteOff;///< Simulate IO error offset on wr
std::atomic mSimDiskWriting;///< Do not really write IO to disk
std::atomic mSimCloseErr; ///< simulate an error during close
std::atomic mSimUnresponsive; ///< simulate timeouts in the OFS layer
//! A vector map pointing from tpc key => tpc information for reads, [0]
//! are readers [1] are writers
std::vector> TpcMap;
XrdSysMutex TpcMapMutex; ///< Mutex protecting the Tpc map
//----------------------------------------------------------------------------
//! Compute adler checksum of given keytab file
//!
//! @param kt_path absolute path to keytab file
//!
//! @return string representing the checksum or "unaccessible" if keytab
//! is unavailable
//----------------------------------------------------------------------------
std::string GetKeytabChecksum(const std::string& kt_path) const;
//----------------------------------------------------------------------------
//! Get simulation error offset. Parse the last characters and return the
//! desired offset e.g. io_read_8M should return 8MB
//!
//! @param input string encoding the error type and optionally the offset
//!
//! @return return offset from which the error should be reported or 0 if no
//! such offset if provided
//----------------------------------------------------------------------------
uint64_t GetSimulationErrorOffset(const std::string& input) const;
//----------------------------------------------------------------------------
//! Update the TPC key min/max validity values. By default these are 2 and 15
//! minutes by can be overwritten by the environment variables.
//----------------------------------------------------------------------------
void UpdateTpcKeyValidity();
//----------------------------------------------------------------------------
//! Create directory hierarchy
//!
//! @param dir_hierarchy given directory hierarcht
//! @param mode mode bits for the newly created directories
//!
//! @return true if successful, otherwise false
//----------------------------------------------------------------------------
bool CreateDirHierarchy(const std::string& dir_hierarchy,
mode_t mode) const;
//----------------------------------------------------------------------------
//! Handle debug query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_OK or SFS_DATA and the
//! err_obj is populated with the response
//----------------------------------------------------------------------------
int HandleDebug(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Handle resync query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_OK or SFS_DATA and the
//! err_obj is populated with the response
//----------------------------------------------------------------------------
int HandleResync(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Handle rtlog query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_DATA and the err_obj is
//! populated with the response
//----------------------------------------------------------------------------
int HandleRtlog(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Handle verify query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_DATA and the err_obj is
//! populated with the response
//----------------------------------------------------------------------------
int HandleVerify(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Handle drop file query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_DATA and the err_obj is
//! populated with the response
//----------------------------------------------------------------------------
int HandleDropFile(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Handle clean orphans query
//!
//! @param env ecoding of the query command
//! @param err_obj object holding the response for the query
//!
//! @param return SFS_ERROR if failed, otherwise SFS_DATA and the err_obj is
//! populated with the response. "OK" if successful.
//----------------------------------------------------------------------------
int HandleCleanOrphans(XrdOucEnv& env, XrdOucErrInfo& err_obj);
//----------------------------------------------------------------------------
//! Set various XrdCl config options more appropriate for the EOS use-case
//! but still allow the env variables to override them
//----------------------------------------------------------------------------
static void SetXrdClConfig();
//----------------------------------------------------------------------------
//! Get Kernel relase information
//!
//! @return kernel release info or empty if failed
//----------------------------------------------------------------------------
static std::string GetKernelRelease();
};
//------------------------------------------------------------------------------
//! Global OFS handle
//------------------------------------------------------------------------------
extern XrdFstOfs gOFS;
EOSFSTNAMESPACE_END
#endif