[Sheepdog] [RFC PATCH 09/11] trace: add a dynamic buffer
Liu Yuan
namei.unix at gmail.com
Tue Jan 17 13:00:00 CET 2012
From: Liu Yuan <tailai.ly at taobao.com>
Dbuffer is a dynamic buffer that can grow automatically.
Maybe per thread buffer is a better idea than global one. But global
one is simple to implement and use.
Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
include/util.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
lib/Makefile.am | 2 +-
lib/dbuffer.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
sheep/strbuf.h | 20 --------------------
4 files changed, 90 insertions(+), 21 deletions(-)
create mode 100644 lib/dbuffer.c
diff --git a/include/util.h b/include/util.h
index ff86a00..e56249f 100644
--- a/include/util.h
+++ b/include/util.h
@@ -69,4 +69,49 @@ extern ssize_t xwrite(int fd, const void *buf, size_t len);
extern ssize_t xpread(int fd, void *buf, size_t count, off_t offset);
extern ssize_t xpwrite(int fd, const void *buf, size_t count, off_t offset);
+#define alloc_nr(x) (((x)+16)*3/2)
+
+/*
+ * Realloc the buffer pointed at by variable 'x' so that it can hold
+ * at least 'nr' entries; the number of entries currently allocated
+ * is 'alloc', using the standard growing factor alloc_nr() macro.
+ *
+ * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
+ */
+#define ALLOC_GROW(x, nr, alloc) \
+ do { \
+ if ((nr) > alloc) { \
+ if (alloc_nr(alloc) < (nr)) \
+ alloc = (nr); \
+ else \
+ alloc = alloc_nr(alloc); \
+ x = xrealloc((x), alloc * sizeof(*(x))); \
+ } \
+ } while(0)
+
+/* dbuffer.c */
+struct dbuffer {
+ char *buffer; /* data buffer */
+ size_t capacity; /* initial maximum number of items in the buffer */
+ size_t count; /* number of items in the buffer */
+ size_t sz; /* size of each item in the buffer */
+ pthread_spinlock_t lock; /* be thread-safe */
+};
+
+#define BUF_ADDR(dbuf, idx) (dbuf->buffer + idx * dbuf->sz)
+/* Caller is responsible for index check */
+static inline void dbuffer_get_item(struct dbuffer *dbuf, void *item, size_t idx)
+{
+ memcpy(item, BUF_ADDR(dbuf, idx), dbuf->sz);
+}
+
+static inline size_t dbuffer_size(struct dbuffer *dbuf)
+{
+ return dbuf->count * dbuf->sz;
+}
+
+void dbuffer_put_item(struct dbuffer *dbuf, const void *item);
+void dbuffer_destroy(struct dbuffer *dbuf);
+int dbuffer_create(struct dbuffer *dbuf, size_t capacity, size_t item_size);
+
#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c4fb3af..3d08739 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,4 +4,4 @@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include
noinst_LIBRARIES = libsheepdog.a
-libsheepdog_a_SOURCES = event.c logger.c net.c util.c coroutine.c
+libsheepdog_a_SOURCES = event.c logger.c net.c util.c coroutine.c dbuffer.c
diff --git a/lib/dbuffer.c b/lib/dbuffer.c
new file mode 100644
index 0000000..3b90acc
--- /dev/null
+++ b/lib/dbuffer.c
@@ -0,0 +1,44 @@
+#include <pthread.h>
+#include <stdlib.h>
+
+#include "util.h"
+#include "logger.h"
+
+notrace int dbuffer_create(struct dbuffer *dbuf, size_t capacity, size_t sz)
+{
+ if (capacity)
+ dbuf->buffer = xmalloc(capacity * sz);
+ else
+ dbuf->buffer = NULL;
+ dbuf->capacity = capacity;
+ dbuf->count = 0;
+ dbuf->sz = sz;
+ if (pthread_spin_init(&dbuf->lock, 0) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+notrace void dbuffer_destroy(struct dbuffer *dbuf)
+{
+ free(dbuf->buffer);
+ pthread_spin_destroy(&dbuf->lock);
+}
+
+notrace static void dbuffer_try_grow(struct dbuffer *dbuf, size_t extra)
+{
+ size_t len = dbuf->count * dbuf->sz;
+ if (len + extra + 1 <= len)
+ panic("you want to use way too much memory");
+ ALLOC_GROW(dbuf->buffer, len + extra + 1, dbuf->capacity);
+}
+
+/* Put the item to the tail of the buffer */
+notrace void dbuffer_put_item(struct dbuffer *dbuf, const void *item)
+{
+ pthread_spin_lock(&dbuf->lock);
+ dbuffer_try_grow(dbuf, dbuf->sz);
+ memcpy(BUF_ADDR(dbuf, dbuf->count), item, dbuf->sz);
+ dbuf->count++;
+ pthread_spin_unlock(&dbuf->lock);
+}
diff --git a/sheep/strbuf.h b/sheep/strbuf.h
index 573784b..3033209 100644
--- a/sheep/strbuf.h
+++ b/sheep/strbuf.h
@@ -17,26 +17,6 @@ struct strbuf {
char *buf;
};
-#define alloc_nr(x) (((x)+16)*3/2)
-
-/*
- * Realloc the buffer pointed at by variable 'x' so that it can hold
- * at least 'nr' entries; the number of entries currently allocated
- * is 'alloc', using the standard growing factor alloc_nr() macro.
- *
- * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
- */
-#define ALLOC_GROW(x, nr, alloc) \
- do { \
- if ((nr) > alloc) { \
- if (alloc_nr(alloc) < (nr)) \
- alloc = (nr); \
- else \
- alloc = alloc_nr(alloc); \
- x = xrealloc((x), alloc * sizeof(*(x))); \
- } \
- } while(0)
-
#define STRBUF_INIT { 0, 0, 0, NULL }
/*----- strbuf life cycle -----*/
--
1.7.8.2
More information about the sheepdog
mailing list