Mercurial > hg > orthanc-databases
diff Framework/PostgreSQL/PostgreSQLLargeObject.cpp @ 248:7a4f9bcb0bc2
PostgreSQL: Support of range reads from the storage area
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 14 Apr 2021 09:46:44 +0200 |
parents | 3236894320d6 |
children | 16aac0287485 |
line wrap: on
line diff
--- a/Framework/PostgreSQL/PostgreSQLLargeObject.cpp Wed Apr 14 09:18:20 2021 +0200 +++ b/Framework/PostgreSQL/PostgreSQLLargeObject.cpp Wed Apr 14 09:46:44 2021 +0200 @@ -80,16 +80,6 @@ PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLDatabase& database, - const void* data, - size_t size) : - database_(database) - { - Create(); - Write(data, size); - } - - - PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLDatabase& database, const std::string& s) : database_(database) { @@ -113,6 +103,24 @@ int fd_; size_t size_; + void ReadInternal(PGconn* pg, + std::string& target) + { + for (size_t position = 0; position < target.size(); ) + { + size_t remaining = target.size() - position; + + int nbytes = lo_read(pg, fd_, &target[position], remaining); + if (nbytes < 0) + { + LOG(ERROR) << "PostgreSQL: Unable to read the large object in the database"; + database_.ThrowException(false); + } + + position += static_cast<size_t>(nbytes); + } + } + public: Reader(PostgreSQLDatabase& database, const std::string& oid) : @@ -138,9 +146,6 @@ database.ThrowException(true); } size_ = static_cast<size_t>(size); - - // Go to the first byte of the object - lo_lseek(pg, fd_, 0, SEEK_SET); } ~Reader() @@ -153,60 +158,67 @@ return size_; } - void Read(char* target) + void ReadWhole(std::string& target) { - for (size_t position = 0; position < size_; ) + if (target.size() != size_) { - size_t remaining = size_ - position; + throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError); + } + + PGconn* pg = reinterpret_cast<PGconn*>(database_.pg_); + + // Go to the first byte of the object + lo_lseek(pg, fd_, 0, SEEK_SET); - int nbytes = lo_read(reinterpret_cast<PGconn*>(database_.pg_), fd_, target + position, remaining); - if (nbytes < 0) - { - LOG(ERROR) << "PostgreSQL: Unable to read the large object in the database"; - database_.ThrowException(false); - } + ReadInternal(pg, target); + } - position += static_cast<size_t>(nbytes); - } + void ReadRange(std::string& target, + uint64_t start) + { + PGconn* pg = reinterpret_cast<PGconn*>(database_.pg_); + + // Go to the first byte of the object + lo_lseek(pg, fd_, start, SEEK_SET); + + ReadInternal(pg, target); } }; - void PostgreSQLLargeObject::Read(std::string& target, - PostgreSQLDatabase& database, - const std::string& oid) + void PostgreSQLLargeObject::ReadWhole(std::string& target, + PostgreSQLDatabase& database, + const std::string& oid) { Reader reader(database, oid); target.resize(reader.GetSize()); if (target.size() > 0) { - reader.Read(&target[0]); + reader.ReadWhole(target); } } - void PostgreSQLLargeObject::Read(void*& target, - size_t& size, - PostgreSQLDatabase& database, - const std::string& oid) + void PostgreSQLLargeObject::ReadRange(std::string& target, + PostgreSQLDatabase& database, + const std::string& oid, + uint64_t start, + size_t length) { Reader reader(database, oid); - size = reader.GetSize(); - if (size == 0) - { - target = NULL; - } - else + if (start >= reader.GetSize() || + start + length > reader.GetSize()) { - target = malloc(size); - if (target == NULL) - { - throw Orthanc::OrthancException(Orthanc::ErrorCode_NotEnoughMemory); - } - - reader.Read(reinterpret_cast<char*>(target)); + throw Orthanc::OrthancException(Orthanc::ErrorCode_BadRange); + } + + target.resize(length); + + if (target.size() > 0) + { + reader.ReadRange(target, start); } }