/******************************************************************************/ /* */ /* X r d S s i G e t C l i e n t S e r v i c e . c c */ /* */ /* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */ /* Produced by Andrew Hanushevsky for Stanford University under contract */ /* DE-AC02-76-SFO0515 with the Department of Energy */ /* */ /* This file is part of the XRootD software suite. */ /* */ /* 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 Lesser General Public */ /* License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public License */ /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ /* COPYING (GPL license). If not, see . */ /* */ /* The copyright holder's institutional names and contributor's names may not */ /* be used to endorse or promote products derived from this software without */ /* specific prior written permission of the institution or contributor. */ /******************************************************************************/ #include #include #include #include #include #include #include #include #include "Xrd/XrdScheduler.hh" #include "Xrd/XrdTrace.hh" #include "XrdCl/XrdClDefaultEnv.hh" #include "XrdNet/XrdNetAddr.hh" #include "XrdSsi/XrdSsiAtomics.hh" #include "XrdSsi/XrdSsiLogger.hh" #include "XrdSsi/XrdSsiProvider.hh" #include "XrdSsi/XrdSsiServReal.hh" #include "XrdSsi/XrdSsiTrace.hh" #include "XrdSys/XrdSysLogger.hh" #include "XrdSys/XrdSysLogging.hh" #include "XrdSys/XrdSysError.hh" #include "XrdSys/XrdSysPthread.hh" #include "XrdSys/XrdSysTrace.hh" /******************************************************************************/ /* N a m e S p a c e G l o b a l s */ /******************************************************************************/ namespace XrdSsi { extern XrdSysError Log; extern XrdSysLogger *Logger; extern XrdSysTrace Trace; extern XrdSsiLogger::MCB_t *msgCB; extern XrdSsiLogger::MCB_t *msgCBCl; XrdSysMutex clMutex; XrdScheduler *schedP = 0; XrdCl::Env *clEnvP = 0; short maxTCB = 300; short maxCLW = 30; Atomic(bool) initDone(false); bool dsTTLSet = false; bool reqTOSet = false; bool strTOSet = false; } using namespace XrdSsi; /******************************************************************************/ /* L o c a l C l a s s e s */ /******************************************************************************/ class XrdSsiClientProvider : public XrdSsiProvider { public: XrdSsiService *GetService(XrdSsiErrInfo &eInfo, const std::string &contact, int oHold=256 ); virtual bool Init(XrdSsiLogger *logP, XrdSsiCluster *clsP, std::string cfgFn, std::string parms, int argc, char **argv ) {return true;} virtual rStat QueryResource(const char *rName, const char *contact=0 ) {return notPresent;} virtual void SetCBThreads(int cbNum, int ntNum); virtual void SetTimeout(tmoType what, int tmoval); XrdSsiClientProvider() {} virtual ~XrdSsiClientProvider() {} private: void SetLogger(); void SetScheduler(); }; /******************************************************************************/ /* X r d S s i C l i e n t P r o v i d e r : : G e t S e r v i c e */ /******************************************************************************/ XrdSsiService *XrdSsiClientProvider::GetService(XrdSsiErrInfo &eInfo, const std::string &contact, int oHold) { static const int maxTMO = 0x7fffffff; XrdNetAddr netAddr; const char *eText; char buff[512]; int n; // Allocate a scheduler if we do not have one and set default env (1st call) // if (!Atomic_GET(initDone)) {clMutex.Lock(); if (!Logger) SetLogger(); if (!schedP) SetScheduler(); if (!clEnvP) clEnvP = XrdCl::DefaultEnv::GetEnv(); if (!dsTTLSet) clEnvP->PutInt("DataServerTTL", maxTMO); if (!reqTOSet) clEnvP->PutInt("RequestTimeout", maxTMO); if (!strTOSet) clEnvP->PutInt("StreamTimeout", maxTMO); initDone = true; clMutex.UnLock(); } // If no contact is given then declare an error // if (contact.empty()) {eInfo.Set("Contact not specified.", EINVAL); return 0;} // Validate the given contact // if ((eText = netAddr.Set(contact.c_str()))) {eInfo.Set(eText, EINVAL); return 0;} // Construct new binding // if (!(n = netAddr.Format(buff, sizeof(buff), XrdNetAddrInfo::fmtName))) {eInfo.Set("Unable to validate contact.", EINVAL); return 0;} // Allocate a service object and return it // return new XrdSsiServReal(buff, oHold); } /******************************************************************************/ /* X r d S s i C l i e n t P r o v i d e r : : S e t C B T h r e a d s */ /******************************************************************************/ void XrdSsiClientProvider::SetCBThreads(int cbNum, int ntNum) { // Validate thread number // if (cbNum > 1) {if (cbNum > 32767) cbNum = 32767; // Max short value if (ntNum < 1) ntNum = cbNum*10/100; if (ntNum < 3) ntNum = 0; else if (ntNum > 100) ntNum = 100; clMutex.Lock(); maxTCB = static_cast(cbNum); maxCLW = static_cast(ntNum); clMutex.UnLock(); } } /******************************************************************************/ /* X r d S s i C l i e n t P r o v i d e r : : S e t L o g g e r */ /******************************************************************************/ void XrdSsiClientProvider::SetLogger() { int eFD; // Get a file descriptor mirroring standard error // #if defined(__linux__) && defined(O_CLOEXEC) eFD = fcntl(STDERR_FILENO, F_DUPFD_CLOEXEC, 0); #else eFD = dup(STDERR_FILENO); fcntl(eFD, F_SETFD, FD_CLOEXEC); #endif // Now we need to get a logger object. We make this a real dumb one. // Logger = new XrdSysLogger(eFD, 0); Log.logger(Logger); Trace.SetLogger(Logger); if (getenv("XRDSSIDEBUG") != 0) Trace.What = TRACESSI_Debug; // Check for a message callback object. This must be set at global init time. // if (msgCBCl) {XrdSysLogging::Parms logParms; msgCB = msgCBCl; logParms.logpi = msgCBCl; logParms.bufsz = 0; XrdSysLogging::Configure(*Logger, logParms); } } /******************************************************************************/ /* X r d S s i C l i e n t P r o v i d e r : : S e t S c h e d u l e r */ /******************************************************************************/ // This may not be called before the logger object is created! void XrdSsiClientProvider::SetScheduler() { static XrdOucTrace myTrc(&Log); // Now construct the proper trace object (note that we do not set tracing if // message forwarding is on because these messages will not be forwarded). // This must be fixed when xrootd starts using XrdSysTrace!!! // if (!msgCBCl && Trace.What & TRACESSI_Debug) myTrc.What = TRACE_SCHED; // We can now set allocate a scheduler // XrdSsi::schedP = new XrdScheduler(&Log, &myTrc); // Set thread count for callbacks // XrdSsi::schedP->setParms(-1, maxTCB, -1, -1, 0); // Set number of framework worker hreads if need be // if (maxCLW) {if (!XrdSsi::clEnvP) clEnvP = XrdCl::DefaultEnv::GetEnv(); clEnvP->PutInt("WorkerThreads", maxCLW); } // Start the scheduler // XrdSsi::schedP->Start(); } /******************************************************************************/ /* X r d S s i C l i e n t P r o v i d e r : : S e t T i m e o u t */ /******************************************************************************/ void XrdSsiClientProvider::SetTimeout(XrdSsiProvider::tmoType what, int tmoval) { // Ignore invalid timeouts // if (tmoval <= 0) return; // Get global environment // clMutex.Lock(); if (!XrdSsi::clEnvP) clEnvP = XrdCl::DefaultEnv::GetEnv(); // Set requested timeout // switch(what) {case connect_N: clEnvP->PutInt("ConnectionRetry", tmoval); break; case connect_T: clEnvP->PutInt("ConnectionWindow", tmoval); break; case idleClose: clEnvP->PutInt("DataServerTTL", tmoval); dsTTLSet = true; break; case request_T: clEnvP->PutInt("RequestTimeout", tmoval); reqTOSet = true; break; case stream_T: clEnvP->PutInt("StreamTimeout", tmoval); strTOSet = true; break; default: break; } // All done // clMutex.UnLock(); } /******************************************************************************/ /* G l o b a l S t a t i c s */ /******************************************************************************/ namespace { XrdSsiClientProvider ClientProvider; } XrdSsiProvider *XrdSsiProviderClient = &ClientProvider;