[sheepdog] [PATCH v3 10/12] collie/farm: implement farm

Kai Zhang kyle at zelin.io
Tue May 14 09:51:55 CEST 2013


moved farm.c from sheep/farm to collie/farm and made minor modification.

Signed-off-by: Kai Zhang <kyle at zelin.io>
---
 collie/farm/farm.c |  228 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 collie/farm/farm.h |    2 +
 2 files changed, 230 insertions(+), 0 deletions(-)

diff --git a/collie/farm/farm.c b/collie/farm/farm.c
index 283cd9b..c95d5a1 100644
--- a/collie/farm/farm.c
+++ b/collie/farm/farm.c
@@ -22,3 +22,231 @@ inline char *get_object_directory(void)
 {
 	return farm_obj_dir;
 }
+
+static int create_directory(const char *p)
+{
+	int i, ret = -1;
+	struct strbuf buf = STRBUF_INIT;
+
+	strbuf_addstr(&buf, p);
+	strbuf_addstr(&buf, "/.farm");
+	if (xmkdir(buf.buf, 0755) < 0)
+		goto out;
+
+	if (!strlen(farm_dir))
+		strbuf_copyout(&buf, farm_dir, sizeof(farm_dir));
+
+	strbuf_addstr(&buf, "/objects");
+	if (xmkdir(buf.buf, 0755) < 0)
+		goto out;
+
+	for (i = 0; i < 256; i++) {
+		strbuf_addf(&buf, "/%02x", i);
+		if (xmkdir(buf.buf, 0755) < 0)
+			goto out;
+
+		strbuf_remove(&buf, buf.len - 3, 3);
+	}
+
+	if (!strlen(farm_obj_dir))
+		strbuf_copyout(&buf, farm_obj_dir, sizeof(farm_obj_dir));
+
+	ret = 0;
+out:
+	if (ret)
+		sd_eprintf("fail to create directory %m");
+	strbuf_release(&buf);
+	return ret;
+}
+
+static int get_trunk_sha1(uint32_t epoch, unsigned char *outsha1)
+{
+	int i, nr_logs = -1, ret = -1;
+	struct snap_log *log_buf, *log_free = NULL;
+	void *snap_buf = NULL;
+	struct sha1_file_hdr hdr;
+
+	log_free = log_buf = snap_log_read(&nr_logs);
+	if (nr_logs < 0)
+		goto out;
+
+	if (!epoch)
+		epoch = nr_logs;
+
+	for (i = 0; i < nr_logs; i++, log_buf++) {
+		if (log_buf->epoch != epoch)
+			continue;
+		snap_buf = snap_file_read(log_buf->sha1, &hdr);
+		if (!snap_buf)
+			goto out;
+		memcpy(outsha1, snap_buf, SHA1_LEN);
+		ret = 0;
+		goto out;
+	}
+	sd_eprintf("could not find epoch %"PRIu32, epoch);
+out:
+	if (ret)
+		sd_eprintf("fail to get trunk sha1");
+	if (log_free)
+		free(log_free);
+	if (snap_buf)
+		free(snap_buf);
+	return ret;
+}
+
+static int notify_vdi_add(uint32_t vdi_id, uint32_t nr_copies)
+{
+	int ret = -1;
+	struct sd_req hdr;
+	char *buf = NULL;
+
+	sd_init_req(&hdr, SD_OP_NOTIFY_VDI_ADD);
+	hdr.vdi_state.new_vid = vdi_id;
+	hdr.vdi_state.copies = nr_copies;
+	hdr.vdi_state.set_bitmap = true;
+
+	ret = collie_exec_req(sdhost, sdport, &hdr, buf);
+
+	if (ret)
+		sd_eprintf("fail to notify vdi add event(%" PRIx32 ", %d)",
+			vdi_id, nr_copies);
+	if (buf)
+		free(buf);
+	return ret;
+}
+
+static int fill_trunk_entry(uint64_t oid, enum obj_type type,
+			int nr_copies, void *buf, size_t size, void *data)
+{
+	int ret = -1;
+
+	struct strbuf *trunk_entries = data;
+	struct trunk_entry new_entry = {};
+	struct sha1_file_hdr hdr = { .priv = 0 };
+	struct strbuf obj_strbuf = STRBUF_INIT;
+
+	/* fill sha1 file */
+	memcpy(hdr.tag, TAG_DATA, TAG_LEN);
+	hdr.size = size;
+
+	/* fill obj_strbuf */
+	strbuf_add(&obj_strbuf, buf, size);
+	strbuf_insert(&obj_strbuf, 0, &hdr, sizeof(hdr));
+
+	/* write sha1 file and fill trunk entry */
+	if (sha1_file_write((void *)obj_strbuf.buf,
+			    obj_strbuf.len,
+			    new_entry.sha1) != 0)
+		goto out;
+
+	new_entry.oid = oid;
+	new_entry.type = type;
+	new_entry.nr_copies = nr_copies;
+	strbuf_add(trunk_entries, &new_entry, sizeof(struct trunk_entry));
+
+	ret = 0;
+out:
+	if (ret)
+		sd_eprintf("fail to fill trunk entry");
+	strbuf_release(&obj_strbuf);
+	return ret;
+}
+
+int farm_init(const char *path)
+{
+	int ret = -1;
+
+	if (create_directory(path) < 0)
+		goto out;
+	if (snap_init(farm_dir) < 0)
+		goto out;
+	return 0;
+out:
+	if (ret)
+		sd_eprintf("fail to init farm");
+	return ret;
+}
+
+int farm_save_snapshot(void)
+{
+	unsigned char snap_sha1[SHA1_LEN];
+	unsigned char trunk_sha1[SHA1_LEN];
+	struct strbuf trunk_entries = STRBUF_INIT;
+	void *snap_log = NULL;
+	int log_nr, epoch;
+	int ret = -1;
+
+	snap_log = snap_log_read(&log_nr);
+	if (!snap_log)
+		goto out;
+
+	epoch = log_nr + 1;
+
+	if (parse_obj(fill_trunk_entry, &trunk_entries) < 0)
+		goto out;
+
+	if (trunk_file_write(trunk_sha1, &trunk_entries) < 0)
+		goto out;
+
+	if (snap_file_write(epoch, trunk_sha1, snap_sha1) < 0)
+		goto out;
+
+	if (snap_log_write(epoch, snap_sha1) != 0)
+		goto out;
+
+	ret = 0;
+out:
+	if (snap_log)
+		free(snap_log);
+	strbuf_release(&trunk_entries);
+	return ret;
+}
+
+int farm_load_snapshot(uint32_t epoch)
+{
+	int ret = -1;
+	struct trunk_entry *trunk_entry, *trunk_free = NULL;
+	struct sha1_file_hdr trunk_hdr;
+	unsigned char trunk_sha1[SHA1_LEN];
+	uint64_t nr_trunks, idx;
+
+	if (get_trunk_sha1(epoch, trunk_sha1) < 0)
+		goto out;
+
+	trunk_free = trunk_entry = trunk_file_read(trunk_sha1, &trunk_hdr);
+
+	if (!trunk_entry)
+		goto out;
+
+	nr_trunks = trunk_hdr.priv;
+
+	for (idx = 0; idx < nr_trunks; idx++, trunk_entry++) {
+		struct sha1_file_hdr hdr;
+		void *buffer = NULL;
+		uint64_t oid = trunk_entry->oid;
+
+		buffer = sha1_file_read(trunk_entry->sha1, &hdr);
+		if (!buffer) {
+			sd_eprintf("oid %"PRIx64" not restored", oid);
+			goto out;
+		}
+
+		if (trunk_entry->type == VDI)
+			if (notify_vdi_add(oid_to_vid(oid),
+					   trunk_entry->nr_copies) < 0)
+				goto out;
+
+		if (sd_write_object(oid, 0, buffer, hdr.size, 0, 0,
+				    trunk_entry->nr_copies,
+				    true, true) != 0) {
+			sd_eprintf("oid %"PRIx64" not restored", oid);
+			goto out;
+		}
+	}
+	ret = 0;
+
+out:
+	if (trunk_free)
+		free(trunk_free);
+	return ret;
+}
diff --git a/collie/farm/farm.h b/collie/farm/farm.h
index 1d4c92a..2631236 100644
--- a/collie/farm/farm.h
+++ b/collie/farm/farm.h
@@ -46,6 +46,8 @@ struct sha1_file_hdr {
 
 /* farm.c */
 int farm_init(const char *path);
+int farm_save_snapshot(void);
+int farm_load_snapshot(uint32_t epoch);
 char *get_object_directory(void);
 
 /* trunk.c */
-- 
1.7.1




More information about the sheepdog mailing list