Skip to content

Commit

Permalink
Rework gvm_hosts_shuffle() implementation.
Browse files Browse the repository at this point in the history
Prior implementation used an O(N^2) routine. This one has O(N) time
complexity.

With a /8 network, the routine takes a couple of seconds, instead of
multiple hours.
  • Loading branch information
kroosec committed Mar 20, 2019
1 parent 52eaf2f commit 4a66413
Showing 1 changed file with 29 additions and 17 deletions.
46 changes: 29 additions & 17 deletions base/openvas_hosts.c
Original file line number Diff line number Diff line change
Expand Up @@ -1165,34 +1165,46 @@ openvas_hosts_free (openvas_hosts_t *hosts)
void
openvas_hosts_shuffle (openvas_hosts_t *hosts)
{
int count;
GList *new_list;
size_t i = 0;
GRand *rand;
GList *element;
void **shuffle_array;

if (hosts == NULL)
return;

count = openvas_hosts_count (hosts);
new_list = NULL;

/* Store all host pointers in an array. */
shuffle_array = g_malloc0 (hosts->count * sizeof (openvas_host_t *));
element = hosts->hosts;
while (element)
{
shuffle_array[i] = element->data;
element = element->next;
i++;
}
/* Shuffle the array. */
rand = g_rand_new ();
for (i = 0; i < hosts->count; i++)
{
void *tmp;
int j = g_rand_int_range (rand, 0, hosts->count);

while (count)
tmp = shuffle_array[i];
shuffle_array[i] = shuffle_array[j];
shuffle_array[j] = tmp;
}
/* Insert shuffled hosts in the list. */
element = hosts->hosts;
for (i = 0; i < hosts->count; i++)
{
GList *element;

/* Get element from random position [0, count[. */
element = g_list_nth (hosts->hosts, g_rand_int_range (rand, 0, count));
/* Remove it. */
hosts->hosts = g_list_remove_link (hosts->hosts, element);
/* Insert it in new list */
new_list = g_list_concat (element, new_list);
count--;
element->data = shuffle_array[i];
element = element->next;
}
hosts->hosts = new_list;
hosts->current = hosts->hosts;

hosts->current = hosts->hosts;
g_rand_free (rand);
g_free (shuffle_array);

}

/**
Expand Down

0 comments on commit 4a66413

Please sign in to comment.