[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