// ----------------------------------------------------------------------
// File: FileId.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 .*
************************************************************************/
#pragma once
#include "common/Namespace.hh"
#include "XrdOuc/XrdOucString.hh"
#include
#include
#include
EOSCOMMONNAMESPACE_BEGIN
//------------------------------------------------------------------------------
//! Class to handle file IDs.
//! Provides conversion functions from/to hex representation and to build path
//! names from fids and prefixes
//------------------------------------------------------------------------------
class FileId
{
public:
typedef unsigned long long fileid_t;
//----------------------------------------------------------------------------
//! Convert a fid into a hexadecimal string
//----------------------------------------------------------------------------
static std::string Fid2Hex(unsigned long long fid)
{
char hexbuffer[128];
sprintf(hexbuffer, "%08llx", fid);
return std::string(hexbuffer);
}
//----------------------------------------------------------------------------
//! Convert a hex decimal string into a fid
//----------------------------------------------------------------------------
static unsigned long long Hex2Fid(const char* hexstring)
{
if (hexstring && strlen(hexstring)) {
return strtoll(hexstring, 0, 16);
} else {
return 0;
}
}
//----------------------------------------------------------------------------
//! Determine which inode encoding to use
//----------------------------------------------------------------------------
static bool useNewInodes() {
static bool initialized = false;
static bool useNew = false;
if(initialized) {
return useNew;
}
useNew = getenv("EOS_USE_NEW_INODES") != nullptr && getenv("EOS_USE_NEW_INODES")[0] == '1';
initialized = true;
return useNew;
}
//----------------------------------------------------------------------------
//! Convert an EOS file id into an inode number. Currently dispatches to the
//! legacy implementation.
//----------------------------------------------------------------------------
static unsigned long long FidToInode(unsigned long long fid)
{
if(useNewInodes()) {
return NewFidToInode(fid);
}
return LegacyFidToInode(fid);
}
static unsigned long long InodeToFid(unsigned long long ino)
{
if (NewIsFileInode(ino)) {
return NewInodeToFid(ino);
}
return LegacyInodeToFid(ino);
}
static bool IsFileInode(unsigned long long ino)
{
if(useNewInodes()) {
return NewIsFileInode(ino);
}
return LegacyIsFileInode(ino);
}
//----------------------------------------------------------------------------
//! New encoding - convert an EOS file id into an inode number.
//! We mark the last bit with "1" for files, and "0" for containers.
//----------------------------------------------------------------------------
static constexpr unsigned long long kLastBitSet = (1ull << 63);
static unsigned long long NewFidToInode(unsigned long long fid)
{
return fid | kLastBitSet;
}
static unsigned long long NewInodeToFid(unsigned long long ino)
{
return ino & (~kLastBitSet);
}
static bool NewIsFileInode(unsigned long long ino)
{
return (ino & kLastBitSet) != 0ull;
}
//----------------------------------------------------------------------------
//! Legacy encoding - convert an EOS file id into an inode number - we shift
//! the range by 28 bytes to not overlap with directory inodes.
//----------------------------------------------------------------------------
static unsigned long long LegacyFidToInode(unsigned long long fid)
{
return (fid << 28);
}
static unsigned long long LegacyInodeToFid(unsigned long long ino)
{
return (ino >> 28);
}
static bool LegacyIsFileInode(unsigned long long ino)
{
return (ino >= (1 << 28));
}
//----------------------------------------------------------------------------
//! Compute a path from a fid and localprefix
//----------------------------------------------------------------------------
static std::string FidPrefix2FullPath(const char* hexstring,
const char* localprefix)
{
std::string fullpath;
if (!hexstring || !localprefix) {
return fullpath;
}
unsigned long long fid = Hex2Fid(hexstring);
std::string slocalprefix = localprefix;
if (*slocalprefix.rbegin() != '/') {
slocalprefix += "/";
}
char sfullpath[16384];
sprintf(sfullpath, "%s%08llx/%s", slocalprefix.c_str(), fid / 10000, hexstring);
fullpath = sfullpath;
return fullpath;
}
//----------------------------------------------------------------------------
//! Compute a fid from a prefix path
//----------------------------------------------------------------------------
static unsigned long long PathToFid(const char* path)
{
XrdOucString hexfid = "";
hexfid = path;
int rpos = hexfid.rfind("/");
if (rpos > 0) {
hexfid.erase(0, rpos + 1);
}
return Hex2Fid(hexfid.c_str());
}
//----------------------------------------------------------------------------
//! Estimate TCP transfer timeout based on file size but not shorter than
//! 30 min.
//!
//! @param fsize file size
//! @param avg_tx average transfer speed in MB/s, default 30 MB/s
//!
//! @return timeout value in seconds
//----------------------------------------------------------------------------
static std::chrono::seconds
EstimateTpcTimeout(const uint64_t fsize, uint64_t avg_tx = 30)
{
const uint64_t default_timeout = 1800;
uint64_t timeout = fsize / (avg_tx * std::pow(2, 20));
if (timeout < default_timeout) {
timeout = default_timeout;
}
return std::chrono::seconds(timeout);
}
};
EOSCOMMONNAMESPACE_END