summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/collection/collection.c182
-rw-r--r--common/collection/collection.h30
-rw-r--r--common/collection/collection_tools.c2
-rw-r--r--common/collection/collection_ut.c28
4 files changed, 191 insertions, 51 deletions
diff --git a/common/collection/collection.c b/common/collection/collection.c
index 3075eff3e..e87523757 100644
--- a/common/collection/collection.c
+++ b/common/collection/collection.c
@@ -86,6 +86,8 @@ struct col_copy {
struct path_data *current_path;
char *given_name;
int given_len;
+ col_copy_cb copy_cb;
+ void *ext_data;
};
/******************** FUNCTION DECLARATIONS ****************************/
@@ -875,7 +877,7 @@ int col_remove_item(struct collection_item *ci,
}
/* Remove item (property) from current collection.
- * Just a simple wropper.
+ * Just a simple wrapper.
*/
int col_remove_item_from_current(struct collection_item *ci,
int disposition,
@@ -1015,6 +1017,64 @@ static int col_insert_property_with_ref_int(struct collection_item *collection,
return EOK;
}
+/* Special function used to copy item from one
+ * collection to another using caller's callback.
+ */
+static int col_copy_item_with_cb(struct collection_item *collection,
+ const char *property,
+ int type,
+ const void *data,
+ int length,
+ col_copy_cb copy_cb,
+ void *ext_data)
+{
+ struct collection_item *item = NULL;
+ int skip = 0;
+ int error = EOK;
+
+ TRACE_FLOW_STRING("col_copy_item_with_cb", "Entry point.");
+
+ /* Create a new property out of the given parameters */
+ error = col_allocate_item(&item, property, data, length, type);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to allocate item", error);
+ return error;
+ }
+
+ /* Call callback if any */
+ if (copy_cb) {
+ TRACE_INFO_STRING("Calling callback for item:", item->property);
+ error = copy_cb(item, ext_data, &skip);
+ if (error) {
+ TRACE_ERROR_NUMBER("Callback failed", error);
+ col_delete_item(item);
+ return error;
+ }
+ }
+
+ /* Are we told to skip this item? */
+ if (skip) col_delete_item(item);
+ else {
+ /* Insted property into the collection */
+ error = col_insert_item(collection,
+ NULL,
+ item,
+ COL_DSP_END,
+ NULL,
+ 0,
+ 0);
+ if (error) {
+ TRACE_ERROR_NUMBER("Failed to insert item", error);
+ col_delete_item(item);
+ return error;
+ }
+ }
+
+ TRACE_FLOW_STRING("col_copy_item_with_cb", "Exit");
+ return EOK;
+}
+
+
/* This is public function so we need to check the validity
* of the arguments.
*/
@@ -1923,6 +1983,7 @@ static int col_copy_traverse_handler(struct collection_item *head,
char *property = NULL;
int property_len;
struct collection_header *header;
+ char *offset;
TRACE_FLOW_STRING("col_copy_traverse_handler", "Entry.");
@@ -1957,19 +2018,29 @@ static int col_copy_traverse_handler(struct collection_item *head,
length = traverse_data->current_path->length;
TRACE_INFO_STRING("Path:", name);
TRACE_INFO_NUMBER("Path len:", length);
+ if (traverse_data->given_name != NULL) {
+ property = traverse_data->given_name;
+ property_len = traverse_data->given_len;
+ }
+ else {
+ property = current->property;
+ property_len = current->property_len;
+ }
}
else {
+ /* Do not create prefix for top collection
+ * if there is no given name.
+ */
name = NULL;
length = 0;
- }
-
- if (traverse_data->given_name != NULL) {
- property = traverse_data->given_name;
- property_len = traverse_data->given_len;
- }
- else {
- property = current->property;
- property_len = current->property_len;
+ if (traverse_data->given_name != NULL) {
+ property = traverse_data->given_name;
+ property_len = traverse_data->given_len;
+ }
+ else {
+ property = NULL;
+ property_len = 0;
+ }
}
TRACE_INFO_STRING("col_copy_traverse_handler", "About to create path data.");
@@ -2081,34 +2152,34 @@ static int col_copy_traverse_handler(struct collection_item *head,
TRACE_ERROR_NUMBER("Failed to allocate memory for a new name:", error);
return error;
}
- memcpy(property, traverse_data->current_path->name,
- traverse_data->current_path->length);
- property[traverse_data->current_path->length] = '.';
- memcpy(property + traverse_data->current_path->length + 1,
- current->property, current->property_len);
- property[traverse_data->current_path->length + 1 +
- current->property_len] = '\0';
+ /* Add first part and dot only if we have prefix */
+ offset = property;
+ if (traverse_data->current_path->length) {
+ memcpy(offset, traverse_data->current_path->name,
+ traverse_data->current_path->length);
+ offset[traverse_data->current_path->length] = '.';
+ offset += traverse_data->current_path->length + 1;
+ }
+ memcpy(offset, current->property, current->property_len);
+ offset[current->property_len] = '\0';
}
else property = current->property;
TRACE_INFO_STRING("Using property:", property);
- error = col_insert_property_with_ref_int(parent,
- NULL,
- COL_DSP_END,
- NULL,
- 0,
- 0,
- property,
- current->type,
- current->data,
- current->length,
- NULL);
- /* First free then check error */
+ error = col_copy_item_with_cb(parent,
+ property,
+ current->type,
+ current->data,
+ current->length,
+ traverse_data->copy_cb,
+ traverse_data->ext_data);
+
+ /* Free property if we allocated it */
if (traverse_data->mode == COL_COPY_FLATDOT) free(property);
if (error) {
- TRACE_ERROR_NUMBER("Add property returned error:", error);
+ TRACE_ERROR_NUMBER("Failed to copy property:", error);
return error;
}
}
@@ -2200,14 +2271,37 @@ void col_destroy_collection(struct collection_item *ci)
/* COPY */
-/* Create a deep copy of the current collection. */
-/* Referenced collections of the donor are copied as sub collections. */
+
+/* Wrapper around a more advanced function */
int col_copy_collection(struct collection_item **collection_copy,
struct collection_item *collection_to_copy,
const char *name_to_use,
int copy_mode)
{
int error = EOK;
+ TRACE_FLOW_STRING("col_copy_collection", "Entry.");
+
+ error = col_copy_collection_with_cb(collection_copy,
+ collection_to_copy,
+ name_to_use,
+ copy_mode,
+ NULL,
+ NULL);
+
+ TRACE_FLOW_NUMBER("col_copy_collection. Exit. Returning", error);
+ return error;
+}
+
+/* Create a deep copy of the current collection. */
+/* Referenced collections of the donor are copied as sub collections. */
+int col_copy_collection_with_cb(struct collection_item **collection_copy,
+ struct collection_item *collection_to_copy,
+ const char *name_to_use,
+ int copy_mode,
+ col_copy_cb copy_cb,
+ void *ext_data)
+{
+ int error = EOK;
struct collection_item *new_collection = NULL;
const char *name;
struct collection_header *header;
@@ -2215,9 +2309,9 @@ int col_copy_collection(struct collection_item **collection_copy,
struct col_copy traverse_data;
int flags;
- TRACE_FLOW_STRING("col_copy_collection", "Entry.");
+ TRACE_FLOW_STRING("col_copy_collection_with_cb", "Entry.");
- /* Collection is requered */
+ /* Collection is required */
if (collection_to_copy == NULL) {
TRACE_ERROR_NUMBER("No collection to search!", EINVAL);
return EINVAL;
@@ -2254,6 +2348,8 @@ int col_copy_collection(struct collection_item **collection_copy,
traverse_data.current_path = NULL;
traverse_data.given_name = NULL;
traverse_data.given_len = 0;
+ traverse_data.copy_cb = copy_cb;
+ traverse_data.ext_data = ext_data;
if (copy_mode == COL_COPY_FLATDOT) flags = COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END;
else if (copy_mode == COL_COPY_FLAT) flags = COL_TRAVERSE_FLAT;
@@ -2266,7 +2362,7 @@ int col_copy_collection(struct collection_item **collection_copy,
if (!error) *collection_copy = new_collection;
else col_destroy_collection(new_collection);
- TRACE_FLOW_NUMBER("col_copy_collection returning", error);
+ TRACE_FLOW_NUMBER("col_copy_collection_with_cb returning", error);
return error;
}
@@ -2518,8 +2614,10 @@ int col_add_collection_to_collection(struct collection_item *ci,
traverse_data.mode = COL_COPY_FLAT;
traverse_data.current_path = NULL;
+ traverse_data.copy_cb = NULL;
+ traverse_data.ext_data = NULL;
- if ((name_to_use) && (*name_to_use)) {
+ if ((as_property) && (*as_property)) {
/* The normal assignement generates a warning
* becuase I am assigning const to a non const.
* I can't make the structure member to be const
@@ -2530,8 +2628,8 @@ int col_add_collection_to_collection(struct collection_item *ci,
* To overcome the issue I use memcpy();
*/
memcpy(&(traverse_data.given_name),
- &(name_to_use), sizeof(char *));
- traverse_data.given_len = strlen(name_to_use);
+ &(as_property), sizeof(char *));
+ traverse_data.given_len = strlen(as_property);
}
else {
traverse_data.given_name = NULL;
@@ -2550,8 +2648,10 @@ int col_add_collection_to_collection(struct collection_item *ci,
traverse_data.mode = COL_COPY_FLATDOT;
traverse_data.current_path = NULL;
+ traverse_data.copy_cb = NULL;
+ traverse_data.ext_data = NULL;
- if ((name_to_use) && (*name_to_use)) {
+ if ((as_property) && (*as_property)) {
/* The normal assignement generates a warning
* becuase I am assigning const to a non const.
* I can't make the structure member to be const
@@ -2562,8 +2662,8 @@ int col_add_collection_to_collection(struct collection_item *ci,
* To overcome the issue I use memcpy();
*/
memcpy(&(traverse_data.given_name),
- &(name_to_use), sizeof(char *));
- traverse_data.given_len = strlen(name_to_use);
+ &(as_property), sizeof(char *));
+ traverse_data.given_len = strlen(as_property);
}
else {
traverse_data.given_name = NULL;
diff --git a/common/collection/collection.h b/common/collection/collection.h
index 710e33ba1..1ff038e15 100644
--- a/common/collection/collection.h
+++ b/common/collection/collection.h
@@ -97,13 +97,6 @@
#define COL_TRAVERSE_IGNORE 0x00000004 /* Ignore sub collections as if none
* is present */
#define COL_TRAVERSE_FLAT 0x00000008 /* Flatten the collection. */
-#define COL_TRAVERSE_FLATDOT 0x00000010 /* Flatten the collection but use
- * dotted notation for property names
- * For example the subcollection
- * named "sub" containing "foo" and
- * "bar" will be flattened as:
- * "sub.foo", "sub.bar".
- */
/* Additional iterator flags
@@ -414,13 +407,32 @@ int col_add_collection_to_collection(struct collection_item *ci, /* C
struct collection_item *collection_to_add, /* Collection to add */
int mode); /* How this collection needs to be added */
-/* Create a deep copy of the current collection. */
-/* The acceptable modes are defined at the top */
+/* Create a deep copy of the current collection.
+ * Wraps the function below.
+ * The acceptable modes are defined at the top.
+ */
int col_copy_collection(struct collection_item **collection_copy,
struct collection_item *collection_to_copy,
const char *name_to_use,
int copy_mode);
+/* Callback used in the next function */
+typedef int (*col_copy_cb)(struct collection_item *item,
+ void *ext_data,
+ int *skip);
+
+/* Create a deep copy of the current collection.
+ * Calls caller provided callback before
+ * copying each item's data.
+ * The acceptable modes are defined at the top.
+ */
+int col_copy_collection_with_cb(struct collection_item **collection_copy,
+ struct collection_item *collection_to_copy,
+ const char *name_to_use,
+ int copy_mode,
+ col_copy_cb copy_cb,
+ void *ext_data);
+
/* Signature of the callback that needs to be used when
traversing a collection or looking for a specific item */
typedef int (*col_item_fn)(const char *property, /* The name of the property will be passed in this parameter. */
diff --git a/common/collection/collection_tools.c b/common/collection/collection_tools.c
index aa82134a3..c3f00eafb 100644
--- a/common/collection/collection_tools.c
+++ b/common/collection/collection_tools.c
@@ -244,7 +244,7 @@ int col_get_data_len(int type, int length)
case COL_TYPE_UNSIGNED:
case COL_TYPE_LONG:
case COL_TYPE_ULONG:
- len = 15;
+ len = 20;
break;
case COL_TYPE_STRING:
diff --git a/common/collection/collection_ut.c b/common/collection/collection_ut.c
index 3666179c9..f1ec905ae 100644
--- a/common/collection/collection_ut.c
+++ b/common/collection/collection_ut.c
@@ -222,16 +222,30 @@ int add_collection_test(void)
return error;
}
+int copy_cb(struct collection_item *item,
+ void *ext_data,
+ int *skip)
+{
+ printf("INSIDE Copy Callback\n");
+ col_debug_item(item);
+ printf("Passed in data: %s\n", (char *) ext_data);
+ if (strcmp(col_get_item_property(item, NULL), "id") == 0) *skip = 1;
+ return EOK;
+}
+
+
int mixed_collection_test(void)
{
struct collection_item *peer;
struct collection_item *socket1;
struct collection_item *socket2;
+ struct collection_item *socket3;
struct collection_item *event;
struct collection_item *host;
char binary_dump[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
int found = 0;
unsigned int class = 0;
+ char foo[] = "foo";
int error = EOK;
@@ -295,6 +309,20 @@ int mixed_collection_test(void)
col_debug_collection(socket2, COL_TRAVERSE_DEFAULT);
col_debug_collection(peer, COL_TRAVERSE_DEFAULT);
+ error = col_copy_collection_with_cb(&socket3, socket1, "socket3",
+ COL_COPY_FLATDOT, copy_cb, (void *)foo);
+ if (error) {
+ col_destroy_collection(peer);
+ col_destroy_collection(host);
+ col_destroy_collection(socket1);
+ col_destroy_collection(socket2);
+ printf("Failed to copy collection. Error %d\n", error);
+ return error;
+ }
+
+ col_debug_collection(socket3, COL_TRAVERSE_DEFAULT);
+ col_destroy_collection(socket3);
+
printf("Adding PEER collection to SOCKET2 collection as a reference named PEER2\n");
/* Embed peer host into the socket2 as reference */