forked from xrootd/xrootd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
35 changed files
with
3,796 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
|
||
#include "BufferUtils.hh" | ||
#include <algorithm> // std::max | ||
|
||
using namespace XrdCephBuffer; | ||
|
||
#ifdef CEPHBUFDEBUG | ||
// to synchronise logging statements | ||
std::mutex cephbuf_iolock; | ||
#endif | ||
|
||
// ------------------------------------------------------ // | ||
// Extent // | ||
|
||
bool Extent::in_extent(off_t pos) const | ||
{ | ||
return ((pos > begin()) && (pos < end())); | ||
} | ||
|
||
bool Extent::isContiguous(const Extent &rhs) const | ||
{ | ||
// does the rhs connect directly to the end of the first | ||
if (end() != rhs.begin()) | ||
return false; | ||
return true; | ||
} | ||
|
||
bool Extent::allInExtent(off_t pos, size_t len) const | ||
{ | ||
// is all the range in this extent | ||
if ((pos < begin()) || (pos >= end())) | ||
return false; | ||
|
||
if (off_t(pos + len) > end()) | ||
return false; | ||
return true; | ||
} | ||
bool Extent::someInExtent(off_t pos, size_t len) const | ||
{ // is some of the range in this extent | ||
if ((off_t(pos + len) < begin()) || (pos >= end())) | ||
return false; | ||
return true; | ||
} | ||
|
||
Extent Extent::containedExtent(off_t pos, size_t len) const | ||
{ | ||
// return the subset of input range that is in this extent | ||
off_t subbeg = std::max(begin(), pos); | ||
off_t subend = std::min(end(), off_t(pos + len)); | ||
|
||
return Extent(subbeg, subend - subbeg); | ||
} | ||
Extent Extent::containedExtent(const Extent &rhs) const | ||
{ | ||
return containedExtent(rhs.begin(), rhs.len()); | ||
} | ||
|
||
bool Extent::operator<(const Extent &rhs) const | ||
{ | ||
// comparison primarily on begin values | ||
// use end values if begin values are equal. | ||
|
||
if (begin() > rhs.begin()) return false; | ||
if (begin() < rhs.begin()) return true; | ||
if (end() < rhs.end() ) return true; | ||
return false; | ||
} | ||
bool Extent::operator==(const Extent &rhs) const | ||
{ | ||
// equivalence based only on start and end | ||
if (begin() != rhs.begin()) | ||
return false; | ||
if (end() != rhs.end()) | ||
return false; | ||
return true; | ||
} | ||
|
||
// ------------------------------------------------------ // | ||
// ExtentHolder // | ||
|
||
ExtentHolder::ExtentHolder() {} | ||
|
||
ExtentHolder::ExtentHolder(size_t elements) | ||
{ | ||
m_extents.reserve(elements); | ||
} | ||
|
||
ExtentHolder::ExtentHolder(const ExtentContainer &extents) | ||
{ | ||
m_extents.reserve(extents.size()); | ||
for (ExtentContainer::const_iterator vit = m_extents.cbegin(); vit != m_extents.cend(); ++vit) { | ||
push_back(*vit); | ||
} | ||
|
||
} | ||
ExtentHolder::~ExtentHolder() | ||
{ | ||
m_extents.clear(); | ||
} | ||
|
||
void ExtentHolder::push_back(const Extent & in) { | ||
if (size()) { | ||
m_begin = std::min(m_begin, in.begin()); | ||
m_end = std::max(m_end, in.end()); | ||
} else { | ||
m_begin = in.begin(); | ||
m_end = in.end(); | ||
} | ||
return m_extents.push_back(in); | ||
} | ||
|
||
|
||
|
||
Extent ExtentHolder::asExtent() const { | ||
// if (!size()) return Extent(0,0); | ||
// ExtentContainer se = getSortedExtents(); | ||
// off_t b = se.front().begin(); | ||
// off_t e = se.back().end(); | ||
|
||
return Extent(m_begin, m_end-m_begin); | ||
|
||
} | ||
|
||
size_t ExtentHolder::bytesContained() const { | ||
size_t nbytes{0}; | ||
for (ExtentContainer::const_iterator vit = m_extents.cbegin(); vit != m_extents.cend(); ++vit) { | ||
nbytes += vit->len(); | ||
} | ||
return nbytes; | ||
} | ||
|
||
size_t ExtentHolder::bytesMissing() const { | ||
size_t bytesUsed = bytesContained(); | ||
size_t totalRange = asExtent().len(); //might be expensive to call | ||
return totalRange - bytesUsed; | ||
} | ||
|
||
|
||
void ExtentHolder::sort() { | ||
std::sort(m_extents.begin(), m_extents.end()); | ||
} | ||
|
||
|
||
ExtentContainer ExtentHolder::getSortedExtents() const { | ||
ExtentContainer v; | ||
v.assign(m_extents.begin(), m_extents.end() ); | ||
std::sort(v.begin(), v.end()); | ||
return v; | ||
} | ||
|
||
ExtentContainer ExtentHolder::getExtents() const { | ||
ExtentContainer v; | ||
v.assign(m_extents.begin(), m_extents.end() ); | ||
return v; | ||
} | ||
|
||
// ------------------------------------------------------ // | ||
// Timer ns // | ||
|
||
Timer_ns::Timer_ns(long &output) : m_output_val(output) | ||
{ | ||
m_start = std::chrono::steady_clock::now(); | ||
} | ||
|
||
Timer_ns::~Timer_ns() | ||
{ | ||
auto end = std::chrono::steady_clock::now(); | ||
m_output_val = std::chrono::duration_cast<std::chrono::nanoseconds>(end - m_start).count(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#ifndef __CEPH_BUFFER_UTILS_HH__ | ||
#define __CEPH_BUFFER_UTILS_HH__ | ||
|
||
// holder of various small utility classes for debugging, profiling, logging, and general stuff | ||
|
||
#include <list> | ||
#include <vector> | ||
#include <atomic> | ||
#include <chrono> | ||
#include <sys/types.h> | ||
#include <memory> | ||
#include <mutex> | ||
#include <sstream> | ||
#include <iomanip> | ||
#include <ctime> | ||
|
||
|
||
// basic logging | ||
// #TODO; merge this into the xrootd logging, when xrootd is available | ||
#define CEPHBUFDEBUG 1 | ||
#ifdef CEPHBUFDEBUG | ||
extern std::mutex cephbuf_iolock; | ||
#define BUFLOG(x) {std::unique_lock<std::mutex>cephbuf_iolock; std::stringstream _bs; _bs << x; std::clog << _bs.str() << std::endl;} | ||
#else | ||
#define BUFLOG(x) | ||
#endif | ||
|
||
namespace XrdCephBuffer | ||
{ | ||
|
||
|
||
class Timer_ns | ||
{ | ||
/** | ||
* @brief RAII based timer information outputing a long value of ns | ||
* Almost trivial class to time something and to pass the duration as a long | ||
* to an output variable (specified in the constructor) at destruction. | ||
* Create the object to start the timer. The timer stops when its destructor is called. | ||
* #TODO improve to template the output type and the time ratio | ||
*/ | ||
public: | ||
explicit Timer_ns(long &output_ns); | ||
~Timer_ns(); | ||
|
||
private: | ||
std::chrono::steady_clock::time_point m_start; | ||
long &m_output_val; //!< reference to the external variable to store the output. | ||
|
||
}; //Timer_ns | ||
|
||
|
||
|
||
class Extent | ||
{ | ||
/** | ||
* @brief Ecapsulates an offsets and length, with added functionaliyu | ||
* Class that represents an offset possition and a length. | ||
* Simplest usecase is to avoid passing two values around, however this class | ||
* provides additional funcationality for manipulation of extends (e.g. merging, splitting) | ||
* which may prove useful. | ||
*/ | ||
|
||
public: | ||
Extent(off_t offset, size_t len) : m_offset(offset), m_len(len){} | ||
inline off_t offset() const { return m_offset; } | ||
inline size_t len() const { return m_len; } | ||
inline off_t begin() const { return m_offset; } //!< Same as offset, but a bit more stl container like | ||
inline off_t end() const { return m_offset + m_len; } //!< similar to stl vector end. | ||
inline bool empty() const {return m_len == 0;} | ||
|
||
/** | ||
* Does the start of the rhs continue directly from the | ||
* end of this Extent | ||
*/ | ||
bool isContiguous(const Extent& rhs) const; | ||
|
||
inline off_t last_pos() const { return m_offset + m_len - 1; } //!< last real position | ||
|
||
bool in_extent(off_t pos) const; //!< is this position within the range of this extent | ||
bool allInExtent(off_t pos, size_t len) const; //!< is all the range in this extent | ||
bool someInExtent(off_t pos, size_t len) const; //!< is some of the range in this extent | ||
|
||
Extent containedExtent(off_t pos, size_t len) const; //!< return the subset of range that is in this extent | ||
Extent containedExtent(const Extent &in) const; //!< | ||
|
||
bool operator<(const Extent &rhs) const; | ||
bool operator==(const Extent &rhs) const; | ||
|
||
|
||
private: | ||
off_t m_offset; | ||
size_t m_len; | ||
}; | ||
|
||
/** | ||
* @brief Container defintion for Extents | ||
* Typedef to provide a container of extents as a simple stl vector container | ||
*/ | ||
typedef std::vector<Extent> ExtentContainer; | ||
|
||
/** | ||
* @brief Designed to hold individual extents, but itself provide Extent-like capabilities | ||
* Useful in cases of combining extends, or needing to hold a range of extends and extract | ||
* information about (or aggregated from) the contained objects. | ||
* Could be useful to inherit from Extent if improvements needed. | ||
* | ||
* | ||
*/ | ||
class ExtentHolder { | ||
// holder of a list of extent objects | ||
public: | ||
ExtentHolder(); | ||
explicit ExtentHolder(size_t elements); //!< reserve memory only | ||
explicit ExtentHolder(const ExtentContainer& extents); | ||
~ExtentHolder(); | ||
|
||
off_t begin() const {return m_begin;} | ||
off_t end() const {return m_end;} | ||
size_t len() const {return m_end - m_begin;} //! Total range in bytes of the extents | ||
|
||
bool empty() const {return m_extents.empty();} | ||
size_t size() const {return m_extents.size();} //!< number of extent elements | ||
|
||
Extent asExtent() const; // return an extent covering the whole range | ||
|
||
|
||
size_t bytesContained() const; // number of bytes across the extent not considering overlaps! | ||
size_t bytesMissing() const; // number of bytes missing across the extent, not considering overlaps! | ||
|
||
void push_back(const Extent & in); | ||
void sort(); //!< inplace sort by offset of contained extents | ||
|
||
const ExtentContainer & extents() const {return m_extents;} | ||
//ExtentContainer & extents() {return m_extents;} | ||
|
||
ExtentContainer getSortedExtents() const; | ||
ExtentContainer getExtents() const; | ||
|
||
|
||
|
||
protected: | ||
ExtentContainer m_extents; | ||
|
||
off_t m_begin{0}; //lowest offset value | ||
off_t m_end{0}; // one past end of last byte used. | ||
|
||
}; | ||
|
||
|
||
} | ||
|
||
#endif |
Oops, something went wrong.