#include "TNetXNGSystem.h"
#include "TFileStager.h"
#include "Rtypes.h"
#include "TList.h"
#include "TUrl.h"
#include <XrdCl/XrdClFileSystem.hh>
#include <XrdCl/XrdClXRootDResponses.hh>
ClassImp(TNetXNGSystem);
namespace
{
struct DirectoryInfo {
XrdCl::URL *fUrl;
XrdCl::DirectoryList *fDirList;
XrdCl::DirectoryList::Iterator *fDirListIter;
public:
DirectoryInfo(const char *dir) : fUrl(new XrdCl::URL(dir)), fDirList(0), fDirListIter(0) {}
~DirectoryInfo() {
delete fUrl;
delete fDirList;
}
};
}
TNetXNGSystem::TNetXNGSystem(Bool_t ) :
TSystem("-root", "Net file Helper System"), fUrl(0), fFileSystem(0)
{
SetName("root");
}
TNetXNGSystem::TNetXNGSystem(const char *url, Bool_t ) :
TSystem("-root", "Net file Helper System")
{
using namespace XrdCl;
SetName("root");
fUrl = new URL(std::string(url));
fFileSystem = new FileSystem(fUrl->GetURL());
}
TNetXNGSystem::~TNetXNGSystem()
{
delete fFileSystem;
delete fUrl;
}
void* TNetXNGSystem::OpenDirectory(const char *dir)
{
using namespace XrdCl;
DirectoryInfo *dirInfo = new DirectoryInfo(dir);
fDirPtrs.insert( (void*)dirInfo );
return (void *) dirInfo;
}
Int_t TNetXNGSystem::MakeDirectory(const char *dir)
{
using namespace XrdCl;
URL url(dir);
XRootDStatus st = fFileSystem->MkDir(url.GetPath(), MkDirFlags::MakePath,
Access::None);
if (!st.IsOK()) {
Error("MakeDirectory", "%s", st.GetErrorMessage().c_str());
return -1;
}
return 0;
}
void TNetXNGSystem::FreeDirectory(void *dirp)
{
fDirPtrs.erase( dirp );
delete (DirectoryInfo *) dirp;
}
const char* TNetXNGSystem::GetDirEntry(void *dirp)
{
using namespace XrdCl;
DirectoryInfo *dirInfo = (DirectoryInfo *) dirp;
if (!dirInfo->fDirList) {
XRootDStatus st = fFileSystem->DirList(dirInfo->fUrl->GetPath(),
DirListFlags::Locate,
dirInfo->fDirList);
if (!st.IsOK()) {
Error("GetDirEntry", "%s", st.GetErrorMessage().c_str());
return 0;
}
dirInfo->fDirListIter = new DirectoryList::Iterator(dirInfo->fDirList->Begin());
}
if (*(dirInfo->fDirListIter) != dirInfo->fDirList->End()) {
const char *filename = (**(dirInfo->fDirListIter))->GetName().c_str();
(*(dirInfo->fDirListIter))++;
return filename;
} else {
return 0;
}
}
Int_t TNetXNGSystem::GetPathInfo(const char *path, FileStat_t &buf)
{
using namespace XrdCl;
StatInfo *info = 0;
URL target(path);
XRootDStatus st = fFileSystem->Stat(target.GetPath(), info);
if (!st.IsOK()) {
Error("GetPathInfo", "Error: %s", st.GetErrorMessage().c_str());
delete info;
return 1;
} else {
if (info->TestFlags(StatInfo::Offline)) {
buf.fMode = kS_IFOFF;
} else {
std::stringstream sstr(info->GetId());
Long64_t id;
sstr >> id;
buf.fDev = (id >> 32);
buf.fIno = (id & 0x00000000FFFFFFFF);
buf.fUid = -1;
buf.fGid = -1;
buf.fIsLink = 0;
buf.fSize = info->GetSize();
buf.fMtime = info->GetModTime();
if (info->TestFlags(StatInfo::XBitSet))
buf.fMode = (kS_IFREG | kS_IXUSR | kS_IXGRP | kS_IXOTH);
if (info->GetFlags() == 0) buf.fMode = kS_IFREG;
if (info->TestFlags(StatInfo::IsDir)) buf.fMode = kS_IFDIR;
if (info->TestFlags(StatInfo::Other)) buf.fMode = kS_IFSOCK;
if (info->TestFlags(StatInfo::IsReadable)) buf.fMode |= kS_IRUSR;
if (info->TestFlags(StatInfo::IsWritable)) buf.fMode |= kS_IWUSR;
}
}
delete info;
return 0;
}
Bool_t TNetXNGSystem::ConsistentWith(const char *path, void *dirptr)
{
using namespace XrdCl;
if( path )
{
URL url(path);
if( gDebug > 1 )
Info("ConsistentWith", "Protocol: '%s' (%s), Username: '%s' (%s), "
"Password: '%s' (%s), Hostname: '%s' (%s), Port: %d (%d)",
fUrl->GetProtocol().c_str(), url.GetProtocol().c_str(),
fUrl->GetUserName().c_str(), url.GetUserName().c_str(),
fUrl->GetPassword().c_str(), url.GetPassword().c_str(),
fUrl->GetHostName().c_str(), url.GetHostName().c_str(),
fUrl->GetPort(), url.GetPort());
if( fUrl->GetProtocol() == url.GetProtocol() &&
fUrl->GetUserName() == url.GetUserName() &&
fUrl->GetPassword() == url.GetPassword() &&
fUrl->GetHostName() == url.GetHostName() &&
fUrl->GetPort() == url.GetPort())
return kTRUE;
}
if( dirptr )
return fDirPtrs.find( dirptr ) != fDirPtrs.end();
return kFALSE;
}
int TNetXNGSystem::Unlink(const char *path)
{
using namespace XrdCl;
StatInfo *info;
URL url(path);
XRootDStatus st = fFileSystem->Stat(url.GetPath(), info);
if (!st.IsOK()) {
Error("Unlink", "%s", st.GetErrorMessage().c_str());
delete info;
return -1;
}
if (info->TestFlags(StatInfo::IsDir))
st = fFileSystem->RmDir(url.GetPath());
else
st = fFileSystem->Rm(url.GetPath());
delete info;
if (!st.IsOK()) {
Error("Unlink", "%s", st.GetErrorMessage().c_str());
return -1;
}
return 0;
}
Bool_t TNetXNGSystem::IsPathLocal(const char *path)
{
return TSystem::IsPathLocal(path);
}
Int_t TNetXNGSystem::Locate(const char *path, TString &endurl)
{
using namespace XrdCl;
LocationInfo *info = 0;
URL pathUrl(path);
XRootDStatus st = fFileSystem->Locate(pathUrl.GetPath(), OpenFlags::None,
info);
if (!st.IsOK()) {
Error("Locate", "%s", st.GetErrorMessage().c_str());
delete info;
return 1;
}
endurl = info->Begin()->GetAddress();
delete info;
return 0;
}
Int_t TNetXNGSystem::Stage(const char* path, UChar_t priority)
{
TList *files = new TList();
files->Add((TObject *) new TUrl(path));
return Stage((TCollection *) files, priority);
}
Int_t TNetXNGSystem::Stage(TCollection *files, UChar_t priority)
{
using namespace XrdCl;
std::vector<std::string> fileList;
TIter it(files);
TObject *object = 0;
while ((object = (TObject *) it.Next())) {
TString path = TFileStager::GetPathName(object);
if (path == "") {
Warning("Stage", "object is of unexpected type %s - ignoring",
object->ClassName());
continue;
}
fileList.push_back(std::string(URL(path.Data()).GetPath()));
}
Buffer *response;
XRootDStatus st = fFileSystem->Prepare(fileList, PrepareFlags::Stage,
(uint8_t) priority, response);
if (!st.IsOK()) {
Error("Stage", "%s", st.GetErrorMessage().c_str());
return -1;
}
return 0;
}