X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fbuck2obj.c;h=c0ee98c66af9486f34338353dfc4e0fec629b9a9;hb=bc5bc0b52b57d424c64a382aeba9def6eb8de45d;hp=ef999f1228ee0c06d4d20c8628e5cc8d719252c4;hpb=9fde345a39cdf547bdedee4fc29d23d7d865cc8a;p=libucw.git diff --git a/lib/buck2obj.c b/lib/buck2obj.c index ef999f12..c0ee98c6 100644 --- a/lib/buck2obj.c +++ b/lib/buck2obj.c @@ -18,31 +18,25 @@ #include #include -#define MAX_HEADER_SIZE 1024 // extra space for the header not counted in MaxObjSize #define RET_ERR(num) ({ errno = num; return NULL; }) +#define GBUF_TYPE byte +#define GBUF_PREFIX(x) bb_##x +#include "lib/gbuf.h" + struct buck2obj_buf { - uns max_len, raw_len; - byte *raw; + bb_t bb; struct lizard_buffer *lizard; struct mempool *mp; }; -static void -buck2obj_alloc_internal(struct buck2obj_buf *buf, uns max_len) -{ - buf->max_len = max_len; - buf->raw_len = max_len * LIZARD_MAX_MULTIPLY + LIZARD_MAX_ADD + MAX_HEADER_SIZE; - buf->raw = xmalloc(buf->raw_len); -} - struct buck2obj_buf * -buck2obj_alloc(uns max_len, struct mempool *mp) +buck2obj_alloc(struct mempool *mp) { struct buck2obj_buf *buf = xmalloc(sizeof(struct buck2obj_buf)); - buck2obj_alloc_internal(buf, max_len); - buf->lizard = lizard_alloc(max_len); + bb_init(&buf->bb); + buf->lizard = lizard_alloc(); buf->mp = mp; return buf; } @@ -51,20 +45,14 @@ void buck2obj_free(struct buck2obj_buf *buf) { lizard_free(buf->lizard); - xfree(buf->raw); + bb_done(&buf->bb); xfree(buf); } void -buck2obj_realloc(struct buck2obj_buf *buf, uns max_len) +buck2obj_flush(struct buck2obj_buf *buf) { - if (max_len <= buf->max_len) - return; - if (max_len < 2*buf->max_len + 1) // to ensure amortized logarithmic complexity - max_len = 2*buf->max_len + 1; - xfree(buf->raw); - buck2obj_alloc_internal(buf, max_len); - lizard_realloc(buf->lizard, max_len); + mp_flush(buf->mp); } static inline byte * @@ -119,23 +107,29 @@ decode_attributes(byte *ptr, byte *end, struct odes *o, uns can_overwrite) } struct odes * -buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) +obj_read_bucket(struct buck2obj_buf *buf, uns buck_type, uns buck_len, struct fastbuf *body, uns *body_start) { - mp_flush(buf->mp); struct odes *o = obj_new(buf->mp); if (buck_type < BUCKET_TYPE_V33) - obj_read_multi(body, o); + { + if (!body_start) // header + body: ignore empty lines, read until EOF + { + obj_read_multi(body, o); + bgetc(body); + } + else // header only: end on EOF or the first empty line + { + sh_off_t start = btell(body); + obj_read(body, o); + *body_start = btell(body) - start; + } + } else { - /* Compute the length of the bucket. We cannot fetch this attribute - * directly due to remote indexing. */ - bseek(body, 0, SEEK_END); - sh_off_t buck_len = btell(body); - bsetpos(body, 0); - /* Read all the bucket into 1 buffer, 0-copy if possible. */ - int can_overwrite = bconfig(body, BCONFIG_CAN_OVERWRITE, 0); + int can_overwrite = bconfig(body, BCONFIG_CAN_OVERWRITE, -1); + /* FIXME: This could be cached in buck2obj_buf */ if (can_overwrite < 0) can_overwrite = 0; uns overwritten; @@ -146,10 +140,9 @@ buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) { /* Copy if the original buffer is too small. * If it is write-protected, copy it also if it is uncompressed. */ - if (buck_len > buf->raw_len) - buck2obj_realloc(buf, buck_len); - len = bread(body, buf->raw, buck_len); - ptr = buf->raw; + bb_grow(&buf->bb, buck_len); + len = bread(body, buf->bb.ptr, buck_len); + ptr = buf->bb.ptr; can_overwrite = 2; overwritten = 0; } @@ -157,21 +150,29 @@ buck2obj_convert(struct buck2obj_buf *buf, uns buck_type, struct fastbuf *body) overwritten = can_overwrite > 1; end = ptr + len; + byte *start = ptr; ptr = decode_attributes(ptr, end, o, can_overwrite);// header + if (body_start) + { + *body_start = ptr - start; + return o; + } if (buck_type == BUCKET_TYPE_V33) ; else if (buck_type == BUCKET_TYPE_V33_LIZARD) // decompression { len = GET_U32(ptr); ptr += 4; - int res = lizard_decompress_safe(ptr, buf->lizard, len); + int res; + byte *new_ptr; + res = lizard_decompress_safe(ptr, buf->lizard, len, &new_ptr); if (res != (int) len) { if (res >= 0) errno = EINVAL; return NULL; } - ptr = buf->lizard->ptr; + ptr = new_ptr; end = ptr + len; can_overwrite = 2; }