diff --git a/io/io/inc/ROOT/RRawFile.hxx b/io/io/inc/ROOT/RRawFile.hxx index f7f35b893fc346c47e7101b9647237d7e8315bcf..1cf7849c9c8a6013cc8eb05ca02f05c3650176af 100644 --- a/io/io/inc/ROOT/RRawFile.hxx +++ b/io/io/inc/ROOT/RRawFile.hxx @@ -133,6 +133,9 @@ protected: /// Derived classes with mmap support must be able to unmap the memory area handed out by Map() virtual void DoUnmap(void *region, size_t nbytes); + /// By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX implementations + virtual void DoReadV(RIOVec *ioVec, unsigned int nReq); + public: RRawFile(std::string_view url, ROptions options); RRawFile(const RRawFile &) = delete; @@ -161,8 +164,8 @@ public: /// Returns the size of the file std::uint64_t GetSize(); - /// By default implemented as a loop of ReadAt calls but can be overwritten, e.g. XRootD or DAVIX implementations - virtual void ReadV(RIOVec *ioVec, unsigned int nReq); + /// Opens the file if necessary and calls DoReadV + void ReadV(RIOVec *ioVec, unsigned int nReq); /// Memory mapping according to POSIX standard; in particular, new mappings of the same range replace older ones. /// Mappings need to be aligned at page boundaries, therefore the real offset can be smaller than the desired value. diff --git a/io/io/src/RRawFile.cxx b/io/io/src/RRawFile.cxx index 375aecf88867b1b88447dc467ed3e01f06502f33..66f335f00e740fe7717f9f9bffb7e594aa6fbb37 100644 --- a/io/io/src/RRawFile.cxx +++ b/io/io/src/RRawFile.cxx @@ -98,6 +98,13 @@ void *ROOT::Experimental::Detail::RRawFile::DoMap(size_t /* nbytes */, std::uint throw std::runtime_error("Memory mapping unsupported"); } +void ROOT::Experimental::Detail::RRawFile::DoReadV(RIOVec *ioVec, unsigned int nReq) +{ + for (unsigned i = 0; i < nReq; ++i) { + ioVec[i].fOutBytes = ReadAt(ioVec[i].fBuffer, ioVec[i].fSize, ioVec[i].fOffset); + } +} + void ROOT::Experimental::Detail::RRawFile::DoUnmap(void * /* region */, size_t /* nbytes */) { throw std::runtime_error("Memory mapping unsupported"); @@ -195,9 +202,10 @@ size_t ROOT::Experimental::Detail::RRawFile::ReadAt(void *buffer, size_t nbytes, void ROOT::Experimental::Detail::RRawFile::ReadV(RIOVec *ioVec, unsigned int nReq) { - for (unsigned i = 0; i < nReq; ++i) { - ioVec[i].fOutBytes = ReadAt(ioVec[i].fBuffer, ioVec[i].fSize, ioVec[i].fOffset); - } + if (!fIsOpen) + DoOpen(); + fIsOpen = true; + DoReadV(ioVec, nReq); } bool ROOT::Experimental::Detail::RRawFile::Readln(std::string &line) diff --git a/net/davix/inc/ROOT/RRawFileDavix.hxx b/net/davix/inc/ROOT/RRawFileDavix.hxx index c1d42adcd7c2ab1225156f757600e7b6787b3fbd..d413c851d19dc58e993971f9cdaf2b0d923cceb7 100644 --- a/net/davix/inc/ROOT/RRawFileDavix.hxx +++ b/net/davix/inc/ROOT/RRawFileDavix.hxx @@ -41,6 +41,7 @@ private: protected: void DoOpen() final; size_t DoReadAt(void *buffer, size_t nbytes, std::uint64_t offset) final; + void DoReadV(RIOVec *ioVec, unsigned int nReq) final; std::uint64_t DoGetSize() final; public: diff --git a/net/davix/src/RRawFileDavix.cxx b/net/davix/src/RRawFileDavix.cxx index 677a0b531cead15194e4586312182c4de37ed448..81e20e7985083630e0c2cb16435d2345eea6b040 100644 --- a/net/davix/src/RRawFileDavix.cxx +++ b/net/davix/src/RRawFileDavix.cxx @@ -88,3 +88,25 @@ size_t ROOT::Experimental::Detail::RRawFileDavix::DoReadAt(void *buffer, size_t } return static_cast<size_t>(retval); } + +void ROOT::Experimental::Detail::RRawFileDavix::DoReadV(RIOVec *ioVec, unsigned int nReq) +{ + Davix::DavixError *davixErr = NULL; + Davix::DavIOVecInput in[nReq]; + Davix::DavIOVecOuput out[nReq]; + + for (unsigned int i = 0; i < nReq; ++i) { + in[i].diov_buffer = ioVec[i].fBuffer; + in[i].diov_offset = ioVec[i].fOffset; + in[i].diov_size = ioVec[i].fSize; + } + + auto ret = fFileDes->pos.preadVec(fFileDes->fd, in, out, nReq, &davixErr); + if (ret < 0) { + throw std::runtime_error("Cannot do vector read from '" + fUrl + "', error: " + davixErr->getErrMsg()); + } + + for (unsigned int i = 0; i < nReq; ++i) { + ioVec[i].fOutBytes = out[i].diov_size; + } +} diff --git a/net/davix/test/RRawFileDavix.cxx b/net/davix/test/RRawFileDavix.cxx index 2b84cd2c72216cc18183a2b58980047514fdde67..ec376e7a18534a37fcb6a88e8cbe801280da187d 100644 --- a/net/davix/test/RRawFileDavix.cxx +++ b/net/davix/test/RRawFileDavix.cxx @@ -38,3 +38,27 @@ TEST(RRawFileDavix, Eof) EXPECT_EQ(3u, nbytes); EXPECT_STREQ("ld\n", tail); } + + +TEST(RRawFileDavix, ReadV) +{ + RRawFile::ROptions options; + options.fBlockSize = 0; + std::unique_ptr<RRawFileDavix> f(new RRawFileDavix("http://root.cern.ch/files/davix.test", options)); + + char buffer[2]; + buffer[0] = buffer[1] = 0; + RRawFile::RIOVec iovec[2]; + iovec[0].fBuffer = &buffer[0]; + iovec[0].fOffset = 0; + iovec[0].fSize = 1; + iovec[1].fBuffer = &buffer[1]; + iovec[1].fOffset = 11; + iovec[1].fSize = 1; + f->ReadV(iovec, 2); + + EXPECT_EQ(1U, iovec[0].fOutBytes); + EXPECT_EQ(1U, iovec[1].fOutBytes); + EXPECT_EQ('H', buffer[0]); + EXPECT_EQ('d', buffer[1]); +}