inserted |= insert_oid_pair(map->to_compat, oid, compat_oid);
inserted |= insert_oid_pair(map->to_storage, compat_oid, oid);
if (inserted)
- oidtree_insert(files->loose->cache, compat_oid);
+ oidtree_insert(files->loose->cache, compat_oid, NULL);
return inserted;
}
}
static int for_each_prefixed_object_wrapper_cb(const struct object_id *oid,
+ void *node_data UNUSED,
void *cb_data)
{
struct for_each_object_wrapper_data *data = cb_data;
const char *path UNUSED,
void *data)
{
- oidtree_insert(data, oid);
+ oidtree_insert(data, oid, NULL);
return 0;
}
struct oidtree_node {
struct cb_node base;
struct object_id key;
+ void *data;
};
void oidtree_init(struct oidtree *ot)
}
}
-void oidtree_insert(struct oidtree *ot, const struct object_id *oid)
+struct oidtree_data {
+ struct object_id oid;
+};
+
+void oidtree_insert(struct oidtree *ot, const struct object_id *oid,
+ void *data)
{
struct oidtree_node *on;
+ struct cb_node *node;
if (!oid->algo)
BUG("oidtree_insert requires oid->algo");
on = mem_pool_alloc(&ot->mem_pool, sizeof(*on));
oidcpy(&on->key, oid);
+ on->data = data;
/*
* n.b. Current callers won't get us duplicates, here. If a
* that won't be freed until oidtree_clear. Currently it's not
* worth maintaining a free list
*/
- cb_insert(&ot->tree, &on->base, sizeof(*oid));
+ node = cb_insert(&ot->tree, &on->base, sizeof(*oid));
+ if (node) {
+ struct oidtree_node *preexisting = container_of(node, struct oidtree_node, base);
+ preexisting->data = data;
+ }
}
-bool oidtree_contains(struct oidtree *ot, const struct object_id *oid)
+static struct oidtree_node *oidtree_lookup(struct oidtree *ot,
+ const struct object_id *oid)
{
struct object_id k;
size_t klen = sizeof(k);
+ struct cb_node *node;
oidcpy(&k, oid);
klen += BUILD_ASSERT_OR_ZERO(offsetof(struct object_id, hash) <
offsetof(struct object_id, algo));
- return !!cb_lookup(&ot->tree, (const uint8_t *)&k, klen);
+ node = cb_lookup(&ot->tree, (const uint8_t *)&k, klen);
+ return node ? container_of(node, struct oidtree_node, base) : NULL;
+}
+
+bool oidtree_contains(struct oidtree *ot, const struct object_id *oid)
+{
+ struct oidtree_node *node = oidtree_lookup(ot, oid);
+ return node ? 1 : 0;
+}
+
+void *oidtree_get(struct oidtree *ot, const struct object_id *oid)
+{
+ struct oidtree_node *node = oidtree_lookup(ot, oid);
+ return node ? node->data : NULL;
}
struct oidtree_each_data {
return 0;
}
- return data->cb(&node->key, data->cb_data);
+ return data->cb(&node->key, node->data, data->cb_data);
}
int oidtree_each(struct oidtree *ot, const struct object_id *prefix,
*/
void oidtree_clear(struct oidtree *ot);
-/* Insert the object ID into the tree. */
-void oidtree_insert(struct oidtree *ot, const struct object_id *oid);
+/*
+ * Insert the object ID into the tree and store the given pointer alongside
+ * with it. The data pointer of any preexisting entry will be overwritten.
+ */
+void oidtree_insert(struct oidtree *ot, const struct object_id *oid,
+ void *data);
/* Check whether the tree contains the given object ID. */
bool oidtree_contains(struct oidtree *ot, const struct object_id *oid);
+/* Get the payload stored with the given object ID. */
+void *oidtree_get(struct oidtree *ot, const struct object_id *oid);
+
/*
* Callback function used for `oidtree_each()`. Returning a non-zero exit code
* will cause iteration to stop. The exit code will be propagated to the caller
* of `oidtree_each()`.
*/
typedef int (*oidtree_each_cb)(const struct object_id *oid,
+ void *node_data,
void *cb_data);
/*
for (size_t i = 0; i < n; i++) {
struct object_id oid;
cl_parse_any_oid(hexes[i], &oid);
- oidtree_insert(ot, &oid);
+ oidtree_insert(ot, &oid, NULL);
}
return 0;
}
const char *query;
};
-static int check_each_cb(const struct object_id *oid, void *data)
+static int check_each_cb(const struct object_id *oid, void *node_data UNUSED, void *cb_data)
{
- struct expected_hex_iter *hex_iter = data;
+ struct expected_hex_iter *hex_iter = cb_data;
struct object_id expected;
cl_assert(hex_iter->i < hex_iter->expected_hexes.nr);
check_each(&ot, "32100", "321", NULL);
check_each(&ot, "32", "320", "321", NULL);
}
+
+void test_oidtree__insert_overwrites_data(void)
+{
+ struct object_id oid;
+ struct oidtree ot;
+ int a, b;
+
+ cl_parse_any_oid("1", &oid);
+
+ oidtree_init(&ot);
+
+ oidtree_insert(&ot, &oid, NULL);
+ cl_assert_equal_p(oidtree_get(&ot, &oid), NULL);
+ oidtree_insert(&ot, &oid, &a);
+ cl_assert_equal_p(oidtree_get(&ot, &oid), &a);
+ oidtree_insert(&ot, &oid, &b);
+ cl_assert_equal_p(oidtree_get(&ot, &oid), &b);
+
+ oidtree_clear(&ot);
+}