From b68b601e59cec9e12e2ad929e115e1cc2c05bcaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz>
Date: Thu, 11 Jun 2015 00:00:23 +0200
Subject: [PATCH] modules/cachectl: fixed cachectl, optional pruning
 granularity

---
 modules/cachectl/README.rst |  3 ++-
 modules/cachectl/cachectl.c | 23 ++++++++++++++++++-----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/modules/cachectl/README.rst b/modules/cachectl/README.rst
index abe5b5774..14d75842d 100644
--- a/modules/cachectl/README.rst
+++ b/modules/cachectl/README.rst
@@ -6,8 +6,9 @@ Module providing an interface to cache database, for inspection, manipulation an
 Properties
 ^^^^^^^^^^
 
-.. function:: cachectl.prune()
+.. function:: cachectl.prune([max_count])
 
+  :param number max_count:  maximum number of items to be pruned at once (default: 65536)
   :return: ``{ pruned: int }``
 
   Prune expired/invalid records.
diff --git a/modules/cachectl/cachectl.c b/modules/cachectl/cachectl.c
index 19bc1ef48..4e042da96 100644
--- a/modules/cachectl/cachectl.c
+++ b/modules/cachectl/cachectl.c
@@ -41,7 +41,7 @@
 /** Return boolean true if a record is expired. */
 static bool is_expired(struct kr_cache_entry *entry, uint32_t drift)
 {
-	return entry->ttl >= drift;
+	return drift > entry->ttl;
 }
 
 /**
@@ -65,18 +65,31 @@ static char* prune(void *env, struct kr_module *module, const char *args)
 
 	/* Iterate cache and find expired records. */
 	int pruned = 0;
-	uint32_t now = time(NULL);
+	int prune_max = 0;
+	if (args) {
+		prune_max = atoi(args);
+	}
+	/* Default pruning granularity */
+	if (prune_max == 0) {
+		prune_max = PRUNE_GRANULARITY;
+	}
+	/* Fetch current time and start iterating */
+	struct timeval now;
+	gettimeofday(&now, NULL);
 	namedb_iter_t *it = storage->iter_begin(&txn.t, 0);
-	while (it && pruned < PRUNE_GRANULARITY) {
+	while (it && pruned < prune_max) {
 		/* Fetch RR from cache */
 		namedb_val_t key, val;
 		if (storage->iter_key(it, &key) != 0 ||
-		    storage->iter_val(it, &val)) {
+		    storage->iter_val(it, &val) != 0) {
 			break;
 		}
 		/* Prune expired records. */
 		struct kr_cache_entry *entry = val.data;
-		if (is_expired(entry, now - entry->timestamp)) {
+		if (entry->timestamp > now.tv_sec) {
+			continue;
+		}
+		if (is_expired(entry, now.tv_sec - entry->timestamp)) {
 			storage->del(&txn.t, &key);
 			cache->stats.delete += 1;
 			pruned += 1;
-- 
GitLab