summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/collection/collection.h3
-rw-r--r--common/collection/collection_iter.c49
-rw-r--r--common/collection/collection_priv.h3
-rw-r--r--common/collection/collection_ut.c172
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;
}