Просмотр исходного кода

Add some new calls into objdb.

These allow replacing/removing keys, and deleting a whole object subtree,
iterator functions to enumerate all objects/keys on an object,
and a dump call for debugging.



git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@1505 fd59a12c-fef9-0310-b244-a6a79926bd2f
Patrick Caulfield 18 лет назад
Родитель
Сommit
2846b57ea1
2 измененных файлов с 486 добавлено и 2 удалено
  1. 441 2
      exec/objdb.c
  2. 45 0
      exec/objdb.h

+ 441 - 2
exec/objdb.c

@@ -51,10 +51,13 @@ struct object_instance {
 	void *object_name;
 	int object_name_len;
 	unsigned int object_handle;
+	unsigned int parent_handle;
 	struct list_head key_head;
 	struct list_head child_head;
 	struct list_head child_list;
 	struct list_head *find_child_list;
+	struct list_head *iter_key_list;
+	struct list_head *iter_list;
 	void *priv;
 	struct object_valid *object_valid_list;
 	int object_valid_list_entries;
@@ -178,9 +181,12 @@ static int object_create (
 
 	object_instance->object_handle = *object_handle;
 	object_instance->find_child_list = &object_instance->child_head;
+	object_instance->iter_key_list = &object_instance->key_head;
+	object_instance->iter_list = &object_instance->child_head;
 	object_instance->priv = NULL;
 	object_instance->object_valid_list = NULL;
 	object_instance->object_valid_list_entries = 0;
+	object_instance->parent_handle = parent_object_handle;
 
 	hdb_handle_put (&object_instance_database, *object_handle);
 
@@ -312,10 +318,66 @@ error_exit:
 	return (-1);
 }
 
+
+static int _clear_object(struct object_instance *instance)
+{
+	struct list_head *list;
+	int res;
+	struct object_instance *find_instance = NULL;
+	struct object_key *object_key = NULL;
+
+	for (list = instance->key_head.next;
+	     list != &instance->key_head; ) {
+
+                object_key = list_entry (list, struct object_key,
+					 list);
+
+		list = list->next;
+
+		list_del(&object_key->list);
+		free(object_key->key_name);
+		free(object_key->value);
+	}
+
+	for (list = instance->child_head.next;
+	     list != &instance->child_head; ) {
+
+                find_instance = list_entry (list, struct object_instance,
+					    child_list);
+		res = _clear_object(find_instance);
+		if (res)
+			return res;
+
+		list = list->next;
+
+		list_del(&find_instance->child_list);
+		free(find_instance->object_name);
+		free(find_instance);
+	}
+
+	return 0;
+}
+
 static int object_destroy (
 	unsigned int object_handle)
 {
-	return (0);
+	struct object_instance *instance;
+	unsigned int res;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	/* Recursively clear sub-objects & keys */
+	res = _clear_object(instance);
+
+	list_del(&instance->child_list);
+	free(instance->object_name);
+	free(instance);
+
+	return (res);
 }
 
 static int object_valid_set (
@@ -477,6 +539,153 @@ error_exit:
 	return (-1);
 }
 
+static int object_key_delete (
+	unsigned int object_handle,
+	void *key_name,
+	int key_len,
+	void *value,
+	int value_len)
+{
+	unsigned int res;
+	int ret = 0;
+	struct object_instance *instance;
+	struct object_key *object_key = NULL;
+	struct list_head *list;
+	int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	for (list = instance->key_head.next;
+		list != &instance->key_head; list = list->next) {
+
+		object_key = list_entry (list, struct object_key, list);
+
+		if ((object_key->key_len == key_len) &&
+		    (memcmp (object_key->key_name, key_name, key_len) == 0) &&
+		    (value == NULL ||
+		     (object_key->value_len == value_len &&
+		      (memcmp (object_key->value, value, value_len) == 0)))) {
+			found = 1;
+			break;
+		}
+	}
+	if (found) {
+		list_del(&object_key->list);
+		free(object_key->key_name);
+		free(object_key->value);
+		free(object_key);
+	}
+	else {
+		ret = -1;
+		errno = ENOENT;
+	}
+
+	hdb_handle_put (&object_instance_database, object_handle);
+	return (ret);
+
+error_exit:
+	return (-1);
+}
+
+static int object_key_replace (
+	unsigned int object_handle,
+	void *key_name,
+	int key_len,
+	void *old_value,
+	int old_value_len,
+	void *new_value,
+	int new_value_len)
+{
+	unsigned int res;
+	int ret = 0;
+	struct object_instance *instance;
+	struct object_key *object_key = NULL;
+	struct list_head *list;
+	int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	for (list = instance->key_head.next;
+		list != &instance->key_head; list = list->next) {
+
+		object_key = list_entry (list, struct object_key, list);
+
+		if ((object_key->key_len == key_len) &&
+		    (memcmp (object_key->key_name, key_name, key_len) == 0) &&
+		    (old_value == NULL ||
+		     (object_key->value_len == old_value_len &&
+		      (memcmp (object_key->value, old_value, old_value_len) == 0)))) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		int i;
+
+		/*
+		 * Do validation check if validation is configured for the parent object
+		 */
+		if (instance->object_key_valid_list_entries) {
+			for (i = 0; i < instance->object_key_valid_list_entries; i++) {
+				if ((key_len ==
+				     instance->object_key_valid_list[i].key_len) &&
+				    (memcmp (key_name,
+					     instance->object_key_valid_list[i].key_name,
+					     key_len) == 0)) {
+
+					found = 1;
+					break;
+				}
+			}
+
+			/*
+			 * Item not found in validation list
+			 */
+			if (found == 0) {
+				goto error_put;
+			} else {
+				if (instance->object_key_valid_list[i].validate_callback) {
+					res = instance->object_key_valid_list[i].validate_callback (
+						key_name, key_len, new_value, new_value_len);
+					if (res != 0) {
+						goto error_put;
+					}
+				}
+			}
+		}
+
+		if (new_value_len <= object_key->value_len) {
+			void *replacement_value;
+			replacement_value = malloc(new_value_len);
+			if (!replacement_value)
+				goto error_exit;
+			free(object_key->value);
+			object_key->value = replacement_value;
+		}
+		memcpy(object_key->value, new_value, new_value_len);
+		object_key->value_len = new_value_len;
+	}
+	else {
+		ret = -1;
+		errno = ENOENT;
+	}
+
+	hdb_handle_put (&object_instance_database, object_handle);
+	return (ret);
+
+error_put:
+	hdb_handle_put (&object_instance_database, object_handle);
+error_exit:
+	return (-1);
+}
+
 static int object_priv_get (
 	unsigned int object_handle,
 	void **priv)
@@ -499,18 +708,248 @@ error_exit:
 	return (-1);
 }
 
+static int _dump_object(struct object_instance *instance, FILE *file, int depth)
+{
+	struct list_head *list;
+	int res;
+	int i;
+	struct object_instance *find_instance = NULL;
+	struct object_key *object_key = NULL;
+	char stringbuf1[1024];
+	char stringbuf2[1024];
+
+	memcpy(stringbuf1, instance->object_name, instance->object_name_len);
+	stringbuf1[instance->object_name_len] = '\0';
+
+	for (i=0; i<depth; i++)
+		fprintf(file, "    ");
+
+	if (instance->object_handle != OBJECT_PARENT_HANDLE)
+		fprintf(file, "%s {\n", stringbuf1);
+
+	for (list = instance->key_head.next;
+	     list != &instance->key_head; list = list->next) {
+
+                object_key = list_entry (list, struct object_key,
+					 list);
+
+		memcpy(stringbuf1, object_key->key_name, object_key->key_len);
+		stringbuf1[object_key->key_len] = '\0';
+		memcpy(stringbuf2, object_key->value, object_key->value_len);
+		stringbuf2[object_key->value_len] = '\0';
+
+		for (i=0; i<depth+1; i++)
+			fprintf(file, "    ");
+
+		fprintf(file, "%s: %s\n", stringbuf1, stringbuf2);
+	}
+
+	for (list = instance->child_head.next;
+	     list != &instance->child_head; list = list->next) {
+
+                find_instance = list_entry (list, struct object_instance,
+					    child_list);
+		res = _dump_object(find_instance, file, depth+1);
+		if (res)
+			return res;
+	}
+	for (i=0; i<depth; i++)
+		fprintf(file, "    ");
+
+	if (instance->object_handle != OBJECT_PARENT_HANDLE)
+		fprintf(file, "}\n");
+
+	return 0;
+}
+
+
+static int object_key_iter_reset(unsigned int object_handle)
+{
+	unsigned int res;
+	struct object_instance *instance;
+
+	res = hdb_handle_get (&object_instance_database,
+		object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	instance->iter_key_list = &instance->key_head;
+
+	hdb_handle_put (&object_instance_database, object_handle);
+	return (0);
+
+error_exit:
+	return (-1);
+}
+
+static int object_key_iter(unsigned int parent_object_handle,
+			   void **key_name,
+			   int *key_len,
+			   void **value,
+			   int *value_len)
+{
+	unsigned int res;
+	struct object_instance *instance;
+	struct object_key *find_key = NULL;
+	struct list_head *list;
+	unsigned int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		parent_object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	res = -ENOENT;
+	list = instance->iter_key_list->next;
+	if (list != &instance->key_head) {
+                find_key = list_entry (list, struct object_key, list);
+		found = 1;
+	}
+	instance->iter_key_list = list;
+	if (found) {
+		*key_name = find_key->key_name;
+		if (key_len)
+			*key_len = find_key->key_len;
+		*value = find_key->value;
+		if (value_len)
+			*value_len = find_key->value_len;
+		res = 0;
+	}
+	else {
+		res = -1;
+	}
+
+	hdb_handle_put (&object_instance_database, parent_object_handle);
+	return (res);
+
+error_exit:
+	return (-1);
+}
+
+static int object_iter_reset(unsigned int parent_object_handle)
+{
+	unsigned int res;
+	struct object_instance *instance;
+
+	res = hdb_handle_get (&object_instance_database,
+		parent_object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	instance->iter_list = &instance->child_head;
+
+	hdb_handle_put (&object_instance_database, parent_object_handle);
+	return (0);
+
+error_exit:
+	return (-1);
+}
+
+static int object_iter(unsigned int parent_object_handle,
+		       void **object_name,
+		       int *name_len,
+		       unsigned int *object_handle)
+{
+	unsigned int res;
+	struct object_instance *instance;
+	struct object_instance *find_instance = NULL;
+	struct list_head *list;
+	unsigned int found = 0;
+
+	res = hdb_handle_get (&object_instance_database,
+		parent_object_handle, (void *)&instance);
+	if (res != 0) {
+		goto error_exit;
+	}
+	res = -ENOENT;
+	list = instance->iter_list->next;
+	if (list != &instance->child_head) {
+
+                find_instance = list_entry (list, struct object_instance,
+					    child_list);
+		found = 1;
+	}
+	instance->iter_list = list;
+
+	if (found) {
+		*object_handle = find_instance->object_handle;
+		*object_name = find_instance->object_name;
+		*name_len = find_instance->object_name_len;
+		res = 0;
+	}
+	else {
+		res = -1;
+	}
+
+	return (res);
+
+error_exit:
+	return (-1);
+}
+
+
+static int object_parent_get(unsigned int object_handle,
+			     unsigned int *parent_handle)
+{
+	struct object_instance *instance;
+	unsigned int res;
+
+	res = hdb_handle_get (&object_instance_database,
+			      object_handle, (void *)&instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	if (object_handle == OBJECT_PARENT_HANDLE)
+		*parent_handle = 0;
+	else
+		*parent_handle = instance->parent_handle;
+
+	hdb_handle_put (&object_instance_database, object_handle);
+
+	return (0);
+}
+
+
+static int object_dump(unsigned int object_handle,
+		       FILE *file)
+{
+	struct object_instance *instance;
+	unsigned int res;
+
+	res = hdb_handle_get (&object_instance_database,
+			      object_handle, (void *)&instance);
+	if (res != 0) {
+		return (res);
+	}
+
+	res = _dump_object(instance, file, -1);
+
+	hdb_handle_put (&object_instance_database, object_handle);
+
+	return (res);
+}
+
 struct objdb_iface_ver0 objdb_iface = {
 	.objdb_init		= objdb_init,
 	.object_create		= object_create,
 	.object_priv_set	= object_priv_set,
 	.object_key_create	= object_key_create,
+	.object_key_delete	= object_key_delete,
+	.object_key_replace	= object_key_replace,
 	.object_destroy		= object_destroy,
 	.object_valid_set	= object_valid_set,
 	.object_key_valid_set	= object_key_valid_set,
 	.object_find_reset	= object_find_reset,
 	.object_find		= object_find,
 	.object_key_get		= object_key_get,
-	.object_priv_get	= object_priv_get
+	.object_key_iter	= object_key_iter,
+	.object_key_iter_reset	= object_key_iter_reset,
+	.object_iter	        = object_iter,
+	.object_iter_reset	= object_iter_reset,
+	.object_priv_get	= object_priv_get,
+	.object_parent_get	= object_parent_get,
+	.object_dump	        = object_dump
 };
 
 struct lcr_iface objdb_iface_ver0[1] = {

+ 45 - 0
exec/objdb.h

@@ -37,6 +37,8 @@
 
 #define OBJECT_PARENT_HANDLE 0
 
+#include <stdio.h>
+
 struct object_valid {
 	char *object_name;
 	int object_len;
@@ -100,6 +102,49 @@ struct objdb_iface_ver0 {
 	int (*object_priv_get) (
 		unsigned int jobject_handle,
 		void **priv);
+
+	int (*object_key_replace) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		void *old_value,
+		int old_value_len,
+		void *new_value,
+		int new_value_len);
+
+	int (*object_key_delete) (
+		unsigned int object_handle,
+		void *key_name,
+		int key_len,
+		void *value,
+		int value_len);
+
+	int (*object_iter_reset) (
+		unsigned int parent_object_handle);
+
+	int (*object_iter) (
+		unsigned int parent_object_handle,
+		void **object_name,
+		int *name_len,
+		unsigned int *object_handle);
+
+	int (*object_key_iter_reset) (
+		unsigned int object_handle);
+
+	int (*object_key_iter) (
+		unsigned int parent_object_handle,
+		void **key_name,
+		int *key_len,
+		void **value,
+		int *value_len);
+
+	int (*object_parent_get) (
+		unsigned int object_handle,
+		unsigned int *parent_handle);
+
+	int (*object_dump) (
+		unsigned int object_handle,
+		FILE *file);
 };
 
 #endif /* OBJDB_H_DEFINED */