#ifndef LCB_ROPE_H
#define LCB_ROPE_H
#include <libcouchbase/sysdefs.h>
#include <libcouchbase/visibility.h>
#include <netbuf/netbuf-defs.h>
#include <stdio.h>
#include "list.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct rdb_ALLOCATOR *rdb_pALLOCATOR;
typedef struct rdb_ROPESEG *rdb_pROPESEG;
typedef struct rdb_ROPEBUF *rdb_pROPEBUF;
typedef struct rdb_ROPEBUF {
lcb_list_t segments;
unsigned nused;
rdb_pALLOCATOR allocator;
} rdb_ROPEBUF;
struct rdb_ROPESEG;
enum rdb_SEGFLAGS {
RDB_ROPESEG_F_USER = 0x01,
RDB_ROPESEG_F_LIB = 0x02
};
enum rdb_ALLOCID {
RDB_ALLOCATOR_BIGALLOC = 1,
RDB_ALLOCATOR_CHUNKED,
RDB_ALLOCATOR_LIBCALLOC,
RDB_ALLOCATOR_MAX
};
typedef struct rdb_ROPESEG {
lcb_list_t llnode;
char *root;
unsigned char shflags;
unsigned char allocid;
unsigned nalloc;
unsigned nused;
unsigned start;
unsigned refcnt;
rdb_pALLOCATOR allocator;
} rdb_ROPESEG;
typedef struct {
rdb_ROPEBUF recvd;
rdb_ROPEBUF avail;
unsigned rdsize;
} rdb_IOROPE;
typedef void (*rdb_buf_reserve_fn)
(rdb_pALLOCATOR allocator, rdb_ROPEBUF *buf, unsigned total_capacity);
typedef rdb_ROPESEG *(*rdb_seg_alloc_fn)
(rdb_pALLOCATOR allocator, unsigned capacity);
typedef rdb_ROPESEG *(*rdb_seg_realloc_fn)
(rdb_pALLOCATOR allocator, rdb_ROPESEG *orig, unsigned capacity);
typedef void (*rdb_seg_free_fn)(rdb_pALLOCATOR allocator, rdb_ROPESEG *seg);
typedef struct rdb_ALLOCATOR {
rdb_buf_reserve_fn r_reserve;
rdb_seg_alloc_fn s_alloc;
rdb_seg_realloc_fn s_realloc;
rdb_seg_free_fn s_release;
void (*a_release)(rdb_pALLOCATOR);
void (*dump)(rdb_pALLOCATOR,FILE*);
} rdb_ALLOCATOR;
void
rdb_init(rdb_IOROPE *rope, rdb_ALLOCATOR *allocator);
void
rdb_challoc(rdb_IOROPE *rope, rdb_ALLOCATOR *allocator);
void
rdb_cleanup(rdb_IOROPE *ior);
unsigned
rdb_rdstart(rdb_IOROPE *ior, nb_IOV *iov, unsigned niov);
void
rdb_rdend(rdb_IOROPE *ior, unsigned nr);
void
rdb_consumed(rdb_IOROPE *ior, unsigned nr);
void
rdb_consolidate(rdb_IOROPE *ior, unsigned n);
char *
rdb_get_consolidated(rdb_IOROPE *ior, unsigned n);
void
rdb_copyread(rdb_IOROPE *ior, void *buf, unsigned n);
#define rdb_refread(ior) \
((LCB_LIST_ITEM(ior->recvd.segments.next, rdb_ROPESEG, llnode))->root + \
(LCB_LIST_ITEM(ior->recvd.segments.next, rdb_ROPESEG, llnode))->start)
int
rdb_refread_ex(rdb_IOROPE *ior, nb_IOV *iov, rdb_ROPESEG **segs,
unsigned nelem, unsigned ndata);
unsigned
rdb_get_contigsize(rdb_IOROPE *ior);
void
rdb_seg_ref(rdb_ROPESEG *seg);
void
rdb_seg_unref(rdb_ROPESEG *seg);
#define rdb_seg_recyclable(seg) (((seg)->shflags & RDB_ROPESEG_F_USER) == 0)
#define rdb_get_first_segment(ior) RDB_SEG_FIRST(&(ior)->recvd)
#define RDB_SEG_SPACE(seg) (seg)->nalloc - ((seg)->nused + (seg)->start)
#define RDB_SEG_RBUF(seg) (seg)->root + (seg)->start
#define RDB_SEG_WBUF(seg) (seg)->root + (seg)->start + (seg)->nused
#define RDB_SEG_LAST(rope) \
(LCB_LIST_TAIL(&(rope)->segments)) \
? LCB_LIST_ITEM(LCB_LIST_TAIL(&(rope)->segments), rdb_ROPESEG, llnode) \
: NULL
#define RDB_SEG_FIRST(rope) \
(LCB_LIST_HEAD(&(rope)->segments)) \
? LCB_LIST_ITEM(LCB_LIST_HEAD(&(rope)->segments), rdb_ROPESEG, llnode) \
: NULL
#define rdb_get_nused(ior) (ior)->recvd.nused
void
rdb_copywrite(rdb_IOROPE *ior, void *buf, unsigned nbuf);
LCB_INTERNAL_API
rdb_ALLOCATOR *
rdb_bigalloc_new(void);
LCB_INTERNAL_API
rdb_ALLOCATOR *
rdb_chunkalloc_new(unsigned chunksize);
LCB_INTERNAL_API
rdb_ALLOCATOR *
rdb_libcalloc_new(void);
void
rdb_dump(const rdb_IOROPE *ior, FILE *fp);
#ifdef __cplusplus
}
#endif
#endif