diff options
-rw-r--r-- | common/collection/collection.c | 182 | ||||
-rw-r--r-- | common/collection/collection.h | 30 | ||||
-rw-r--r-- | common/collection/collection_tools.c | 2 | ||||
-rw-r--r-- | common/collection/collection_ut.c | 28 |
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 */ |