diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/collection/collection.h | 3 | ||||
-rw-r--r-- | common/collection/collection_iter.c | 49 | ||||
-rw-r--r-- | common/collection/collection_priv.h | 3 | ||||
-rw-r--r-- | common/collection/collection_ut.c | 172 |
4 files changed, 220 insertions, 7 deletions
diff --git a/common/collection/collection.h b/common/collection/collection.h index b4bbb2a4b..be1240ca5 100644 --- a/common/collection/collection.h +++ b/common/collection/collection.h @@ -742,6 +742,9 @@ int col_get_iterator_depth(struct collection_iterator *iterator, int *depth); */ int col_get_item_depth(struct collection_iterator *iterator, int *depth); +/* Pins down the iterator to loop around current point */ +void col_pin_iterator(struct collection_iterator *iterator); + /* FIXME - Do we need to be able to rewind iterator? */ /* Set collection class */ diff --git a/common/collection/collection_iter.c b/common/collection/collection_iter.c index 4d7a90428..f66fc3085 100644 --- a/common/collection/collection_iter.c +++ b/common/collection/collection_iter.c @@ -87,6 +87,8 @@ int col_bind_iterator(struct collection_iterator **iterator, iter->stack_depth = 0; iter->item_level = 0; iter->flags = mode_flags; + iter->pin_level = 0; + iter->can_break = 0; TRACE_INFO_NUMBER("Iterator flags", iter->flags); @@ -110,6 +112,7 @@ int col_bind_iterator(struct collection_iterator **iterator, header = (struct collection_header *)ci->data; header->reference_count++; iter->top = ci; + iter->pin = ci; *(iter->stack) = ci; iter->stack_depth++; @@ -213,17 +216,29 @@ int col_iterate_collection(struct collection_iterator *iterator, TRACE_INFO_NUMBER("Stack depth:", iterator->stack_depth); - /* Are we done? */ if (iterator->stack_depth == 0) { - TRACE_FLOW_STRING("We are done.", ""); - *item = NULL; - return EOK; + /* Re-init so if we continue looping we start over */ + iterator->stack[0] = iterator->top; + iterator->stack_depth++; + iterator->item_level = 0; } /* Is current item available */ current = iterator->stack[iterator->stack_depth - 1]; iterator->item_level = iterator->stack_depth - 1; + /* Are we done? */ + if (((iterator->stack_depth - 1) == iterator->pin_level) && + (iterator->pin == current)) { + if (iterator->can_break) { + TRACE_FLOW_STRING("We are done.", ""); + *item = NULL; + iterator->can_break = 0; + return EOK; + } + else iterator->can_break = 1; + } + /* We are not done so check if we have an item */ if (current != NULL) { @@ -357,6 +372,30 @@ int col_iterate_collection(struct collection_iterator *iterator, } } - TRACE_FLOW_STRING("iterate_collection", "Exit"); + TRACE_FLOW_STRING("col_iterate_collection", "Exit"); return EOK; } + + +/* Pins down the iterator to loop around this point */ +void col_pin_iterator(struct collection_iterator *iterator) +{ + TRACE_FLOW_STRING("col_iterator_add_pin", "Entry"); + + while ((iterator->stack[iterator->stack_depth - 1] == NULL) && + (iterator->stack_depth)) { + iterator->stack_depth--; + } + + if (iterator->stack_depth == 0) { + iterator->pin = iterator->top; + iterator->pin_level = 0; + } + else { + iterator->pin = iterator->stack[iterator->stack_depth - 1]; + iterator->pin_level = iterator->stack_depth - 1; + } + iterator->can_break = 0; + + TRACE_FLOW_STRING("col_iterator_add_pin", "Exit"); +} diff --git a/common/collection/collection_priv.h b/common/collection/collection_priv.h index 767514bee..a8aa36699 100644 --- a/common/collection/collection_priv.h +++ b/common/collection/collection_priv.h @@ -60,6 +60,9 @@ struct collection_iterator { unsigned item_level; int flags; struct collection_item *end_item; + struct collection_item *pin; + unsigned pin_level; + unsigned can_break; }; diff --git a/common/collection/collection_ut.c b/common/collection/collection_ut.c index c17f5bc7b..5d0c58463 100644 --- a/common/collection/collection_ut.c +++ b/common/collection/collection_ut.c @@ -593,6 +593,7 @@ int iterator_test(void) int depth = 0; int idepth = 0; int len = 0; + int i; printf("\n\n==== ITERATOR TEST ====\n\n"); @@ -1015,8 +1016,6 @@ int iterator_test(void) return error; } - col_destroy_collection(peer); - printf("\n\nIterate up test:\n\n"); do { @@ -1026,6 +1025,7 @@ int iterator_test(void) if (error) { printf("Error (iterate): %d\n", error); col_unbind_iterator(iterator); + col_destroy_collection(peer); return error; } @@ -1065,6 +1065,174 @@ int iterator_test(void) while(1); col_unbind_iterator(iterator); + + /* Bind iterator again in flat mode */ + error = col_bind_iterator(&iterator, peer, COL_TRAVERSE_FLAT | COL_TRAVERSE_END); + if (error) { + printf("Error (bind): %d\n", error); + col_destroy_collection(peer); + return error; + } + + printf("\n\nCircled looping:\n\n"); + + for (i = 0; i < 200; i++) { + /* Loop through a collection */ + error = col_iterate_collection(iterator, &item); + if (error) { + printf("Error (iterate): %d\n", error); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return error; + } + + /* Are we done ? */ + if (item == NULL) printf("Reached end.\n\n"); + else { + depth = 0; + col_get_item_depth(iterator, &depth); + printf("%*s", depth * 4, ""); + col_debug_item(item); + } + } + + /* Do not forget to unbind iterator - otherwise there will be a leak */ + col_unbind_iterator(iterator); + + /* Bind iterator again in flat mode */ + error = col_bind_iterator(&iterator, peer, COL_TRAVERSE_FLAT | COL_TRAVERSE_END); + if (error) { + printf("Error (bind): %d\n", error); + col_destroy_collection(peer); + return error; + } + + printf("\n\nCircled looping with pin:\n\n"); + + do { + /* Loop through a collection */ + error = col_iterate_collection(iterator, &item); + if (error) { + printf("Error (iterate): %d\n", error); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return error; + } + + if (strcmp(col_get_item_property(item, NULL), "queue") == 0) { + /* Make it a new looping point */ + col_pin_iterator(iterator); + printf("Found pin point.\n\n"); + break; + } + /* Are we done ? */ + if (item == NULL) { + printf("Unexpected end.\n\n"); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return EINVAL; + } + else { + depth = 0; + col_get_item_depth(iterator, &depth); + printf("%*s", depth * 4, ""); + col_debug_item(item); + } + } + while(1); + + /* Second loop around the pin point */ + for (i = 0; i < 200; i++) { + /* Loop through a collection */ + error = col_iterate_collection(iterator, &item); + if (error) { + printf("Error (iterate): %d\n", error); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return error; + } + + /* Are we done ? */ + if (item == NULL) printf("Reached end.\n\n"); + else { + depth = 0; + col_get_item_depth(iterator, &depth); + printf("%*s", depth * 4, ""); + col_debug_item(item); + } + } + + /* Do not forget to unbind iterator - otherwise there will be a leak */ + col_unbind_iterator(iterator); + + + /* Bind iterator again in flat mode */ + error = col_bind_iterator(&iterator, peer, COL_TRAVERSE_DEFAULT | COL_TRAVERSE_END); + if (error) { + printf("Error (bind): %d\n", error); + col_destroy_collection(peer); + return error; + } + + printf("\n\nCircled looping with pin (default):\n\n"); + + do { + /* Loop through a collection */ + error = col_iterate_collection(iterator, &item); + if (error) { + printf("Error (iterate): %d\n", error); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return error; + } + + if (strcmp(col_get_item_property(item, NULL), "queue") == 0) { + /* Make it a new looping point */ + col_pin_iterator(iterator); + printf("Found pin point.\n\n"); + break; + } + /* Are we done ? */ + if (item == NULL) { + printf("Unexpected end.\n\n"); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return EINVAL; + } + else { + depth = 0; + col_get_item_depth(iterator, &depth); + printf("%*s", depth * 4, ""); + col_debug_item(item); + } + } + while(1); + + /* Second loop around the pin point */ + for (i = 0; i < 200; i++) { + /* Loop through a collection */ + error = col_iterate_collection(iterator, &item); + if (error) { + printf("Error (iterate): %d\n", error); + col_destroy_collection(peer); + col_unbind_iterator(iterator); + return error; + } + + /* Are we done ? */ + if (item == NULL) printf("Reached end.\n\n"); + else { + depth = 0; + col_get_item_depth(iterator, &depth); + printf("%*s", depth * 4, ""); + col_debug_item(item); + } + } + + /* Do not forget to unbind iterator - otherwise there will be a leak */ + col_unbind_iterator(iterator); + col_destroy_collection(peer); + return EOK; } |