Project
Loading...
Searching...
No Matches
LocalByteSource.cxx
Go to the documentation of this file.
1// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include "LocalByteSource.h"
13#include "AODNative/Errors.h"
14#include <atomic>
15#include <cerrno>
16#include <cstring>
17#include <fcntl.h>
18#include <sys/mman.h>
19#include <sys/stat.h>
20#include <unistd.h>
21
22namespace o2::aod::native
23{
24
25namespace
26{
27size_t pageSize()
28{
29 static size_t size = sysconf(_SC_PAGESIZE);
30 return size;
31}
32} // namespace
33
34LocalByteSource::LocalByteSource(std::string path, Options const& options)
35 : mPath(std::move(path))
36{
37 mFd = ::open(mPath.c_str(), O_RDONLY | O_CLOEXEC);
38 if (mFd < 0) {
39 throw IoError(mPath, std::strerror(errno));
40 }
41 struct stat st;
42 if (fstat(mFd, &st) != 0) {
43 auto err = errno;
44 ::close(mFd);
45 throw IoError(mPath, std::strerror(err));
46 }
47 mSize = st.st_size;
48 if (options.localIO == Options::LocalIO::MMap && sizeof(void*) == 8 && mSize > 0) {
49 void* p = mmap(nullptr, mSize, PROT_READ, MAP_PRIVATE, mFd, 0);
50 if (p != MAP_FAILED) {
51 mMap = (uint8_t const*)p;
52 }
53 }
54}
55
57{
58 if (mMap) {
59 munmap((void*)mMap, mSize);
60 }
61 ::close(mFd);
62}
63
64void LocalByteSource::checkRange(uint64_t off, size_t len) const
65{
66 if (off > mSize || len > mSize - off) {
67 throw CorruptData(mPath, off, "read of " + std::to_string(len) + " bytes past the end of a " + std::to_string(mSize) + " byte file");
68 }
69}
70
71void LocalByteSource::readInto(uint64_t off, size_t len, void* dst)
72{
73 checkRange(off, len);
74 if (len == 0) {
75 return;
76 }
77 mReadCalls.fetch_add(1, std::memory_order_relaxed);
78 mBytesRead.fetch_add(len, std::memory_order_relaxed);
79 if (mMap) {
80 std::memcpy(dst, mMap + off, len);
81 return;
82 }
83 auto* out = (uint8_t*)dst;
84 while (len > 0) {
85 auto n = ::pread(mFd, out, len, off);
86 if (n < 0 && errno == EINTR) {
87 continue;
88 }
89 if (n <= 0) {
90 throw IoError(mPath, n == 0 ? "unexpected end of file" : std::strerror(errno));
91 }
92 out += n;
93 off += n;
94 len -= n;
95 }
96}
97
98void LocalByteSource::readvInto(std::span<ReadRequest> requests)
99{
100 for (auto& r : requests) {
101 readInto(r.offset, r.length, r.dst);
102 }
103}
104
105std::span<const uint8_t> LocalByteSource::tryMap(uint64_t off, size_t len)
106{
107 if (!mMap) {
108 return {};
109 }
110 checkRange(off, len);
111 // Mapped bytes are accounted as read, so that monitoring is the same for both modes.
112 mReadCalls.fetch_add(1, std::memory_order_relaxed);
113 mBytesRead.fetch_add(len, std::memory_order_relaxed);
114 return {mMap + off, len};
115}
116
117void LocalByteSource::advise(uint64_t off, size_t len, int advice)
118{
119 if (!mMap || off >= mSize) {
120 return;
121 }
122 len = std::min<uint64_t>(len, mSize - off);
123 auto start = off & ~(uint64_t)(pageSize() - 1);
124 madvise((void*)(mMap + start), len + (off - start), advice);
125}
126
127void LocalByteSource::willNeed(uint64_t off, size_t len) { advise(off, len, MADV_WILLNEED); }
128void LocalByteSource::dontNeed(uint64_t off, size_t len) { advise(off, len, MADV_DONTNEED); }
129
130} // namespace o2::aod::native
benchmark::State & st
static std::unique_ptr< ByteSource > open(std::string url, const Options &)
void dontNeed(uint64_t off, size_t len) override
LocalByteSource(std::string path, Options const &options)
void willNeed(uint64_t off, size_t len) override
Hints that a range will be needed soon, or is no longer needed.
void readvInto(std::span< ReadRequest > requests) override
std::span< const uint8_t > tryMap(uint64_t off, size_t len) override
A view of the bytes without copying them, if the backend can provide it.
void readInto(uint64_t off, size_t len, void *dst) override
Throws IoError, or CorruptData when the range is past the end of the file.
GLdouble n
Definition glcorearb.h:1982
GLsizeiptr size
Definition glcorearb.h:659
GLenum GLenum dst
Definition glcorearb.h:1767
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLboolean r
Definition glcorearb.h:1233
GLuint start
Definition glcorearb.h:469
GLenum GLenum GLsizei len
Definition glcorearb.h:4232
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
Failure of the underlying transport.
Definition Errors.h:69