Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RRawFile.cxx
Go to the documentation of this file.
1// @(#)root/io:$Id$
2// Author: Jakob Blomer
3
4/*************************************************************************
5 * Copyright (C) 1995-2018, 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#include <ROOT/RConfig.hxx>
13#include <ROOT/RRawFile.hxx>
14#ifdef _WIN32
15#include <ROOT/RRawFileWin.hxx>
16#else
17#include <ROOT/RRawFileUnix.hxx>
18#endif
19
20#include "TError.h"
21#include "TPluginManager.h"
22#include "TROOT.h"
23#include "ROOT/InternalIOUtils.hxx"
24
25#include <algorithm>
26#include <cctype> // for towlower
27#include <cerrno>
28#include <cstddef>
29#include <cstdint>
30#include <cstring>
31#include <stdexcept>
32#include <string>
33
34namespace {
35const char *kTransportSeparator = "://";
36// Corresponds to ELineBreaks
37#ifdef _WIN32
38const char *kLineBreakTokens[] = {"", "\r\n", "\n", "\r\n"};
39constexpr unsigned int kLineBreakTokenSizes[] = {0, 2, 1, 2};
40#else
41const char *kLineBreakTokens[] = {"", "\n", "\n", "\r\n"};
42constexpr unsigned int kLineBreakTokenSizes[] = {0, 1, 1, 2};
43#endif
44constexpr unsigned int kLineBuffer = 128; // On Readln, look for line-breaks in chunks of 128 bytes
45} // anonymous namespace
46
47size_t ROOT::Internal::RRawFile::RBlockBuffer::CopyTo(void *buffer, size_t nbytes, std::uint64_t offset)
48{
50 return 0;
51
52 size_t copiedBytes = 0;
53 std::uint64_t offsetInBuffer = offset - fBufferOffset;
54 if (offsetInBuffer < static_cast<std::uint64_t>(fBufferSize)) {
55 size_t bytesInBuffer = std::min(nbytes, static_cast<size_t>(fBufferSize - offsetInBuffer));
58 }
59 return copiedBytes;
60}
61
62ROOT::Internal::RRawFile::RRawFile(std::string_view url, ROptions options) : fUrl(url), fOptions(options) {}
63
64std::unique_ptr<ROOT::Internal::RRawFile>
66{
67 std::string transport = GetTransport(url);
68 if (transport == "file") {
69#ifdef _WIN32
70 return std::unique_ptr<RRawFile>(new RRawFileWin(url, options));
71#else
72 // We're assuming the input url is null-terminated in the next call
73 if (auto xurl = ROOT::Internal::GetEOSRedirectedXRootURL(url))
74 return Create(*xurl, options);
75 return std::unique_ptr<RRawFile>(new RRawFileUnix(url, options));
76#endif
77 }
78 if (transport == "http" || transport == "https" || transport == "root" || transport == "roots") {
79 std::string plgclass = transport.compare(0, 4, "http") == 0 ? "RRawFileDavix" : "RRawFileNetXNG";
80 if (TPluginHandler *h =
81 gROOT->GetPluginManager()->FindHandler("ROOT::Internal::RRawFile", std::string(url).c_str())) {
82 if (h->LoadPlugin() == 0) {
83 return std::unique_ptr<RRawFile>(reinterpret_cast<RRawFile *>(h->ExecPlugin(2, &url, &options)));
84 }
85 throw std::runtime_error("Cannot load plugin handler for " + plgclass);
86 }
87 throw std::runtime_error("Cannot find plugin handler for " + plgclass);
88 }
89 throw std::runtime_error("Unsupported transport protocol: " + transport);
90}
91
93{
94 if (fIsOpen)
95 return;
96
97 OpenImpl();
98 fIsOpen = true;
99 SetDiscourageReadAheadImpl(!fIsBuffering);
100}
101
103{
104 for (unsigned i = 0; i < nReq; ++i) {
105 ioVec[i].fOutBytes = ReadAt(ioVec[i].fBuffer, ioVec[i].fSize, ioVec[i].fOffset);
106 }
107}
108
109std::string ROOT::Internal::RRawFile::GetLocation(std::string_view url)
110{
111 auto idx = url.find(kTransportSeparator);
112 if (idx == std::string_view::npos)
113 return std::string(url);
114 return std::string(url.substr(idx + strlen(kTransportSeparator)));
115}
116
118{
119 if (fFileSize != kUnknownFileSize)
120 return fFileSize;
121
122 EnsureOpen();
123 fFileSize = GetSizeImpl();
124 return fFileSize;
125}
126
128 return fUrl;
129}
130
131std::string ROOT::Internal::RRawFile::GetTransport(std::string_view url)
132{
133 auto idx = url.find(kTransportSeparator);
134 if (idx == std::string_view::npos)
135 return "file";
136 std::string transport(url.substr(0, idx));
137 std::transform(transport.begin(), transport.end(), transport.begin(), ::tolower);
138 return transport;
139}
140
141size_t ROOT::Internal::RRawFile::Read(void *buffer, size_t nbytes)
142{
143 size_t res = ReadAt(buffer, nbytes, fFilePos);
144 fFilePos += res;
145 return res;
146}
147
148size_t ROOT::Internal::RRawFile::ReadAt(void *buffer, size_t nbytes, std::uint64_t offset)
149{
150 EnsureOpen();
151
152 // Early return for empty requests
153 if (nbytes == 0)
154 return 0;
155
156 // "Large" reads are served directly, bypassing the cache; since nbytes > 0, fBlockSize == 0 is also handled here
157 if (!fIsBuffering || nbytes > static_cast<unsigned int>(fOptions.fBlockSize))
158 return ReadAtImpl(buffer, nbytes, offset);
159
160 if (!fBufferSpace) {
161 fBufferSpace.reset(new unsigned char[kNumBlockBuffers * fOptions.fBlockSize]);
162 for (unsigned int i = 0; i < kNumBlockBuffers; ++i) {
163 fBlockBuffers[i].fBuffer = fBufferSpace.get() + i * fOptions.fBlockSize;
164 fBlockBuffers[i].fBufferSize = 0;
165 }
166 }
167
168 size_t totalBytes = 0;
169 size_t copiedBytes = 0;
170 /// Try to serve as many bytes as possible from the block buffers
171 for (unsigned int idx = fBlockBufferIdx; idx < fBlockBufferIdx + kNumBlockBuffers; ++idx) {
172 copiedBytes = fBlockBuffers[idx % kNumBlockBuffers].CopyTo(buffer, nbytes, offset);
173 buffer = reinterpret_cast<unsigned char *>(buffer) + copiedBytes;
177 if (copiedBytes > 0)
178 fBlockBufferIdx = idx;
179 if (nbytes == 0)
180 return totalBytes;
181 }
182 fBlockBufferIdx++;
183
184 /// The request was not fully satisfied and fBlockBufferIdx now points to the previous shadow buffer
185
186 /// The remaining bytes populate the newly promoted main buffer
187 RBlockBuffer *thisBuffer = &fBlockBuffers[fBlockBufferIdx % kNumBlockBuffers];
188 size_t res = ReadAtImpl(thisBuffer->fBuffer, fOptions.fBlockSize, offset);
189 thisBuffer->fBufferOffset = offset;
190 thisBuffer->fBufferSize = res;
191 size_t remainingBytes = std::min(res, nbytes);
192 memcpy(buffer, thisBuffer->fBuffer, remainingBytes);
194 return totalBytes;
195}
196
198{
199 EnsureOpen();
200 ReadVImpl(ioVec, nReq);
201}
202
204{
205 fIsBuffering = value;
206 if (!fIsBuffering)
207 fBufferSpace.reset();
208 if (fIsOpen)
209 SetDiscourageReadAheadImpl(!fIsBuffering);
210}
211
213{
214 if (fOptions.fLineBreak == ELineBreaks::kAuto) {
215 // Auto-detect line breaks according to the break discovered in the first line
216 fOptions.fLineBreak = ELineBreaks::kUnix;
217 bool res = Readln(line);
218 if ((line.length() > 0) && (*line.rbegin() == '\r')) {
219 fOptions.fLineBreak = ELineBreaks::kWindows;
220 line.resize(line.length() - 1);
221 }
222 return res;
223 }
224
225 line.clear();
226 char buffer[kLineBuffer];
227 size_t nbytes;
228 do {
229 nbytes = Read(buffer, sizeof(buffer));
230 std::string_view bufferView(buffer, nbytes);
231 auto idx = bufferView.find(kLineBreakTokens[static_cast<int>(fOptions.fLineBreak)]);
232 if (idx != std::string_view::npos) {
233 // Line break found, return the string and skip the linebreak itself
234 line.append(buffer, idx);
235 fFilePos -= nbytes - idx;
236 fFilePos += kLineBreakTokenSizes[static_cast<int>(fOptions.fLineBreak)];
237 return true;
238 }
239 line.append(buffer, nbytes);
240 } while (nbytes > 0);
241
242 return !line.empty();
243}
244
246{
247 fFilePos = offset;
248}
fBuffer
dim_t fSize
#define h(i)
Definition RSha256.hxx:106
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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 value
#define gROOT
Definition TROOT.h:417
The RRawFileUnix class uses POSIX calls to read from a mounted file system.
The RRawFileWin class uses portable C I/O calls to read from a drive.
The RRawFile provides read-only access to local and remote files.
Definition RRawFile.hxx:43
static std::string GetLocation(std::string_view url)
Returns only the file location, e.g. "server/file" for http://server/file.
Definition RRawFile.cxx:109
RRawFile(std::string_view url, ROptions options)
Definition RRawFile.cxx:62
virtual void ReadVImpl(RIOVec *ioVec, unsigned int nReq)
By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX impleme...
Definition RRawFile.cxx:102
static std::string GetTransport(std::string_view url)
Returns only the transport protocol in lower case, e.g. "http" for HTTP://server/file.
Definition RRawFile.cxx:131
std::uint64_t GetSize()
Returns the size of the file.
Definition RRawFile.cxx:117
static std::unique_ptr< RRawFile > Create(std::string_view url, ROptions options=ROptions())
Factory method that returns a suitable concrete implementation according to the transport in the url.
Definition RRawFile.cxx:65
void Seek(std::uint64_t offset)
Change the cursor fFilePos.
Definition RRawFile.cxx:245
size_t ReadAt(void *buffer, size_t nbytes, std::uint64_t offset)
Buffered read from a random position.
Definition RRawFile.cxx:148
bool Readln(std::string &line)
Read the next line starting from the current value of fFilePos. Returns false if the end of the file ...
Definition RRawFile.cxx:212
void EnsureOpen()
Open the file if not already open. Otherwise noop.
Definition RRawFile.cxx:92
void ReadV(RIOVec *ioVec, unsigned int nReq)
Opens the file if necessary and calls ReadVImpl.
Definition RRawFile.cxx:197
size_t Read(void *buffer, size_t nbytes)
Read from fFilePos offset. Returns the actual number of bytes read.
Definition RRawFile.cxx:141
void SetBuffering(bool value)
Turn on/off buffered reads; if off, all scalar read requests go directly to the implementation.
Definition RRawFile.cxx:203
std::string GetUrl() const
Returns the url of the file.
Definition RRawFile.cxx:127
const_iterator begin() const
const_iterator end() const
TLine * line
std::uint64_t fBufferOffset
Where in the open file does fBuffer start.
Definition RRawFile.hxx:95
unsigned char * fBuffer
Points into the I/O buffer with data from the file, not owned.
Definition RRawFile.hxx:99
size_t CopyTo(void *buffer, size_t nbytes, std::uint64_t offset)
Tries to copy up to nbytes starting at offset from fBuffer into buffer. Returns number of bytes copie...
Definition RRawFile.cxx:47
size_t fBufferSize
The number of currently buffered bytes in fBuffer.
Definition RRawFile.hxx:97
Used for vector reads from multiple offsets into multiple buffers.
Definition RRawFile.hxx:61
On construction, an ROptions parameter can customize the RRawFile behavior.
Definition RRawFile.hxx:49