Commit 27c21a117aca21c6059c735e8aed46d0c27d01bd

Stefan Sperling 2018-06-22T09:30:25

introduce got_object_idset_remove_random()

diff --git a/lib/got_lib_object_idset.h b/lib/got_lib_object_idset.h
index 68c9c90..f5c7fb0 100644
--- a/lib/got_lib_object_idset.h
+++ b/lib/got_lib_object_idset.h
@@ -24,6 +24,8 @@ const struct got_error *got_object_idset_add(void **,
 void *got_object_idset_get(struct got_object_idset *, struct got_object_id *);
 const struct got_error *got_object_idset_remove(struct got_object_idset *,
     struct got_object_id *);
+const struct got_error *got_object_idset_remove_random(void **,
+    struct got_object_idset *);
 int got_object_idset_contains(struct got_object_idset *,
     struct got_object_id *);
 void got_object_idset_for_each(struct got_object_idset *,
diff --git a/lib/object_idset.c b/lib/object_idset.c
index ae64f9a..12537d5 100644
--- a/lib/object_idset.c
+++ b/lib/object_idset.c
@@ -181,6 +181,34 @@ got_object_idset_remove(struct got_object_idset *set,
 	return got_error(GOT_ERR_NO_OBJ);
 }
 
+const struct got_error *
+got_object_idset_remove_random(void **data, struct got_object_idset *set)
+{
+	struct got_object_idset_element *entry, *tmp;
+	int i, n;
+
+	*data = NULL;
+
+	if (set->nelem == 0)
+		return got_error(GOT_ERR_NO_OBJ);
+
+	n = arc4random_uniform(set->nelem);
+	for (i = 0; i < nitems(set->entries); i++) {
+		TAILQ_FOREACH_SAFE(entry, &set->entries[i], entry, tmp) {
+			if (--n == 0) {
+				TAILQ_REMOVE(&set->entries[i], entry, entry);
+				*data = entry->data;
+				free(entry);
+				set->nelem--;
+				return NULL;
+			}
+		}
+
+	}
+
+	return got_error(GOT_ERR_NO_OBJ);
+}
+
 int
 got_object_idset_contains(struct got_object_idset *set,
     struct got_object_id *id)