From: Yuan Zhou Date: Wed, 16 Jan 2019 15:38:26 +0000 (+0800) Subject: common/buffer: adding pread_file method X-Git-Tag: v15.0.0~136^2~42 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=952116012fa4c75e4352cb96ea31134c581f6171;p=ceph.git common/buffer: adding pread_file method pread_file allows to read length of contents at a given offset using pread_file instead of read_file to reduce extra reads in ObjectCacheFile Signed-off-by: Yuan Zhou --- diff --git a/src/common/buffer.cc b/src/common/buffer.cc index a3c6201d208a..8633ca407b5e 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -1781,7 +1781,59 @@ void buffer::list::decode_base64(buffer::list& e) push_back(std::move(bp)); } - +int buffer::list::pread_file(const char *fn, uint64_t off, uint64_t len, std::string *error) +{ + int fd = TEMP_FAILURE_RETRY(::open(fn, O_RDONLY|O_CLOEXEC)); + if (fd < 0) { + int err = errno; + std::ostringstream oss; + oss << "can't open " << fn << ": " << cpp_strerror(err); + *error = oss.str(); + return -err; + } + + struct stat st; + memset(&st, 0, sizeof(st)); + if (::fstat(fd, &st) < 0) { + int err = errno; + std::ostringstream oss; + oss << "bufferlist::read_file(" << fn << "): stat error: " + << cpp_strerror(err); + *error = oss.str(); + VOID_TEMP_FAILURE_RETRY(::close(fd)); + return -err; + } + + if (off > st.st_size) { + std::ostringstream oss; + oss << "bufferlist::read_file(" << fn << "): read error: size < offset"; + VOID_TEMP_FAILURE_RETRY(::close(fd)); + return -1; + } + + if (len > st.st_size - off) { + len = st.st_size - off; + } + lseek(fd, off, SEEK_SET); + ssize_t ret = safe_read(fd, (void*)this->c_str(), len); + if (ret < 0) { + std::ostringstream oss; + oss << "bufferlist::read_file(" << fn << "): read error:" + << cpp_strerror(ret); + *error = oss.str(); + VOID_TEMP_FAILURE_RETRY(::close(fd)); + return ret; + } else if (ret != len) { + // Premature EOF. + // Perhaps the file changed between stat() and read()? + std::ostringstream oss; + oss << "bufferlist::read_file(" << fn << "): warning: got premature EOF."; + *error = oss.str(); + // not actually an error, but weird + } + VOID_TEMP_FAILURE_RETRY(::close(fd)); + return 0; +} int buffer::list::read_file(const char *fn, std::string *error) { diff --git a/src/include/buffer.h b/src/include/buffer.h index e5a581ca5b0b..08ad06aff2de 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -1216,6 +1216,7 @@ inline namespace v14_2_0 { void write_stream(std::ostream &out) const; void hexdump(std::ostream &out, bool trailing_newline = true) const; + int pread_file(const char *fn, uint64_t off, uint64_t len, std::string *error); int read_file(const char *fn, std::string *error); ssize_t read_fd(int fd, size_t len); int write_file(const char *fn, int mode=0644); diff --git a/src/tools/immutable_object_cache/ObjectCacheFile.cc b/src/tools/immutable_object_cache/ObjectCacheFile.cc index 47c9da68ba8b..a85d7f5f13c7 100644 --- a/src/tools/immutable_object_cache/ObjectCacheFile.cc +++ b/src/tools/immutable_object_cache/ObjectCacheFile.cc @@ -56,26 +56,14 @@ int ObjectCacheFile::read_object_from_file(ceph::bufferlist* read_buf, uint64_t ldout(cct, 20) << "offset:" << object_off << ", length:" << object_len << dendl; - bufferlist temp_bl; std::string error_str; - // TODO : current implements will drop sharely performance. - int ret = temp_bl.read_file(m_name.c_str(), &error_str); + int ret = read_buf->pread_file(m_name.c_str(), object_off, object_len, &error_str); if (ret < 0) { lderr(cct)<<"read file fail:" << error_str << dendl; return -1; } - if(object_off >= temp_bl.length()) { - return 0; - } - - if((temp_bl.length() - object_off) < object_len) { - object_len = temp_bl.length() - object_off; - } - - read_buf->substr_of(temp_bl, object_off, object_len); - return read_buf->length(); }