From d6d985e8154b88e9bd66d8296d5d42d110486100 Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Fri, 16 Jan 2015 20:29:12 +0300
Subject: [PATCH] Convert recovery_new() to use exceptions.

---
 src/box/box.cc         | 71 +++++++++++++++++++++++-------------------
 src/box/recovery.cc    | 30 +++++++++---------
 src/box/replication.cc | 15 ++++-----
 3 files changed, 63 insertions(+), 53 deletions(-)

diff --git a/src/box/box.cc b/src/box/box.cc
index 2371de06a2..ca114c8dd1 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -391,7 +391,6 @@ void
 box_init()
 {
 	box_check_config();
-	title("loading", NULL);
 
 	replication_prefork(cfg_gets("snap_dir"), cfg_gets("wal_dir"));
 	stat_init();
@@ -399,7 +398,6 @@ box_init()
 	tuple_init(cfg_getd("slab_alloc_arena"),
 		   cfg_geti("slab_alloc_minimal"),
 		   cfg_getd("slab_alloc_factor"));
-
 	engine_init();
 
 	schema_init();
@@ -410,37 +408,48 @@ box_init()
 	 * as a default session user when running triggers.
 	 */
 	session_init();
-
-	/* recovery initialization */
-	recovery = recovery_new(cfg_gets("snap_dir"), cfg_gets("wal_dir"),
-		      recover_row, NULL, box_snapshot_cb, cfg_geti("rows_per_wal"));
-	recovery_set_remote(recovery, cfg_gets("replication_source"));
-	recovery_update_io_rate_limit(recovery,
-				      cfg_getd("snap_io_rate_limit"));
-	recovery_setup_panic(recovery,
-			     cfg_geti("panic_on_snap_error"),
-			     cfg_geti("panic_on_wal_error"));
-
 	stat_base = stat_register(iproto_type_strs, IPROTO_TYPE_STAT_MAX);
 
-	if (recovery_has_data(recovery)) {
-		/* Process existing snapshot */
-		recover_snap(recovery);
-		space_end_recover_snapshot();
-	} else if (recovery_has_remote(recovery)) {
-		/* Initialize a new replica */
-		replica_bootstrap(recovery);
-		space_end_recover_snapshot();
-		snapshot_save(recovery);
-	} else {
-		/* Initialize the first server of a new cluster */
-		recovery_bootstrap(recovery);
-		box_set_cluster_uuid();
-		box_set_server_uuid();
-		space_end_recover_snapshot();
-		snapshot_save(recovery);
+	title("loading", NULL);
+
+	try {
+
+		/* recovery initialization */
+		recovery = recovery_new(cfg_gets("snap_dir"),
+					cfg_gets("wal_dir"),
+					recover_row, NULL,
+					box_snapshot_cb,
+					cfg_geti("rows_per_wal"));
+		recovery_set_remote(recovery,
+				    cfg_gets("replication_source"));
+		recovery_update_io_rate_limit(recovery,
+					      cfg_getd("snap_io_rate_limit"));
+		recovery_setup_panic(recovery,
+				     cfg_geti("panic_on_snap_error"),
+				     cfg_geti("panic_on_wal_error"));
+
+		if (recovery_has_data(recovery)) {
+			/* Process existing snapshot */
+			recover_snap(recovery);
+			space_end_recover_snapshot();
+		} else if (recovery_has_remote(recovery)) {
+			/* Initialize a new replica */
+			replica_bootstrap(recovery);
+			space_end_recover_snapshot();
+			snapshot_save(recovery);
+		} else {
+			/* Initialize the first server of a new cluster */
+			recovery_bootstrap(recovery);
+			box_set_cluster_uuid();
+			box_set_server_uuid();
+			space_end_recover_snapshot();
+			snapshot_save(recovery);
+		}
+		fiber_gc();
+	} catch (Exception *e) {
+		e->log();
+		panic("can't scan a data directory");
 	}
-	fiber_gc();
 
 	title("orphan", NULL);
 	recovery_follow_local(recovery,
@@ -448,7 +457,6 @@ box_init()
 	title("hot_standby", NULL);
 
 	const char *listen = cfg_gets("listen");
-
 	/*
 	 * application server configuration).
 	 */
@@ -465,7 +473,6 @@ box_init()
 	iobuf_set_readahead(cfg_geti("readahead"));
 }
 
-
 void
 box_atfork()
 {
diff --git a/src/box/recovery.cc b/src/box/recovery.cc
index f7ce5d6954..68b19d72b7 100644
--- a/src/box/recovery.cc
+++ b/src/box/recovery.cc
@@ -121,6 +121,7 @@ fill_lsn(struct recovery_state *r, struct xrow_header *row)
 	if (row == NULL || row->server_id == 0) {
 		/* Local request */
 		int64_t lsn = vclock_inc(&r->vclock, r->server_id);
+		/* row is NULL if wal_mode = NONE */
 		if (row != NULL) {
 			row->server_id = r->server_id;
 			row->lsn = lsn;
@@ -158,6 +159,11 @@ recovery_new(const char *snap_dirname, const char *wal_dirname,
 {
 	struct recovery_state *r = (struct recovery_state *)
 			calloc(1, sizeof(*r));
+
+	auto guard = make_scoped_guard([=]{
+		free(r);
+	});
+
 	recovery_update_mode(r, WAL_NONE);
 
 	assert(rows_per_wal > 1);
@@ -179,21 +185,17 @@ recovery_new(const char *snap_dirname, const char *wal_dirname,
 
 	vclock_create(&r->vclock);
 
-	try {
-		xdir_scan(&r->snap_dir);
-		/**
-		 * Avoid scanning WAL dir before we recovered
-		 * the snapshot and know server UUID - this will
-		 * make sure the scan skips files with wrong
-		 * UUID, see replication/cluster.test for
-		 * details.
-		 */
-		xdir_check(&r->wal_dir);
-	} catch (Exception *e) {
-		e->log();
-		panic("can't scan a data directory");
-	}
+	xdir_scan(&r->snap_dir);
+	/**
+	 * Avoid scanning WAL dir before we recovered
+	 * the snapshot and know server UUID - this will
+	 * make sure the scan skips files with wrong
+	 * UUID, see replication/cluster.test for
+	 * details.
+	 */
+	xdir_check(&r->wal_dir);
 
+	guard.is_active = false;
 	return r;
 }
 
diff --git a/src/box/replication.cc b/src/box/replication.cc
index dd54ab0167..34c0b46f7b 100644
--- a/src/box/replication.cc
+++ b/src/box/replication.cc
@@ -749,20 +749,21 @@ replication_relay_loop(struct relay *relay)
 	sio_setfl(relay->sock, O_NONBLOCK, 0);
 
 	/* Initialize the recovery process */
-	struct recovery_state *r;
-	r = recovery_new(cfg_snap_dir, cfg_wal_dir,
-			 replication_relay_send_row,
-			 NULL, NULL, INT32_MAX);
-	r->relay = *relay; /* copy relay state to recovery */
-
 	int rc = EXIT_SUCCESS;
+	struct recovery_state *r = NULL;
 	try {
+		r = recovery_new(cfg_snap_dir, cfg_wal_dir,
+				 replication_relay_send_row,
+				 NULL, NULL, INT32_MAX);
+		r->relay = *relay; /* copy relay state to recovery */
+
 		assert(r->relay.type == IPROTO_SUBSCRIBE);
 		replication_relay_subscribe(r);
 	} catch (Exception *e) {
 		say_error("relay error: %s", e->errmsg());
 		rc = EXIT_FAILURE;
 	}
-	recovery_delete(r);
+	if (r)
+		recovery_delete(r);
 	exit(rc);
 }
-- 
GitLab