struct tth tt_root_hash(const struct tth *src, size_t n_leaves) { g_assert(src); g_assert(n_leaves > 0); if (n_leaves > 1) { struct tth root, *buf; buf = halloc((n_leaves + 1) * 2 * sizeof buf[0]); n_leaves = tt_compute_parents(buf, src, n_leaves); while (n_leaves > 1) { n_leaves = tt_compute_parents(buf, buf, n_leaves); } root = buf[0]; HFREE_NULL(buf); return root; } else { return src[0]; } }
size_t tth_cache_get_tree(const struct tth *tth, filesize_t filesize, const struct tth **tree) { static struct tth nodes[TTH_MAX_LEAVES * 2]; size_t n_leaves, expected; g_return_val_if_fail(tth, 0); g_return_val_if_fail(tree, 0); expected = tt_good_node_count(filesize); if (1 == expected) { nodes[0] = *tth; *tree = &nodes[0]; return 1; } *tree = NULL; n_leaves = tth_cache_get_leaves(tth, &nodes[TTH_MAX_LEAVES], TTH_MAX_LEAVES); g_assert(n_leaves <= TTH_MAX_LEAVES); if (expected == n_leaves) { size_t n_nodes, dst, src; n_nodes = n_leaves; dst = TTH_MAX_LEAVES; while (n_leaves > 1) { src = dst; dst = src - (n_leaves + 1) / 2; n_leaves = tt_compute_parents(&nodes[dst], &nodes[src], n_leaves); n_nodes += n_leaves; } if (tth_eq(tth, &nodes[dst])) { *tree = &nodes[dst]; return n_nodes; } } if (tth_cache_file_exists(tth)) { g_warning("tth_cache_get_tree(): Removing corrupted tigertree for %s", tth_base32(tth)); tth_cache_remove(tth); } return 0; }