static struct cache_tree_sub *find_subtree(struct cache_tree *it, const char *path, int pathlen, int create) { struct cache_tree_sub *down; int pos = subtree_pos(it, path, pathlen); if (0 <= pos) return it->down[pos]; if (!create) return NULL; pos = -pos-1; if (it->subtree_alloc <= it->subtree_nr) { it->subtree_alloc = alloc_nr(it->subtree_alloc); it->down = xrealloc(it->down, it->subtree_alloc * sizeof(*it->down)); } it->subtree_nr++; down = xmalloc(sizeof(*down) + pathlen + 1); down->cache_tree = NULL; down->namelen = pathlen; memcpy(down->name, path, pathlen); down->name[pathlen] = 0; if (pos < it->subtree_nr) memmove(it->down + pos + 1, it->down + pos, sizeof(down) * (it->subtree_nr - pos - 1)); it->down[pos] = down; return down; }
static struct cache_tree_sub *find_subtree(struct cache_tree *it, const char *path, int pathlen, int create) { struct cache_tree_sub *down; int pos = subtree_pos(it, path, pathlen); if (0 <= pos) return it->down[pos]; if (!create) return NULL; pos = -pos-1; ALLOC_GROW(it->down, it->subtree_nr + 1, it->subtree_alloc); it->subtree_nr++; FLEX_ALLOC_MEM(down, name, path, pathlen); down->cache_tree = NULL; down->namelen = pathlen; if (pos < it->subtree_nr) MOVE_ARRAY(it->down + pos + 1, it->down + pos, it->subtree_nr - pos - 1); it->down[pos] = down; return down; }
void cache_tree_invalidate_path(struct cache_tree *it, const char *path) { /* a/b/c * ==> invalidate self * ==> find "a", have it invalidate "b/c" * a * ==> invalidate self * ==> if "a" exists as a subtree, remove it. */ const char *slash; int namelen; struct cache_tree_sub *down; #if DEBUG fprintf(stderr, "cache-tree invalidate <%s>\n", path); #endif if (!it) return; slash = strchr(path, '/'); it->entry_count = -1; if (!slash) { int pos; namelen = strlen(path); pos = subtree_pos(it, path, namelen); if (0 <= pos) { cache_tree_free(&it->down[pos]->cache_tree); free(it->down[pos]); /* 0 1 2 3 4 5 * ^ ^subtree_nr = 6 * pos * move 4 and 5 up one place (2 entries) * 2 = 6 - 3 - 1 = subtree_nr - pos - 1 */ memmove(it->down+pos, it->down+pos+1, sizeof(struct cache_tree_sub *) * (it->subtree_nr - pos - 1)); it->subtree_nr--; } return; } namelen = slash - path; down = find_subtree(it, path, namelen, 0); if (down) cache_tree_invalidate_path(down->cache_tree, slash + 1); }
static int do_invalidate_path(struct cache_tree *it, const char *path) { /* a/b/c * ==> invalidate self * ==> find "a", have it invalidate "b/c" * a * ==> invalidate self * ==> if "a" exists as a subtree, remove it. */ const char *slash; int namelen; struct cache_tree_sub *down; #if DEBUG_CACHE_TREE fprintf(stderr, "cache-tree invalidate <%s>\n", path); #endif if (!it) return 0; slash = strchrnul(path, '/'); namelen = slash - path; it->entry_count = -1; if (!*slash) { int pos; pos = subtree_pos(it, path, namelen); if (0 <= pos) { cache_tree_free(&it->down[pos]->cache_tree); free(it->down[pos]); /* 0 1 2 3 4 5 * ^ ^subtree_nr = 6 * pos * move 4 and 5 up one place (2 entries) * 2 = 6 - 3 - 1 = subtree_nr - pos - 1 */ MOVE_ARRAY(it->down + pos, it->down + pos + 1, it->subtree_nr - pos - 1); it->subtree_nr--; } return 1; } down = find_subtree(it, path, namelen, 0); if (down) do_invalidate_path(down->cache_tree, slash + 1); return 1; }