]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/buffer: adding pread_file method
authorYuan Zhou <yuan.zhou@intel.com>
Wed, 16 Jan 2019 15:38:26 +0000 (23:38 +0800)
committerYuan Zhou <yuan.zhou@intel.com>
Thu, 21 Mar 2019 16:16:27 +0000 (00:16 +0800)
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 <yuan.zhou@intel.com>
src/common/buffer.cc
src/include/buffer.h
src/tools/immutable_object_cache/ObjectCacheFile.cc

index a3c6201d208a5dc868bc161f27dd61f93b9824c7..8633ca407b5edb7ccc1be140f2b100a28b69782b 100644 (file)
@@ -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)
 {
index e5a581ca5b0b58fb52fb6829c3fdf455cb9245d4..08ad06aff2deb82bf4f7de9cc83a4985502ac4b7 100644 (file)
@@ -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);
index 47c9da68ba8b82592273677bec04ce789eee2ca8..a85d7f5f13c798120bb35186896af6f2a93eb34d 100644 (file)
@@ -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();
 }