+ return hash;
+}
+
+static bool satisfies(const TDB_DATA *data, const TDB_DATA *need)
+{
+ /* Don't need anything? Cool. */
+ if (!need)
+ return true;
+
+ /* This should be tdb_null or a real value. */
+ assert(data != &must_exist);
+ assert(data != &must_not_exist);
+ assert(data != ¬_exists_or_empty);
+
+ /* must_not_exist == must_not_exist, must_exist == must_exist, or
+ not_exists_or_empty == not_exists_or_empty. */
+ if (data->dsize == need->dsize && data->dptr == need->dptr)
+ return true;
+
+ /* Must not exist? data must not exist. */
+ if (need == &must_not_exist)
+ return data->dptr == NULL;
+
+ /* Must exist? */
+ if (need == &must_exist)
+ return data->dptr != NULL;
+
+ /* Either noexist or empty. */
+ if (need == ¬_exists_or_empty)
+ return data->dsize == 0;
+
+ /* Needs something specific. */
+ return key_eq(*data, *need);
+}
+
+static bool sort_deps(char *filename[], struct op *op[],
+ struct key_user res[], unsigned num,
+ const TDB_DATA *data)
+{
+ unsigned int i;
+
+ /* Nothing left? We're sorted. */
+ if (num == 0)
+ return true;
+
+ for (i = 0; i < num; i++) {
+ struct op *this_op = &op[res[i].file][res[i].op_num];
+
+ /* Is what we have good enough for this op? */
+ if (satisfies(data, needs(this_op))) {
+ /* Try this one next. */
+ struct key_user tmp = res[0];
+ res[0] = res[i];
+ res[i] = tmp;
+ if (sort_deps(filename, op, res+1, num-1,
+ gives(this_op, data)))
+ return true;
+ }
+ }
+ /* No combination worked. */
+ return false;
+}
+
+/* All these ops have the same serial number. Which comes first?
+ *
+ * This can happen both because read ops or failed write ops don't
+ * change serial number, and also due to race since we access the
+ * number unlocked (the race can cause less detectable ordering problems,
+ * in which case we'll deadlock and report: fix manually in that case).
+ */
+static void figure_deps(char *filename[], struct op *op[],
+ struct key_user user[], unsigned start, unsigned end)
+{
+ unsigned int i;
+ /* We assume database starts empty. */
+ const struct TDB_DATA *data = &tdb_null;
+
+ /* What do we have to start with? */
+ for (i = 0; i < start; i++)
+ data = gives(&op[user[i].file][user[i].op_num], data);
+
+ if (!sort_deps(filename, op, user + start, end - start, data))
+ fail(filename[user[start].file], user[start].op_num+1,
+ "Could not resolve inter-dependencies");
+}
+
+static void sort_ops(struct keyinfo hash[], char *filename[], struct op *op[])
+{
+ unsigned int h;
+
+ /* Gcc nexted function extension. How cool is this? */
+ int compare_serial(const void *_a, const void *_b)
+ {
+ const struct key_user *a = _a, *b = _b;
+ return op[a->file][a->op_num].serial
+ - op[b->file][b->op_num].serial;
+ }
+