diff --git a/libisofs/find.c b/libisofs/find.c index 85acfca..797ef88 100644 --- a/libisofs/find.c +++ b/libisofs/find.c @@ -93,13 +93,20 @@ int find_iter_remove(IsoDirIter *iter) return iso_dir_iter_remove(data->iter); } +void find_notify_child_taken(IsoDirIter *iter, IsoNode *node) +{ + /* nothing to do */ + return; +} + static struct iso_dir_iter_iface find_iter_class = { find_iter_next, find_iter_has_next, find_iter_free, find_iter_take, - find_iter_remove + find_iter_remove, + find_notify_child_taken }; int iso_dir_find_children(IsoDir* dir, IsoFindCondition *cond, diff --git a/libisofs/node.c b/libisofs/node.c index 5def3a8..95a0095 100644 --- a/libisofs/node.c +++ b/libisofs/node.c @@ -485,6 +485,10 @@ int iso_node_take(IsoNode *node) /* should never occur */ return ISO_ASSERT_FAILURE; } + + /* notify iterators just before remove */ + iso_notify_dir_iters(node, 0); + *pos = node->next; node->parent = NULL; node->next = NULL; @@ -531,7 +535,6 @@ static int iter_take(IsoDirIter *iter) { struct dir_iter_data *data; - IsoNode *pos, *pre; if (iter == NULL) { return ISO_NULL_POINTER; } @@ -549,38 +552,7 @@ int iter_take(IsoDirIter *iter) /* clear next flag */ data->flag &= ~0x01; - pos = iter->dir->children; - pre = NULL; - while (pos != NULL && pos != data->pos) { - pre = pos; - pos = pos->next; - } - if (pos == NULL) { - return ISO_ERROR; /* node not in dir */ - } - - if (pos != data->pos) { - return ISO_ASSERT_FAILURE; - } - - /* dispose iterator reference */ - iso_node_unref(data->pos); - - if (pre == NULL) { - /* node is a first position */ - iter->dir->children = pos->next; - data->pos = NULL; - } else { - pre->next = pos->next; - data->pos = pre; - iso_node_ref(pre); /* take iter ref */ - } - - /* take pos */ - pos->parent = NULL; - pos->next = NULL; - iter->dir->nchildren--; - return ISO_SUCCESS; + return iso_node_take(data->pos); } static @@ -601,19 +573,49 @@ int iter_remove(IsoDirIter *iter) /* remove node */ iso_node_unref(pos); } - if (data->pos == pos) { - return ISO_ERROR; - } return ret; } +void iter_notify_child_taken(IsoDirIter *iter, IsoNode *node) +{ + IsoNode *pos, *pre; + struct dir_iter_data *data; + data = iter->data; + + if (data->pos == node) { + pos = iter->dir->children; + pre = NULL; + while (pos != NULL && pos != data->pos) { + pre = pos; + pos = pos->next; + } + if (pos == NULL || pos != data->pos) { + return; + } + + /* dispose iterator reference */ + iso_node_unref(data->pos); + + if (pre == NULL) { + /* node is a first position */ + iter->dir->children = pos->next; + data->pos = NULL; + } else { + pre->next = pos->next; + data->pos = pre; + iso_node_ref(pre); /* take iter ref */ + } + } +} + static struct iso_dir_iter_iface iter_class = { iter_next, iter_has_next, iter_free, iter_take, - iter_remove + iter_remove, + iter_notify_child_taken }; int iso_dir_get_children(const IsoDir *dir, IsoDirIter **iter) @@ -1021,6 +1023,18 @@ void iso_dir_iter_unregister(IsoDirIter *iter) } } +void iso_notify_dir_iters(IsoNode *node, int flag) +{ + struct iter_reg_node *pos = iter_reg; + while (pos != NULL) { + IsoDirIter *iter = pos->iter; + if (iter->dir == node->parent) { + iter->class->notify_child_taken(iter, node); + } + pos = pos->next; + } +} + int iso_node_new_root(IsoDir **root) { IsoDir *dir; diff --git a/libisofs/node.h b/libisofs/node.h index 821a120..dd13469 100644 --- a/libisofs/node.h +++ b/libisofs/node.h @@ -161,6 +161,11 @@ struct iso_dir_iter_iface int (*remove)(IsoDirIter *iter); + /** + * This is called just before remove a node from a directory. The iterator + * may want to update its internal state according to this. + */ + void (*notify_child_taken)(IsoDirIter *iter, IsoNode *node); }; /** @@ -334,6 +339,6 @@ int iso_dir_iter_register(IsoDirIter *iter); */ void iso_dir_iter_unregister(IsoDirIter *iter); - +void iso_notify_dir_iters(IsoNode *node, int flag); #endif /*LIBISO_NODE_H_*/