[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