+/* This is simple, but not complete. We don't take into account
+ * indirect dependencies. */
+static void optimize_dependencies(struct op *op[], unsigned int num_ops[],
+ unsigned int num)
+{
+ unsigned int i, j;
+
+ /* There can only be one real dependency on each file */
+ for (i = 0; i < num; i++) {
+ for (j = 1; j < num_ops[i]; j++) {
+ struct depend *dep, *next;
+ struct depend *prev[num];
+
+ memset(prev, 0, sizeof(prev));
+
+ list_for_each_safe(&op[i][j].pre, dep, next, pre_list) {
+ if (!prev[dep->prereq.file]) {
+ prev[dep->prereq.file] = dep;
+ continue;
+ }
+ if (prev[dep->prereq.file]->prereq.op_num
+ < dep->prereq.op_num) {
+ talloc_free(prev[dep->prereq.file]);
+ prev[dep->prereq.file] = dep;
+ } else
+ talloc_free(dep);
+ }
+ }
+ }
+
+ for (i = 0; i < num; i++) {
+ int deps[num];
+
+ for (j = 0; j < num; j++)
+ deps[j] = -1;
+
+ for (j = 1; j < num_ops[i]; j++) {
+ struct depend *dep, *next;
+
+ list_for_each_safe(&op[i][j].pre, dep, next, pre_list) {
+ if (deps[dep->prereq.file]
+ >= (int)dep->prereq.op_num)
+ talloc_free(dep);
+ else
+ deps[dep->prereq.file]
+ = dep->prereq.op_num;
+ }
+ }
+ }
+}
+
+#if TRAVERSALS_TAKE_TRANSACTION_LOCK
+/* Force an order among the traversals, so they don't deadlock (as much) */
+static void make_traverse_depends(char *filename[],
+ struct op *op[], unsigned int num_ops[],
+ unsigned int num)
+{
+ unsigned int i, num_traversals = 0;
+ int j;
+ struct op_desc *desc;
+
+ /* Sort by which one runs first. */
+ int compare_traverse_desc(const void *_a, const void *_b)
+ {
+ const struct op_desc *da = _a, *db = _b;
+ const struct op *a = &op[da->file][da->op_num],
+ *b = &op[db->file][db->op_num];
+
+ if (a->seqnum != b->seqnum)
+ return a->seqnum - b->seqnum;
+
+ /* If they have same seqnum, it means one didn't make any
+ * changes. Thus sort by end in that case. */
+ return a[a->group_len].seqnum - b[b->group_len].seqnum;
+ }
+
+ desc = talloc_array(NULL, struct op_desc, 1);
+
+ /* Count them. */
+ for (i = 0; i < num; i++) {
+ for (j = 1; j < num_ops[i]; j++) {
+ /* Traverse start (ignore those in
+ * transactions; they're already covered by
+ * transaction dependencies). */
+ if (starts_traverse(&op[i][j])
+ && !in_transaction(op[i], j)) {
+ desc = talloc_realloc(NULL, desc,
+ struct op_desc,
+ num_traversals+1);
+ desc[num_traversals].file = i;
+ desc[num_traversals].op_num = j;
+ num_traversals++;
+ }
+ }
+ }
+ qsort(desc, num_traversals, sizeof(desc[0]), compare_traverse_desc);
+
+ for (i = 1; i < num_traversals; i++) {
+ const struct op *prev = &op[desc[i-1].file][desc[i-1].op_num];
+ const struct op *curr = &op[desc[i].file][desc[i].op_num];
+
+ /* Read traverses don't depend on each other (read lock). */
+ if (prev->type == OP_TDB_TRAVERSE_READ_START
+ && curr->type == OP_TDB_TRAVERSE_READ_START)
+ continue;
+
+ /* Only make dependency if it's clear. */
+ if (compare_traverse_desc(&desc[i], &desc[i-1])) {
+ /* i depends on end of traverse i-1. */
+ struct op_desc end = desc[i-1];
+ end.op_num += prev->group_len;
+ add_dependency(NULL, op, filename, &desc[i], &end);
+ }
+ }
+ talloc_free(desc);
+}
+#endif
+