The oid list isn't a string, so simply using a dynamically reallocated
array makes the code simpler and earier to understand.

Signed-off-by: Christoph Hellwig <hch@lst.de>

diff --git a/sheep/object_list_cache.c b/sheep/object_list_cache.c
index 3dfb8a0..a980d20 100644
--- a/sheep/object_list_cache.c
+++ b/sheep/object_list_cache.c
@@ -30,18 +30,15 @@ struct objlist_cache {
 	int tree_version;
 	int buf_version;
 	int cache_size;
-	struct strbuf buffer;
+	uint64_t *buf;
 	struct rb_root root;
 	pthread_rwlock_t lock;
 };
 
 struct objlist_cache obj_list_cache = {
-			1, /* tree_version */
-			0, /* buf_version */
-			0, /* cache_size */
-			STRBUF_INIT, /* buffer */
-			RB_ROOT, /* root */
-		};
+	.tree_version	= 1,
+	.root		= RB_ROOT,
+};
 
 static struct objlist_cache_entry *objlist_cache_rb_insert(struct rb_root *root,
 		struct objlist_cache_entry *new)
@@ -129,32 +126,33 @@ int objlist_cache_insert(uint64_t oid)
 
 int get_obj_list(const struct sd_list_req *hdr, struct sd_list_rsp *rsp, void *data)
 {
-	uint64_t *list = (uint64_t *)data;
 	int nr = 0;
 	struct objlist_cache_entry *entry;
 	struct rb_node *p;
 
+	/* first try getting the cached buffer with only a read lock held */
 	pthread_rwlock_rdlock(&obj_list_cache.lock);
-	rsp->data_length = obj_list_cache.cache_size * sizeof(uint64_t);
-	if (obj_list_cache.tree_version == obj_list_cache.buf_version) {
-		memcpy(list, obj_list_cache.buffer.buf, rsp->data_length);
-		pthread_rwlock_unlock(&obj_list_cache.lock);
-	} else {
-		for (p = rb_first(&obj_list_cache.root); p; p = rb_next(p)) {
-			entry = rb_entry(p, struct objlist_cache_entry, node);
-			list[nr++] = entry->oid;
-		}
-		pthread_rwlock_unlock(&obj_list_cache.lock);
-
-		pthread_rwlock_wrlock(&obj_list_cache.lock);
-		if (obj_list_cache.tree_version == obj_list_cache.buf_version)
-			goto unlock;
-		strbuf_reset(&obj_list_cache.buffer);
-		strbuf_add(&obj_list_cache.buffer, list, nr * sizeof(uint64_t));
-		obj_list_cache.buf_version = obj_list_cache.tree_version;
-unlock:
-		pthread_rwlock_unlock(&obj_list_cache.lock);
+	if (obj_list_cache.tree_version == obj_list_cache.buf_version)
+		goto out;
+
+	/* if that fails grab a write lock for the usually nessecary update */
+	pthread_rwlock_unlock(&obj_list_cache.lock);
+	pthread_rwlock_wrlock(&obj_list_cache.lock);
+	if (obj_list_cache.tree_version == obj_list_cache.buf_version)
+		goto out;
+
+	obj_list_cache.buf_version = obj_list_cache.tree_version;
+	obj_list_cache.buf = xrealloc(obj_list_cache.buf,
+				obj_list_cache.cache_size * sizeof(uint64_t));
+
+	for (p = rb_first(&obj_list_cache.root); p; p = rb_next(p)) {
+		entry = rb_entry(p, struct objlist_cache_entry, node);
+		obj_list_cache.buf[nr++] = entry->oid;
 	}
 
+out:
+	rsp->data_length = obj_list_cache.cache_size * sizeof(uint64_t);
+	memcpy(data, obj_list_cache.buf, rsp->data_length);
+	pthread_rwlock_unlock(&obj_list_cache.lock);
 	return SD_RES_SUCCESS;
 }


