]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
encoding: use iterator to copy_in encoded length
authorSage Weil <sage.weil@dreamhost.com>
Fri, 6 Apr 2012 16:33:43 +0000 (09:33 -0700)
committerSage Weil <sage.weil@dreamhost.com>
Fri, 6 Apr 2012 17:00:16 +0000 (10:00 -0700)
This gives us a pointer to the position into the list where the final
length value will be copied.  Previously we used bl.copy_in(), which takes
a byte offset and needs iterator over the bufferlist to seek to the
correct position, resulting in O(n^2) encoding time for large structures.

Fixes: #2161
Reported-by: Jim Schutt <jaschut@sandia.gov>
Diagnosed-by: Ake van der Meer <petrabbit@xs4all.nl>
Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/include/encoding.h

index fa1cebeec48732e08a4f1be0b7b265bad27eec4f..e9bf1e9260113f8d125ce7ec6a5cac8e8b25e0eb 100644 (file)
@@ -656,7 +656,7 @@ inline void decode(std::deque<T>& ls, bufferlist::iterator& p)
   ::encode(struct_v, bl);                                   \
   ::encode(struct_compat, bl);                              \
   __le32 struct_len = 0;                                    \
-  unsigned struct_len_pos = bl.length();                    \
+  buffer::list::iterator struct_len_it = bl.end();          \
   ::encode(struct_len, bl);                                 \
   do {
 
@@ -667,8 +667,8 @@ inline void decode(std::deque<T>& ls, bufferlist::iterator& p)
  */
 #define ENCODE_FINISH(bl)                                              \
   } while (false);                                                     \
-  struct_len = bl.length() - struct_len_pos - sizeof(struct_len);      \
-  bl.copy_in(struct_len_pos, 4, (char *)&struct_len);
+  struct_len = bl.length() - struct_len_it.get_off() - sizeof(struct_len); \
+  struct_len_it.copy_in(4, (char *)&struct_len);
 
 #define DECODE_ERR_VERSION(func, v)                    \
   "" #func " unknown encoding version > " #v