Skip to content

Commit

Permalink
Report cache object age for caching proxy mode
Browse files Browse the repository at this point in the history
When in caching proxy mode, have the HTTP response populate the
standardized `Age` field so the client knows the approximate age
of the object in cache.
  • Loading branch information
bbockelm authored and osschar committed Feb 23, 2023
1 parent 4ef0f2f commit 2c0b531
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 25 deletions.
63 changes: 39 additions & 24 deletions src/XrdHttp/XrdHttpReq.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2286,36 +2286,51 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) {

getfhandle();

// Now parse the stat info if we still don't have it
if (filesize == 0) {
if (iovP[1].iov_len > 1) {
TRACEI(REQ, "Stat for GET " << resource.c_str()
<< " stat=" << (char *) iovP[1].iov_base);

long dummyl;
sscanf((const char *) iovP[1].iov_base, "%ld %lld %ld %ld",
&dummyl,
&filesize,
&fileflags,
&filemodtime);
// Always try to parse response. In the case of a caching proxy, the open
// will have created the file in cache
filectime = 0;
if (iovP[1].iov_len > 1) {
TRACEI(REQ, "Stat for GET " << resource.c_str()
<< " stat=" << (char *) iovP[1].iov_base);

// As above: if the client specified a response size, we use that.
// Otherwise, utilize the filesize
if (!length) {
length = filesize;
}
long dummyl;
sscanf((const char *) iovP[1].iov_base, "%ld %lld %ld %ld %ld",
&dummyl,
&filesize,
&fileflags,
&filemodtime,
&filectime);

// As above: if the client specified a response size, we use that.
// Otherwise, utilize the filesize
if (!length) {
length = filesize;
}
else
TRACEI(ALL, "GET returned no STAT information. Internal error?");
}

else {
TRACEI(ALL, "GET returned no STAT information. Internal error?");
}

std::string responseHeader;
if (!m_digest_header.empty()) {
responseHeader = m_digest_header;
}
long one;
if (filemodtime && XrdOucEnv::Import("XRDPFC", one)) {
if (!responseHeader.empty()) {
responseHeader += "\r\n";
}
long object_age = time(NULL) - filectime;
responseHeader += std::string("Age: ") + std::to_string(object_age < 0 ? 0 : object_age);
}

if (rwOps.size() == 0) {
// Full file.

if (m_transfer_encoding_chunked && m_trailer_headers) {
prot->StartChunkedResp(200, NULL, m_digest_header.empty() ? NULL : m_digest_header.c_str(), filesize, keepalive);
prot->StartChunkedResp(200, NULL, responseHeader.empty() ? NULL : responseHeader.c_str(), filesize, keepalive);
} else {
prot->SendSimpleResp(200, NULL, m_digest_header.empty() ? NULL : m_digest_header.c_str(), NULL, filesize, keepalive);
prot->SendSimpleResp(200, NULL, responseHeader.empty() ? NULL : responseHeader.c_str(), NULL, filesize, keepalive);
}
return 0;
} else
Expand All @@ -2329,9 +2344,9 @@ int XrdHttpReq::PostProcessHTTPReq(bool final_) {
XrdOucString s = "Content-Range: bytes ";
sprintf(buf, "%lld-%lld/%lld", rwOps[0].bytestart, rwOps[0].byteend, filesize);
s += buf;
if (!m_digest_header.empty()) {
if (!responseHeader.empty()) {
s += "\r\n";
s += m_digest_header.c_str();
s += responseHeader.c_str();
}

prot->SendSimpleResp(206, NULL, (char *)s.c_str(), NULL, cnt, keepalive);
Expand Down
1 change: 1 addition & 0 deletions src/XrdHttp/XrdHttpReq.hh
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ public:
long long filesize;
long fileflags;
long filemodtime;
long filectime;
char fhandle[4];
bool fopened;

Expand Down
3 changes: 3 additions & 0 deletions src/XrdPfc/XrdPfcConfiguration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ bool Cache::Config(const char *config_filename, const char *parameters)
const char *theINS = getenv("XRDINSTANCE");
m_isClient = (theINS != 0 && strncmp("*client ", theINS, 8) == 0);

// Tell everyone else we are a caching proxy
XrdOucEnv::Export("XRDPFC", 1);

XrdOucEnv myEnv;
XrdOucStream Config(&m_log, theINS, &myEnv, "=====> ");

Expand Down
7 changes: 6 additions & 1 deletion src/XrdPfc/XrdPfcIOFile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ int IOFile::initCachedStat(const char* path)
int res = -1;
struct stat tmpStat;

if (m_cache.GetOss()->Stat(path, &tmpStat) == XrdOssOK)
if (m_cache.GetOss()->Stat(GetFilename().c_str(), &tmpStat) == XrdOssOK)
{
XrdOssDF* infoFile = m_cache.GetOss()->newFile(Cache::GetInstance().RefConfiguration().m_username.c_str());
XrdOucEnv myEnv;
Expand Down Expand Up @@ -115,6 +115,11 @@ int IOFile::initCachedStat(const char* path)
{
res = GetInput()->Fstat(tmpStat);
TRACEIO(Debug, trace_pfx << "got stat from client res = " << res << ", size = " << tmpStat.st_size);
// The mtime / atime / ctime for cached responses come from the file on disk in the cache hit case.
// To avoid weirdness when two subsequent stat queries can give wildly divergent times (one from the
// origin, one from the cache), set the times to "now" so we effectively only report the *time as the
// cache service sees it.
tmpStat.st_ctime = tmpStat.st_mtime = tmpStat.st_atime = time(NULL);
}

if (res == 0)
Expand Down

0 comments on commit 2c0b531

Please sign in to comment.