]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
buffer: add page_aligned_appender
authorSage Weil <sage@redhat.com>
Wed, 21 Sep 2016 18:14:15 +0000 (14:14 -0400)
committerSage Weil <sage@redhat.com>
Sun, 16 Oct 2016 14:32:51 +0000 (10:32 -0400)
Signed-off-by: Sage Weil <sage@redhat.com>
src/include/buffer.h

index 48df6cffb70fc29e6f89775388eca0e1baf1a549..3264b54855398708611eeed9d802ceebb17f96ed 100644 (file)
@@ -552,6 +552,65 @@ namespace buffer CEPH_BUFFER_API {
       return contiguous_appender(this, len);
     }
 
+    class page_aligned_appender {
+      bufferlist *pbl;
+      size_t offset;
+      unsigned min_alloc;
+      ptr buffer;
+      char *pos, *end;
+
+      page_aligned_appender(list *l, unsigned min_pages)
+       : pbl(l),
+         min_alloc(min_pages * CEPH_PAGE_SIZE),
+         pos(nullptr), end(nullptr) {}
+
+      friend class list;
+
+    public:
+      ~page_aligned_appender() {
+       flush();
+      }
+
+      void flush() {
+       if (pos && pos != buffer.c_str()) {
+         size_t len = pos - buffer.c_str();
+         pbl->append(buffer, 0, len);
+         buffer.set_length(buffer.length() - len);
+         buffer.set_offset(buffer.offset() + len);
+       }
+      }
+
+      void append(const char *buf, size_t len) {
+       while (len > 0) {
+         if (!pos) {
+           size_t alloc = (len + CEPH_PAGE_SIZE - 1) & CEPH_PAGE_MASK;
+           if (alloc < min_alloc) {
+             alloc = min_alloc;
+           }
+           buffer = create_page_aligned(alloc);
+           pos = buffer.c_str();
+           end = buffer.end_c_str();
+         }
+         size_t l = len;
+         if (l > (size_t)(end - pos)) {
+           l = end - pos;
+         }
+         memcpy(pos, buf, l);
+         pos += l;
+         buf += l;
+         len -= l;
+         if (pos == end) {
+           pbl->append(buffer, 0, buffer.length());
+           pos = end = nullptr;
+         }
+       }
+      }
+    };
+
+    page_aligned_appender get_page_aligned_appender(unsigned min_pages=1) {
+      return page_aligned_appender(this, min_pages);
+    }
+
   private:
     mutable iterator last_p;
     int zero_copy_to_fd(int fd) const;