[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[lvm-devel] Add-cache-for-parsed-config-trees



Proposal for caching parser config trees
From: Zdenek Kabelac <zkabelac redhat com>
Subject: Add cache for parsed config trees

Before the new config tree is created - check if there is not
cached the same buffer with already created config tree.

Config tree is created from internal memory poll which is
released just on command exit via config_cache_exit().

Risk - every config tree is cached - may get memory expensive ?
Maybe it would be 'good enough' to keep only few last trees
or just the last one ?
---
 lib/commands/toolcontext.c |    2 +
 lib/config/config.c        |   57 +++++++++++++++++++++++++++++++++++++++++++-
 lib/config/config.h        |    1 +
 3 files changed, 59 insertions(+), 1 deletions(-)

diff --git a/lib/commands/toolcontext.c b/lib/commands/toolcontext.c
index 8dd7d6f..1dac646 100644
--- a/lib/commands/toolcontext.c
+++ b/lib/commands/toolcontext.c
@@ -1306,6 +1306,7 @@ int refresh_toolcontext(struct cmd_context *cmd)
 
 	activation_release();
 	lvmcache_destroy(cmd, 0);
+	config_cache_exit();
 	label_exit();
 	_destroy_segtypes(&cmd->segtypes);
 	_destroy_formats(cmd, &cmd->formats);
@@ -1370,6 +1371,7 @@ void destroy_toolcontext(struct cmd_context *cmd)
 	archive_exit(cmd);
 	backup_exit(cmd);
 	lvmcache_destroy(cmd, 0);
+	config_cache_exit();
 	label_exit();
 	_destroy_segtypes(&cmd->segtypes);
 	_destroy_formats(cmd, &cmd->formats);
diff --git a/lib/config/config.c b/lib/config/config.c
index 07c1f1c..61018b8 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -148,12 +148,67 @@ void destroy_config_tree(struct config_tree *cft)
 	dm_pool_destroy(c->mem);
 }
 
+
+static struct dm_hash_table *_config_hash;
+static struct dm_pool *_config_mem;
+
+void config_cache_exit(void)
+{
+	if (_config_hash) {
+		dm_hash_destroy(_config_hash);
+		_config_hash = NULL;
+	}
+
+	if (_config_mem) {
+		dm_pool_destroy(_config_mem);
+		_config_mem = NULL;
+	}
+}
+
+static struct config_node *_file_cache(struct parser *p)
+{
+	struct config_node *root;
+	struct dm_pool *save_mem;
+
+	if (!_config_hash) {
+		if (!(_config_hash = dm_hash_create(64))) {
+			log_error("Hash allocation failed");
+			return NULL;
+		}
+
+		if (!(_config_mem = dm_pool_create("cacheparser", 4096))) {
+			log_error("Failed to allocate cache pool.");
+                        config_cache_exit();
+			return NULL;
+		}
+	}
+
+        /* Hash by buffer - suboptimal for larger buffer */
+	if (!(root = dm_hash_lookup(_config_hash, p->fb))) {
+                /* Use cache mem pool for config tree parsing */
+		save_mem = p->mem;
+                p->mem = _config_mem;
+		root = _file(p);
+		p->mem = save_mem; /* Restore mem poll */
+		if (!root)
+                        return_NULL;
+		if (!dm_hash_insert(_config_hash, p->fb, root)) {
+                        log_error("Hash insert failed.");
+			return NULL;
+		}
+		log_debug("Caching new config tree.");
+	} else
+		log_debug("Reusing cached config tree.");
+
+        return root;
+}
+
 static int _parse_config_file(struct parser *p, struct config_tree *cft)
 {
 	p->tb = p->te = p->fb;
 	p->line = 1;
 	_get_token(p, TOK_SECTION_E);
-	if (!(cft->root = _file(p)))
+	if (!(cft->root = _file_cache(p)))
 		return_0;
 
 	return 1;
diff --git a/lib/config/config.h b/lib/config/config.h
index 2d16abd..2e3cc0d 100644
--- a/lib/config/config.h
+++ b/lib/config/config.h
@@ -59,6 +59,7 @@ struct config_tree *create_config_tree_from_string(struct cmd_context *cmd,
 int override_config_tree_from_string(struct cmd_context *cmd,
 				     const char *config_settings);
 void destroy_config_tree(struct config_tree *cft);
+void config_cache_exit(void);
 
 typedef uint32_t (*checksum_fn_t) (uint32_t initial, const uint8_t *buf, uint32_t size);
 
-- 
1.7.3.3


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]