Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Loading...
Searching...
No Matches
TDavixFile.cxx
Go to the documentation of this file.
1// @(#)root/net:$Id$
2// Author: Adrien Devresse and Tigran Mkrtchyan
3
4/*************************************************************************
5 * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TDavixFile //
15// //
16// A TDavixFile is like a normal TFile except that it uses //
17// libdavix to read/write remote files. //
18// It supports HTTP and HTTPS in a number of dialects and options //
19// e.g. S3 is one of them //
20// Other caracteristics come from the full support of Davix, //
21// e.g. full redirection support in any circumstance //
22// //
23// Authors: Adrien Devresse (CERN IT/SDC) //
24// Tigran Mkrtchyan (DESY) //
25// //
26// Checks and ROOT5 porting: //
27// Fabrizio Furano (CERN IT/SDC) //
28// //
29// September 2013 //
30// //
31//////////////////////////////////////////////////////////////////////////
32
33#include "ROOT/RLogger.hxx"
34#include "TDavixFile.h"
35#include "TROOT.h"
36#include "TSocket.h"
37#include "Bytes.h"
38#include "TError.h"
39#include "TEnv.h"
40#include "TBase64.h"
41#include "TVirtualPerfStats.h"
42#include "TDavixFileInternal.h"
43#include "utils.h"
44#include "snprintf.h"
45
46#include <cerrno>
47#include <cstdlib>
48#include <unistd.h>
49#include <fcntl.h>
50#include <davix.hpp>
51#include <sstream>
52#include <string>
53#include <cstring>
54
55
56static const std::string VERSION = "0.2.0";
57
58static const std::string gUserAgent = "ROOT/" + std::string(gROOT->GetVersion()) +
59" TDavixFile/" + VERSION + " davix/" + Davix::version();
60
61// The prefix that is used to find the variables in the gEnv
62#define ENVPFX "Davix."
63
65
66using namespace Davix;
67
68const char* grid_mode_opt = "grid_mode=yes";
69const char* ca_check_opt = "ca_check=no";
70const char* s3_seckey_opt = "s3seckey=";
71const char* s3_acckey_opt = "s3acckey=";
72const char* s3_region_opt = "s3region=";
73const char* s3_token_opt = "s3token=";
74const char* s3_alternate_opt = "s3alternate=";
75const char* open_mode_read = "READ";
76const char* open_mode_create = "CREATE";
77const char* open_mode_new = "NEW";
78const char* open_mode_update = "UPDATE";
79
81static Context* davix_context_s = NULL;
82
83////////////////////////////////////////////////////////////////////////////////
84
90
91////////////////////////////////////////////////////////////////////////////////
92
93bool strToBool(const char *str, bool defvalue) {
94 if(!str) return defvalue;
95
96 if(strcmp(str, "n") == 0 || strcmp(str, "no") == 0 || strcmp(str, "0") == 0 || strcmp(str, "false") == 0) return false;
97 if(strcmp(str, "y") == 0 || strcmp(str, "yes") == 0 || strcmp(str, "1") == 0 || strcmp(str, "true") == 0) return true;
98
99 return defvalue;
100}
101
102////////////////////////////////////////////////////////////////////////////////
103
104int configure_open_flag(const std::string &str, int old_flag)
105{
106 if (strcasecmp(str.c_str(), open_mode_read) == 0)
108 if ((strcasecmp(str.c_str(), open_mode_create) == 0)
109 || (strcasecmp(str.c_str(), open_mode_new) == 0)) {
111 }
112 if ((strcasecmp(str.c_str(), open_mode_update) == 0)) {
113 old_flag |= (O_RDWR);
114 }
115 return old_flag;
116}
117
118////////////////////////////////////////////////////////////////////////////////
119
121{
122 Int_t log_level = (gEnv) ? gEnv->GetValue("Davix.Debug", 0) : 0;
123
124 switch (log_level) {
125 case 0:
127 break;
128 case 1:
130 break;
131 case 2:
133 break;
134 case 3:
136 break;
137 default:
139 break;
140 }
141}
142
143////////////////////////////////////////////////////////////////////////////////
144
145bool normalizeToken(const std::string &input_token, std::string &output_token)
146{
147 static const std::string whitespace = " \t\f\n\v\r";
148 // Tokens are meant for use in an HTTP header; these are forbidden
149 // characters.
150 static const std::string nonheader_whitespace = "\r\n";
151 auto begin = input_token.find_first_not_of(whitespace);
152 // No token here, but not an error.
153 if (begin == std::string::npos) {
154 output_token = "";
155 return true;
156 }
157
158 std::string token = input_token.substr(begin);
159 auto end = token.find_last_not_of(whitespace);
160 token = token.substr(0, end + 1);
161
162 // If non-permitted header characters are present ("\r\n"),
163 // then this token is not permitted.
164 if (token.find(nonheader_whitespace) != std::string::npos) {
165 output_token = "";
166 R__LOG_ERROR(TDavixLogChannel()) << "Token discovery failure: token contains non-permitted character sequence (\r\n)";
167 return false;
168 }
170 return true;
171}
172
173bool findTokenInFile(const std::string &token_file, std::string &output_token)
174{
175 R__LOG_INFO(TDavixLogChannel()) << "Looking for token in file " << token_file.c_str();
176 int fd = open(token_file.c_str(), O_RDONLY);
177 if (fd == -1) {
178 output_token = "";
179 if (errno == ENOENT) {
180 return true;
181 }
182 R__LOG_ERROR(TDavixLogChannel()) << "Cannot open '" << token_file << "', error: " << strerror(errno);
183 return false;
184 }
185
186 // As a pragmatic matter, we limit tokens to 16KB; this is often the limit
187 // in size of HTTP headers for many web servers.
188 // This also avoids unbounded memory use in case if the user points us to
189 // a large file.
190 static const size_t max_size = 16384;
191 std::vector<char> input_buffer;
192 input_buffer.resize(max_size);
193 ssize_t retval = read(fd, &input_buffer[0], max_size);
194 close(fd);
195
196 if (retval == -1) {
197 output_token = "";
198 R__LOG_ERROR(TDavixLogChannel()) << "Token discovery failure: failed to read file " << token_file.c_str() << "', error: " << strerror(errno);
199 return false;
200 }
201 if (retval == 16384) {
202 // Token may have been truncated! Erring on the side of caution.
203 R__LOG_ERROR(TDavixLogChannel()) << "Token discovery failure: token was larger than 16KB limit.";
204 return false;
205 }
206
207 std::string token(&input_buffer[0], retval);
208
210}
211
212// Token discovery process is based on WLCG specification:
213// https://github.com/WLCG-AuthZ-WG/bearer-token-discovery/blob/master/specification.md
214std::string DiscoverToken()
215{
216 const char *bearer_token = getenv("BEARER_TOKEN");
217 std::string token;
218 if (bearer_token && *bearer_token){
219 if (!normalizeToken(bearer_token, token)) {return "";}
220 if (!token.empty()) {return token;}
221 }
222
223 const char *bearer_token_file = getenv("BEARER_TOKEN_FILE");
224 if (bearer_token_file) {
225 if (!findTokenInFile(bearer_token_file, token)) {return "";}
226 if (!token.empty()) {return token;}
227 }
228
229#ifndef WIN32
230 uid_t euid = geteuid();
231 std::string fname = "/bt_u";
232 fname += std::to_string(euid);
233
234 const char *xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
235 if (xdg_runtime_dir) {
236 std::string xdg_token_file = std::string(xdg_runtime_dir) + fname;
237 if (!findTokenInFile(xdg_token_file, token)) {return "";}
238 if (!token.empty()) {return token;}
239 }
240
241 if (!findTokenInFile("/tmp" + fname, token)) {return "";}
242 return token;
243#else
244 // WLCG profile doesn't define search paths on Windows;
245 // skip this for now.
246 return "";
247#endif
248}
249
250///////////////////////////////////////////////////////////////////
251// Authn implementation, Locate and get VOMS cred if exist
252
253////////////////////////////////////////////////////////////////////////////////
254
255static void TDavixFile_http_get_ucert(std::string &ucert, std::string &ukey)
256{
257 char default_proxy[64];
258 const char *genvvar = 0, *genvvar1 = 0;
259 // The gEnv has higher priority, let's look for a proxy cert
260 genvvar = gEnv->GetValue("Davix.GSI.UserProxy", (const char *) NULL);
261 if (genvvar) {
262 ucert = ukey = genvvar;
263 if (gDebug > 0)
264 Info("TDavixFile_http_get_ucert", "Found proxy in gEnv");
265 return;
266 }
267
268 // Try explicit environment for proxy
269 if (getenv("X509_USER_PROXY")) {
270 if (gDebug > 0)
271 Info("TDavixFile_http_get_ucert", "Found proxy in X509_USER_PROXY");
272 ucert = ukey = getenv("X509_USER_PROXY");
273 return;
274 }
275
276 // Try with default location
277 snprintf(default_proxy, sizeof(default_proxy), "/tmp/x509up_u%d",
278 geteuid());
279
280 if (access(default_proxy, R_OK) == 0) {
281 if (gDebug > 0)
282 Info("TDavixFile_http_get_ucert", "Found proxy in /tmp");
284 return;
285 }
286
287 // It seems we got no proxy, let's try to gather the keys
288 genvvar = gEnv->GetValue("Davix.GSI.UserCert", (const char *) NULL);
289 genvvar1 = gEnv->GetValue("Davix.GSI.UserKey", (const char *) NULL);
290 if (genvvar || genvvar1) {
291 if (gDebug > 0)
292 Info("TDavixFile_http_get_ucert", "Found cert and key in gEnv");
293
294 ucert = genvvar;
295 ukey = genvvar1;
296 return;
297 }
298
299 // try with X509_* environment
300 if (getenv("X509_USER_CERT"))
301 ucert = getenv("X509_USER_CERT");
302 if (getenv("X509_USER_KEY"))
303 ukey = getenv("X509_USER_KEY");
304
305 if ((ucert.size() > 0) || (ukey.size() > 0)) {
306 if (gDebug > 0)
307 Info("TDavixFile_http_get_ucert", "Found cert and key in gEnv");
308 }
309 return;
310
311}
312
313////////////////////////////////////////////////////////////////////////////////
314
315static int TDavixFile_http_authn_cert_X509(void *userdata, const Davix::SessionInfo &info,
316 Davix::X509Credential *cert, Davix::DavixError **err)
317{
318 (void) userdata; // keep quiete compilation warnings
319 (void) info;
320 std::string ucert, ukey;
322
323 if (ucert.empty() || ukey.empty()) {
324 Davix::DavixError::setupError(err, "TDavixFile",
325 Davix::StatusCode::AuthentificationError,
326 "Could not set the user's proxy or certificate");
327 return -1;
328 }
329 return cert->loadFromFilePEM(ukey, ucert, "", err);
330}
331/////////////////////////////////////////////////////////////////////////////////////////////
332
333////////////////////////////////////////////////////////////////////////////////
334
340
341////////////////////////////////////////////////////////////////////////////////
342
344{
345 if (davix_context_s == NULL) {
346 TLockGuard guard(&createLock);
347 if (davix_context_s == NULL) {
348 davix_context_s = new Context();
349 }
350 }
351 return davix_context_s;
352}
353
354////////////////////////////////////////////////////////////////////////////////
355
357{
360 if (fd == NULL) {
361 // An error has occurred.. We might be able to recover with metalinks.
362 // Try to populate the replicas vector. If successful, TFile will try
363 // the replicas one by one
364
365 replicas.clear();
367 try {
368 DavFile file(*davixContext, Davix::Uri(fUrl.GetUrl()));
369 std::vector<DavFile> replicasLocal = file.getReplicas(NULL, &davixErr2);
370 for(size_t i = 0; i < replicasLocal.size(); i++) {
371 replicas.push_back(replicasLocal[i].getUri().getString());
372 }
373 }
374 catch(...) {}
375 DavixError::clearError(&davixErr2);
376
377 if(replicas.empty()) {
378 // I was unable to retrieve a list of replicas: propagate the original
379 // error.
380 Error("DavixOpen", "can not open file \"%s\" with davix: %s (%d)",
381 fUrl.GetUrl(),
382 davixErr->getErrMsg().c_str(), davixErr->getStatus());
383 }
384 DavixError::clearError(&davixErr);
385 } else {
386 // setup ROOT style read
387 davixPosix->fadvise(fd, 0, 300, Davix::AdviseRandom);
388 }
389
390 return fd;
391}
392
393////////////////////////////////////////////////////////////////////////////////
394
396{
398 if (davixFd != NULL && davixPosix->close(davixFd, &davixErr)) {
399 Error("DavixClose", "can not to close file with davix: %s (%d)",
400 davixErr->getErrMsg().c_str(), davixErr->getStatus());
401 DavixError::clearError(&davixErr);
402 }
403}
404
405////////////////////////////////////////////////////////////////////////////////
406
408{
409 const char *env_var = NULL;
410
411 if (gDebug > 1)
412 Info("enableGridMode", " grid mode enabled !");
413
414 if( ( env_var = getenv("X509_CERT_DIR")) == NULL){
415 env_var= "/etc/grid-security/certificates/";
416 }
417 davixParam->addCertificateAuthorityPath(env_var);
418 if (gDebug > 0)
419 Info("enableGridMode", "Adding CAdir %s", env_var);
420}
421
422////////////////////////////////////////////////////////////////////////////////
423
424// Only newer versions of davix support setting the S3 region and STS tokens.
425// But it's only possible to check the davix version through a #define starting from
426// 0.6.4.
427// I have no way to check if setAwsRegion is available, so let's use SFINAE. :-)
428// The first overload will always take priority - if "substitution" fails, meaning
429// setAwsRegion is not there, the compiler will pick the second overload with
430// the ellipses. (...)
431
432template<typename TRequestParams = Davix::RequestParams>
433static auto awsRegion(TRequestParams *parameters, const char *region)
434 -> decltype(parameters->setAwsRegion(region), void())
435{
436 if (gDebug > 1) Info("awsRegion", "Setting S3 Region to '%s' - v4 signature will be used", region);
437 parameters->setAwsRegion(region);
438}
439
440template<typename TRequestParams = Davix::RequestParams>
441static void awsRegion(...) {
442 Warning("setAwsRegion", "Unable to set AWS region, not supported by this version of davix");
443}
444
445// Identical SFINAE trick as above for setAwsToken
446template<typename TRequestParams = Davix::RequestParams>
447static auto awsToken(TRequestParams *parameters, const char *token)
448 -> decltype(parameters->setAwsToken(token), void())
449{
450 if (gDebug > 1) Info("awsToken", "Setting S3 STS temporary credentials");
451 parameters->setAwsToken(token);
452}
453
454template<typename TRequestParams = Davix::RequestParams>
455static void awsToken(...) {
456 Warning("awsToken", "Unable to set AWS token, not supported by this version of davix");
457}
458
459// Identical SFINAE trick as above for setAwsAlternate
460template<typename TRequestParams = Davix::RequestParams>
461static auto awsAlternate(TRequestParams *parameters, bool option)
462 -> decltype(parameters->setAwsAlternate(option), void())
463{
464 if (gDebug > 1) Info("awsAlternate", "Setting S3 path-based bucket option (s3alternate)");
465 parameters->setAwsAlternate(option);
466}
467
468template<typename TRequestParams = Davix::RequestParams>
469static void awsAlternate(...) {
470 Warning("awsAlternate", "Unable to set AWS path-based bucket option (s3alternate), not supported by this version of davix");
471}
472
473void TDavixFileInternal::setAwsRegion(const std::string & region) {
474 if(!region.empty()) {
475 awsRegion(davixParam, region.c_str());
476 }
477}
478
479void TDavixFileInternal::setAwsToken(const std::string & token) {
480 if(!token.empty()) {
481 awsToken(davixParam, token.c_str());
482 }
483}
484
488
489
490void TDavixFileInternal::setS3Auth(const std::string &secret, const std::string &access,
491 const std::string &region, const std::string &token)
492{
493 if (gDebug > 1) {
494 Info("setS3Auth", " Aws S3 tokens configured");
495 }
496 davixParam->setAwsAuthorizationKeys(secret, access);
497 davixParam->setProtocol(RequestProtocol::AwsS3);
498
501}
502
503////////////////////////////////////////////////////////////////////////////////
504
506{
507 const char *env_var = NULL, *env_var2 = NULL;
508 // default opts
509 davixParam->setTransparentRedirectionSupport(true);
510 davixParam->setClientCertCallbackX509(&TDavixFile_http_authn_cert_X509, NULL);
511
512 // setup CADIR
513 env_var = gEnv->GetValue("Davix.GSI.CAdir", (const char *) NULL);
514 if (env_var) {
515 davixParam->addCertificateAuthorityPath(env_var);
516 if (gDebug > 0)
517 Info("parseConfig", "Add CAdir: %s", env_var);
518 }
519
520 // CA Check
521 bool ca_check_local = !isno(gEnv->GetValue("Davix.GSI.CACheck", (const char *)"y"));
522 davixParam->setSSLCAcheck(ca_check_local);
523 if (gDebug > 0)
524 Info("parseConfig", "Setting CAcheck to %s", ((ca_check_local) ? ("true") : ("false")));
525
526 // WLCG Bearer tokens check
527 std::string prefix = "Bearer ";
528 auto token = DiscoverToken();
529 if (!token.empty()) {
530 // header: "Authorization: Bearer mytoken"
531 R__LOG_INFO(TDavixLogChannel()) << "Using Bearer token starting with: " << token.substr(0, 3);
532 davixParam->addHeader("Authorization", prefix + token);
533 }
534
535 // S3 Auth
536 if (((env_var = gEnv->GetValue("Davix.S3.SecretKey", getenv("S3_SECRET_KEY"))) != NULL)
537 && ((env_var2 = gEnv->GetValue("Davix.S3.AccessKey", getenv("S3_ACCESS_KEY"))) != NULL)) {
538 Info("parseConfig", "Setting S3 SecretKey and AccessKey. Access Key : %s ", env_var2);
539 davixParam->setAwsAuthorizationKeys(env_var, env_var2);
540
541 // need to set region?
542 if ( (env_var = gEnv->GetValue("Davix.S3.Region", getenv("S3_REGION"))) != NULL) {
544 }
545 // need to set STS token?
546 if( (env_var = gEnv->GetValue("Davix.S3.Token", getenv("S3_TOKEN"))) != NULL) {
548 }
549 // need to set aws alternate?
550 if( (env_var = gEnv->GetValue("Davix.S3.Alternate", getenv("S3_ALTERNATE"))) != NULL) {
552 }
553 }
554
555 env_var = gEnv->GetValue("Davix.GSI.GridMode", (const char *)"y");
556 if (!isno(env_var))
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// intput params
562
564{
565 std::stringstream ss(option);
566 std::string item;
567 std::vector<std::string> parsed_options;
568 // parameters
569 std::string s3seckey, s3acckey, s3region, s3token;
570
571 while (std::getline(ss, item, ' ')) {
572 parsed_options.push_back(item);
573 }
574
575 for (std::vector<std::string>::iterator it = parsed_options.begin(); it < parsed_options.end(); ++it) {
576 // grid mode option
577 if ((strcasecmp(it->c_str(), grid_mode_opt)) == 0) {
579 }
580 // ca check option
581 if ((strcasecmp(it->c_str(), ca_check_opt)) == 0) {
582 davixParam->setSSLCAcheck(false);
583 }
584 // s3 sec key
585 if (strncasecmp(it->c_str(), s3_seckey_opt, strlen(s3_seckey_opt)) == 0) {
586 s3seckey = std::string(it->c_str() + strlen(s3_seckey_opt));
587 }
588 // s3 access key
589 if (strncasecmp(it->c_str(), s3_acckey_opt, strlen(s3_acckey_opt)) == 0) {
590 s3acckey = std::string(it->c_str() + strlen(s3_acckey_opt));
591 }
592 // s3 region
593 if (strncasecmp(it->c_str(), s3_region_opt, strlen(s3_region_opt)) == 0) {
594 s3region = std::string(it->c_str() + strlen(s3_region_opt));
595 }
596 // s3 sts token
597 if (strncasecmp(it->c_str(), s3_token_opt, strlen(s3_token_opt)) == 0) {
598 s3token = std::string(it->c_str() + strlen(s3_token_opt));
599 }
600 // s3 alternate option
601 if (strncasecmp(it->c_str(), s3_alternate_opt, strlen(s3_alternate_opt)) == 0) {
602 setAwsAlternate(strToBool(it->c_str() + strlen(s3_alternate_opt), false));
603 }
604 // open mods
606 }
607
608 if (s3seckey.size() > 0) {
610 }
611
612 if (oflags == 0) // default open mode
614}
615
616////////////////////////////////////////////////////////////////////////////////
617
619{
620 davixPosix = new DavPosix(davixContext);
621 davixParam = new RequestParams();
622 davixParam->setUserAgent(gUserAgent);
623 davixParam->setMetalinkMode(Davix::MetalinkMode::Disable);
625 parseConfig();
627}
628
629////////////////////////////////////////////////////////////////////////////////
630
631Int_t TDavixFileInternal::DavixStat(const char *url, struct stat *st)
632{
634
635 if (davixPosix->stat(davixParam, url, st, &davixErr) < 0) {
636
637 Error("DavixStat", "can not stat the file with davix: %s (%d)",
638 davixErr->getErrMsg().c_str(), davixErr->getStatus());
639 DavixError::clearError(&davixErr);
640 return 0;
641 }
642 return 1;
643}
644
645/////////////////////////////////////////////////////////////////////////////////////////////
646
647////////////////////////////////////////////////////////////////////////////////
648
649TDavixFile::TDavixFile(const char *url, Option_t *opt, const char *ftitle, Int_t compress)
650 : TFile(url, strstr(opt, "_WITHOUT_GLOBALREGISTRATION") != nullptr ? "WEB_WITHOUT_GLOBALREGISTRATION" : "WEB"),
651 d_ptr(new TDavixFileInternal(fUrl, opt))
652{
653 (void) ftitle;
654 (void) compress;
655 Init(kFALSE);
656}
657
658////////////////////////////////////////////////////////////////////////////////
659
661{
662 d_ptr->Close();
663 delete d_ptr;
664}
665
666////////////////////////////////////////////////////////////////////////////////
667
669{
670 (void) init;
671 //initialize davix
672 d_ptr->init();
673 // pre-open file
674 if ((d_ptr->getDavixFileInstance()) == NULL){
675 MakeZombie();
677 return;
678 }
680 fOffset = 0;
681 fD = -2; // so TFile::IsOpen() will return true when in TFile::~TFi */
682}
683
685 std::vector<std::string> replicas = d_ptr->getReplicas();
687 if(!replicas.empty()) {
688 std::stringstream ss;
689 for(size_t i = 0; i < replicas.size(); i++) {
690 ss << replicas[i];
691 if(i != replicas.size()-1) ss << "|";
692 }
693 newUrl = ss.str();
694 }
695 return newUrl;
696}
697
698////////////////////////////////////////////////////////////////////////////////
699/// Set position from where to start reading.
700
702{
703 TLockGuard guard(&(d_ptr->positionLock));
704 switch (pos) {
705 case kBeg:
707 break;
708 case kCur:
709 fOffset += offset;
710 break;
711 case kEnd:
712 // this option is not used currently in the ROOT code
713 if (fArchiveOffset)
714 Error("Seek", "seeking from end in archive is not (yet) supported");
715 fOffset = fEND - offset; // is fEND really EOF or logical EOF?
716 break;
717 }
718
719 if (gDebug > 1)
720 Info("Seek", " move cursor to %lld"
721 , fOffset);
722}
723
724////////////////////////////////////////////////////////////////////////////////
725/// Read specified byte range from remote file via HTTP.
726/// Returns kTRUE in case of error.
727
729{
730 TLockGuard guard(&(d_ptr->positionLock));
731 Davix_fd *fd;
732 if ((fd = d_ptr->getDavixFileInstance()) == NULL)
733 return kTRUE;
734 Long64_t ret = DavixReadBuffer(fd, buf, len);
735 if (ret < 0)
736 return kTRUE;
737
738 if (gDebug > 1)
739 Info("ReadBuffer", "%lld bytes of data read sequentially"
740 " (%d requested)", ret, len);
741
742 return kFALSE;
743}
744
745////////////////////////////////////////////////////////////////////////////////
746
748{
749 Davix_fd *fd;
750 if ((fd = d_ptr->getDavixFileInstance()) == NULL)
751 return kTRUE;
752
753 Long64_t ret = DavixPReadBuffer(fd, buf, pos, len);
754 if (ret < 0)
755 return kTRUE;
756
757 if (gDebug > 1)
758 Info("ReadBuffer", "%lld bytes of data read from offset"
759 " %lld (%d requested)", ret, pos, len);
760 return kFALSE;
761}
762
763////////////////////////////////////////////////////////////////////////////////
764
766{
767 Davix_fd *fd;
768 if ((fd = d_ptr->getDavixFileInstance()) == NULL)
769 return kFALSE;
770
771 d_ptr->davixPosix->fadvise(fd, static_cast<dav_off_t>(offs), static_cast<dav_size_t>(len), Davix::AdviseRandom);
772
773 if (gDebug > 1)
774 Info("ReadBufferAsync", "%d bytes of data prefected from offset"
775 " %lld ", len, offs);
776 return kFALSE;
777}
778
779////////////////////////////////////////////////////////////////////////////////
780
782{
783 Davix_fd *fd;
784 if ((fd = d_ptr->getDavixFileInstance()) == NULL)
785 return kTRUE;
786
787 Long64_t ret = DavixReadBuffers(fd, buf, pos, len, nbuf);
788 if (ret < 0)
789 return kTRUE;
790
791 if (gDebug > 1)
792 Info("ReadBuffers", "%lld bytes of data read from a list of %d buffers",
793 ret, nbuf);
794
795 return kFALSE;
796}
797
798////////////////////////////////////////////////////////////////////////////////
799
801{
802 Davix_fd *fd;
803 if ((fd = d_ptr->getDavixFileInstance()) == NULL)
804 return kTRUE;
805
806 Long64_t ret = DavixWriteBuffer(fd, buf, len);
807 if (ret < 0)
808 return kTRUE;
809
810 if (gDebug > 1)
811 Info("WriteBuffer", "%lld bytes of data write"
812 " %d requested", ret, len);
813 return kFALSE;
814}
815
816////////////////////////////////////////////////////////////////////////////////
817
819{
820 d_ptr->davixParam->setSSLCAcheck((bool)check);
821}
822
823////////////////////////////////////////////////////////////////////////////////
824
829
830////////////////////////////////////////////////////////////////////////////////
831
833{
835 std::vector<void *>::iterator f = std::find(dirdVec.begin(), dirdVec.end(), fd);
836 return (f != dirdVec.end());
837}
838
839////////////////////////////////////////////////////////////////////////////////
840
842{
844 dirdVec.push_back(fd);
845}
846
847////////////////////////////////////////////////////////////////////////////////
848
850{
852 std::vector<void *>::iterator f = std::find(dirdVec.begin(), dirdVec.end(), fd);
853 if (f != dirdVec.end())
854 dirdVec.erase(f);
855}
856
857////////////////////////////////////////////////////////////////////////////////
858
860{
861 struct stat st;
863 if (ret) {
864 if (gDebug > 1)
865 Info("GetSize", "file size requested: %lld", (Long64_t)st.st_size);
866 return st.st_size;
867 }
868 return -1;
869}
870
871////////////////////////////////////////////////////////////////////////////////
872
874{
875 if (gPerfStats)
876 return TTimeStamp();
877 return 0;
878}
879
880////////////////////////////////////////////////////////////////////////////////
881/// set TFile state info
882
884{
885 if(read) {
886 fBytesRead += len;
887 fReadCalls += 1;
888
891
892 if (gPerfStats)
893 gPerfStats->FileReadEvent(this, (Int_t) len, t_start);
894 } else {
895 fBytesWrite += len;
897 }
898}
899
900////////////////////////////////////////////////////////////////////////////////
901
903{
905 Double_t start_time = eventStart();
906
907 Long64_t ret = d_ptr->davixPosix->pread(fd, buf, len, fOffset, &davixErr);
908 if (ret < 0) {
909 Error("DavixReadBuffer", "can not read data with davix: %s (%d)",
910 davixErr->getErrMsg().c_str(), davixErr->getStatus());
911 DavixError::clearError(&davixErr);
912 } else {
913 fOffset += ret;
914 eventStop(start_time, ret);
915 }
916
917 return ret;
918}
919
920////////////////////////////////////////////////////////////////////////////////
921
923{
925 Double_t start_time = eventStart();
926
927 Long64_t ret = d_ptr->davixPosix->pwrite(fd, buf, len, fOffset, &davixErr);
928 if (ret < 0) {
929 Error("DavixWriteBuffer", "can not write data with davix: %s (%d)",
930 davixErr->getErrMsg().c_str(), davixErr->getStatus());
931 DavixError::clearError(&davixErr);
932 } else {
933 fOffset += ret;
934 eventStop(start_time, ret, false);
935 }
936
937 return ret;
938}
939
940////////////////////////////////////////////////////////////////////////////////
941
943{
945 Double_t start_time = eventStart();
946
947 Long64_t ret = d_ptr->davixPosix->pread(fd, buf, len, pos, &davixErr);
948 if (ret < 0) {
949 Error("DavixPReadBuffer", "can not read data with davix: %s (%d)",
950 davixErr->getErrMsg().c_str(), davixErr->getStatus());
951 DavixError::clearError(&davixErr);
952 } else {
953 eventStop(start_time, ret);
954 }
955
956
957 return ret;
958}
959
960////////////////////////////////////////////////////////////////////////////////
961
963{
965 Double_t start_time = eventStart();
967 DavIOVecOuput out[nbuf];
968
969 int lastPos = 0;
970 for (Int_t i = 0; i < nbuf; ++i) {
971 in[i].diov_buffer = &buf[lastPos];
972 in[i].diov_offset = pos[i];
973 in[i].diov_size = len[i];
974 lastPos += len[i];
975 }
976
977 Long64_t ret = d_ptr->davixPosix->preadVec(fd, in, out, nbuf, &davixErr);
978 if (ret < 0) {
979 Error("DavixReadBuffers", "can not read data with davix: %s (%d)",
980 davixErr->getErrMsg().c_str(), davixErr->getStatus());
981 DavixError::clearError(&davixErr);
982 } else {
983 eventStop(start_time, ret);
984 }
985
986 return ret;
987}
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define R__LOG_INFO(...)
Definition RLogger.hxx:364
#define f(i)
Definition RSha256.hxx:104
int Int_t
Definition RtypesCore.h:45
constexpr Bool_t kFALSE
Definition RtypesCore.h:101
long long Long64_t
Definition RtypesCore.h:80
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
const char * s3_seckey_opt
bool normalizeToken(const std::string &input_token, std::string &output_token)
static const std::string VERSION
static void ConfigureDavixLogLevel()
static auto awsRegion(TRequestParams *parameters, const char *region) -> decltype(parameters->setAwsRegion(region), void())
bool findTokenInFile(const std::string &token_file, std::string &output_token)
static TMutex createLock
static auto awsAlternate(TRequestParams *parameters, bool option) -> decltype(parameters->setAwsAlternate(option), void())
std::string DiscoverToken()
static int TDavixFile_http_authn_cert_X509(void *userdata, const Davix::SessionInfo &info, Davix::X509Credential *cert, Davix::DavixError **err)
const char * s3_alternate_opt
static auto awsToken(TRequestParams *parameters, const char *token) -> decltype(parameters->setAwsToken(token), void())
const char * s3_token_opt
const char * ca_check_opt
const char * open_mode_new
const char * open_mode_update
const char * open_mode_create
const char * s3_acckey_opt
static Context * davix_context_s
const char * grid_mode_opt
ROOT::Experimental::RLogChannel & TDavixLogChannel()
int configure_open_flag(const std::string &str, int old_flag)
static void TDavixFile_http_get_ucert(std::string &ucert, std::string &ukey)
static const std::string gUserAgent
bool strToBool(const char *str, bool defvalue)
const char * s3_region_opt
const char * open_mode_read
ROOT::Experimental::RLogChannel & TDavixLogChannel()
#define gDirectory
Definition TDirectory.h:384
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:218
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:185
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Int_t gDebug
Definition TROOT.cxx:597
#define gROOT
Definition TROOT.h:406
#define gPerfStats
#define snprintf
Definition civetweb.c:1540
A log configuration for a channel, e.g.
Definition RLogger.hxx:101
const_iterator begin() const
const_iterator end() const
void addDird(void *fd)
Davix::RequestParams * davixParam
bool isMyDird(void *fd)
std::vector< void * > dirdVec
void setAwsToken(const std::string &token)
void setS3Auth(const std::string &secret, const std::string &access, const std::string &region, const std::string &token)
void setAwsAlternate(const bool &option)
static Davix::Context * getDavixInstance()
Davix::DavPosix * davixPosix
void parseParams(Option_t *option)
intput params
std::vector< std::string > getReplicas()
Int_t DavixStat(const char *url, struct stat *st)
Davix_fd * getDavixFileInstance()
Davix_fd * Open()
Davix::Context * davixContext
void setAwsRegion(const std::string &region)
std::vector< std::string > replicas
void removeDird(void *fd)
virtual Long64_t GetSize() const
Returns the current file size.
void Init(Bool_t init)
Initialize a TFile object.
Long64_t DavixReadBuffers(Davix_fd *fd, char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
Long64_t DavixReadBuffer(Davix_fd *fd, char *buf, Int_t len)
Long64_t DavixPReadBuffer(Davix_fd *fd, char *buf, Long64_t pos, Int_t len)
virtual Bool_t WriteBuffer(const char *buffer, Int_t bufferLength)
Write a buffer to the file.
virtual TString GetNewUrl()
Long64_t DavixWriteBuffer(Davix_fd *fd, const char *buf, Int_t len)
virtual Bool_t ReadBufferAsync(Long64_t offs, Int_t len)
virtual Bool_t ReadBuffer(char *buf, Int_t len)
Read specified byte range from remote file via HTTP.
TDavixFile(const char *url, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault)
Open function for TDavixFile.
void enableGridMode()
Enable the grid mode The grid Mode configure automatically all grid-CA path, VOMS authentication and ...
virtual void Seek(Long64_t offset, ERelativeTo pos=kBeg)
Set position from where to start reading.
TDavixFileInternal * d_ptr
Definition TDavixFile.h:72
virtual Bool_t ReadBuffers(char *buf, Long64_t *pos, Int_t *len, Int_t nbuf)
Read the nbuf blocks described in arrays pos and len.
void eventStop(Double_t t, Long64_t len, bool read=true)
set TFile state info
void setCACheck(Bool_t check)
Enable or disable certificate authority check.
Double_t eventStart()
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
Definition TFile.h:53
Int_t fReadCalls
Number of read calls ( not counting the cache calls )
Definition TFile.h:89
static void SetFileBytesWritten(Long64_t bytes=0)
Definition TFile.cxx:4616
Long64_t fBytesRead
Number of bytes read from this file.
Definition TFile.h:76
static Long64_t GetFileBytesWritten()
Static function returning the total number of bytes written to all files.
Definition TFile.cxx:4588
static void SetFileBytesRead(Long64_t bytes=0)
Definition TFile.cxx:4613
static void SetFileReadCalls(Int_t readcalls=0)
Definition TFile.cxx:4619
TUrl fUrl
!URL of file
Definition TFile.h:110
static Long64_t GetFileBytesRead()
Static function returning the total number of bytes read from all files.
Definition TFile.cxx:4579
Long64_t fArchiveOffset
!Offset at which file starts in archive
Definition TFile.h:101
virtual void Init(Bool_t create)
Initialize a TFile object.
Definition TFile.cxx:613
ERelativeTo
Definition TFile.h:199
@ kCur
Definition TFile.h:199
@ kBeg
Definition TFile.h:199
@ kEnd
Definition TFile.h:199
Int_t fD
File descriptor.
Definition TFile.h:82
Long64_t fBytesWrite
Number of bytes written to this file.
Definition TFile.h:75
Long64_t fOffset
!Seek offset cache
Definition TFile.h:96
Long64_t fEND
Last used byte in file.
Definition TFile.h:79
static Int_t GetFileReadCalls()
Static function returning the total number of read calls from all files.
Definition TFile.cxx:4596
void MakeZombie()
Definition TObject.h:53
Basic string class.
Definition TString.h:139
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
const char * GetUrl(Bool_t withDeflt=kFALSE) const
Return full URL.
Definition TUrl.cxx:390
TLine l
Definition textangle.C:4
bool isno(const char *str)
Definition utils.h:11