From a43c16528780847271e2bfcc890b61cd7c211a66 Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Wed, 18 Jan 2017 10:03:23 +0100
Subject: [PATCH] timers: all zones' timers written in one txn

---
 src/knot/zone/timers.c   | 35 ++++++++++++++++++++++++++---------
 src/knot/zone/timers.h   | 22 +++++++++++++++++++++-
 src/utils/knotd/main.c   | 10 ++++++----
 tests/test_zone_timers.c |  2 +-
 4 files changed, 54 insertions(+), 15 deletions(-)

diff --git a/src/knot/zone/timers.c b/src/knot/zone/timers.c
index 97d145fe52..69244b5076 100644
--- a/src/knot/zone/timers.c
+++ b/src/knot/zone/timers.c
@@ -195,29 +195,46 @@ int zone_timers_read(knot_db_t *db, const knot_dname_t *zone,
 	return ret;
 }
 
+int zone_timers_write_begin(knot_db_t *db, knot_db_txn_t *txn)
+{
+	memset(txn, 0, sizeof(*txn));
+	return knot_db_lmdb_api()->txn_begin(db, txn, KNOT_DB_SORTED);
+}
+
+void zone_timers_write_end(knot_db_txn_t *txn)
+{
+	knot_db_lmdb_api()->txn_commit(txn);
+}
+
 int zone_timers_write(knot_db_t *db, const knot_dname_t *zone,
-                      const zone_timers_t *timers)
+                      const zone_timers_t *timers, knot_db_txn_t *txn)
 {
-	if (!db || !zone || !timers) {
+	if (!zone || !timers || (!db && !txn)) {
 		return KNOT_EINVAL;
 	}
 
 	const knot_db_api_t *db_api = knot_db_lmdb_api();
 	assert(db_api);
 
-	knot_db_txn_t txn = { 0 };
-	int ret = db_api->txn_begin(db, &txn, KNOT_DB_SORTED);
-	if (ret != KNOT_EOK) {
-		return ret;
+	knot_db_txn_t static_txn, *mytxn = txn;
+	if (txn == NULL) {
+		mytxn = &static_txn;
+		int ret = db_api->txn_begin(db, mytxn, KNOT_DB_SORTED);
+		if (ret != KNOT_EOK) {
+			return ret;
+		}
 	}
 
-	ret = txn_write_timers(&txn, zone, timers);
+	int ret = txn_write_timers(mytxn, zone, timers);
 	if (ret != KNOT_EOK) {
-		db_api->txn_abort(&txn);
+		db_api->txn_abort(mytxn);
 		return ret;
 	}
 
-	db_api->txn_commit(&txn);
+	if (txn == NULL) {
+		db_api->txn_commit(mytxn);
+	}
+
 	return KNOT_EOK;
 }
 
diff --git a/src/knot/zone/timers.h b/src/knot/zone/timers.h
index a009bef121..9d301dbb97 100644
--- a/src/knot/zone/timers.h
+++ b/src/knot/zone/timers.h
@@ -64,17 +64,37 @@ void zone_timers_close(knot_db_t *db);
 int zone_timers_read(knot_db_t *db, const knot_dname_t *zone,
                      zone_timers_t *timers);
 
+/*!
+ * \brief Init txn for zone_timers_write()
+ *
+ * \param db      Timer database.
+ * \param txn     Handler to be initialized.
+ *
+ * \return KNOT_E*
+ */
+int zone_timers_write_begin(knot_db_t *db, knot_db_txn_t *txn);
+
+/*!
+ * \brief Close txn for zone_timers_write()
+ *
+ * \param txn     Handler to be closed.
+ *
+ * \return KNOT_E*
+ */
+void zone_timers_write_end(knot_db_txn_t *txn);
+
 /*!
  * \brief Write timers for one zone.
  *
  * \param db      Timer database.
  * \param zone    Zone name.
  * \param timers  Loaded timers
+ * \param txn     Transaction handler obtained from zone_timers_write_begin()
  *
  * \return KNOT_E*
  */
 int zone_timers_write(knot_db_t *db, const knot_dname_t *zone,
-                      const zone_timers_t *timers);
+                      const zone_timers_t *timers, knot_db_txn_t *txn);
 
 /*!
  * \brief Callback used in \ref zone_timers_sweep.
diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c
index 4563ff9928..3556b939a8 100644
--- a/src/utils/knotd/main.c
+++ b/src/utils/knotd/main.c
@@ -376,9 +376,9 @@ static int set_config(const char *confdb, const char *config)
 	return KNOT_EOK;
 }
 
-static void write_timers(const zone_t *zone, zone_timers_t *db)
+static void write_timers(const zone_t *zone, knot_db_txn_t *txn)
 {
-	zone_timers_write(db, zone->name, &zone->timers);
+	zone_timers_write(NULL, zone->name, &zone->timers, txn);
 }
 
 int main(int argc, char **argv)
@@ -576,9 +576,11 @@ int main(int argc, char **argv)
 	server_wait(&server);
 	stats_deinit();
 
-	// TODO: will be very slow, each write is in separate transation
 	log_info("updating zone timers database");
-	knot_zonedb_foreach(server.zone_db, write_timers, server.timers_db);
+	knot_db_txn_t timers_txn;
+	zone_timers_write_begin(server.timers_db, &timers_txn);
+	knot_zonedb_foreach(server.zone_db, write_timers, &timers_txn);
+	zone_timers_write_end(&timers_txn);
 
 	/* Cleanup PID file. */
 	pid_cleanup();
diff --git a/tests/test_zone_timers.c b/tests/test_zone_timers.c
index 38c7aea4a1..4d0935d1ce 100644
--- a/tests/test_zone_timers.c
+++ b/tests/test_zone_timers.c
@@ -72,7 +72,7 @@ int main(int argc, char *argv[])
 	ok(ret == KNOT_ENOENT, "zone_timer_read() nonexistent");
 
 	// Write timers
-	ret = zone_timers_write(db, zone, &timers);
+	ret = zone_timers_write(db, zone, &timers, NULL);
 	ok(ret == KNOT_EOK, "zone_timers_write()");
 
 	// Read timers
-- 
GitLab