]> git.ipfire.org Git - people/ms/libloc.git/blobdiff - src/database.c
database: Allocate subnets list only once
[people/ms/libloc.git] / src / database.c
index 8835507e7be4bdb3c9e7b654d84d8d63f70227d0..1b3484592e3c08c484c80f8d01db0217d616c1e9 100644 (file)
@@ -125,6 +125,7 @@ struct loc_database_enumerator {
 
        // For subnet search and bogons
        struct loc_network_list* stack;
+       struct loc_network_list* subnets;
 
        // For bogons
        struct in6_addr gap6_start;
@@ -984,6 +985,9 @@ static void loc_database_enumerator_free(struct loc_database_enumerator* enumera
        if (enumerator->stack)
                loc_network_list_unref(enumerator->stack);
 
+       if (enumerator->subnets)
+               loc_network_list_unref(enumerator->subnets);
+
        free(enumerator);
 }
 
@@ -1301,12 +1305,13 @@ static int __loc_database_enumerator_next_network_flattened(
                return 0;
 
        struct loc_network* subnet = NULL;
-       struct loc_network_list* subnets;
 
        // Create a list with all subnets
-       r = loc_network_list_new(enumerator->ctx, &subnets);
-       if (r)
-               return r;
+       if (!enumerator->subnets) {
+               r = loc_network_list_new(enumerator->ctx, &enumerator->subnets);
+               if (r)
+                       return r;
+       }
 
        // Search all subnets from the database
        while (1) {
@@ -1314,7 +1319,7 @@ static int __loc_database_enumerator_next_network_flattened(
                r = __loc_database_enumerator_next_network(enumerator, &subnet, 0);
                if (r) {
                        loc_network_unref(subnet);
-                       loc_network_list_unref(subnets);
+                       loc_network_list_clear(enumerator->subnets);
 
                        return r;
                }
@@ -1325,10 +1330,10 @@ static int __loc_database_enumerator_next_network_flattened(
 
                // Collect all subnets in a list
                if (loc_network_is_subnet(*network, subnet)) {
-                       r = loc_network_list_push(subnets, subnet);
+                       r = loc_network_list_push(enumerator->subnets, subnet);
                        if (r) {
                                loc_network_unref(subnet);
-                               loc_network_list_unref(subnets);
+                               loc_network_list_clear(enumerator->subnets);
 
                                return r;
                        }
@@ -1341,7 +1346,7 @@ static int __loc_database_enumerator_next_network_flattened(
                r = loc_network_list_push(enumerator->stack, subnet);
                if (r) {
                        loc_network_unref(subnet);
-                       loc_network_list_unref(subnets);
+                       loc_network_list_clear(enumerator->subnets);
 
                        return r;
                }
@@ -1350,27 +1355,28 @@ static int __loc_database_enumerator_next_network_flattened(
                break;
        }
 
-       DEBUG(enumerator->ctx, "Found %zu subnet(s)\n", loc_network_list_size(subnets));
+       DEBUG(enumerator->ctx, "Found %zu subnet(s)\n",
+               loc_network_list_size(enumerator->subnets));
 
        // We can abort here if the network has no subnets
-       if (loc_network_list_empty(subnets)) {
-               loc_network_list_unref(subnets);
+       if (loc_network_list_empty(enumerator->subnets)) {
+               loc_network_list_clear(enumerator->subnets);
 
                return 0;
        }
 
        // If the network has any subnets, we will break it into smaller parts
        // without the subnets.
-       struct loc_network_list* excluded = loc_network_exclude_list(*network, subnets);
+       struct loc_network_list* excluded = loc_network_exclude_list(*network, enumerator->subnets);
        if (!excluded) {
-               loc_network_list_unref(subnets);
+               loc_network_list_clear(enumerator->subnets);
                return -1;
        }
 
        // Merge subnets onto the stack
-       r = loc_network_list_merge(enumerator->stack, subnets);
+       r = loc_network_list_merge(enumerator->stack, enumerator->subnets);
        if (r) {
-               loc_network_list_unref(subnets);
+               loc_network_list_clear(enumerator->subnets);
                loc_network_list_unref(excluded);
 
                return r;
@@ -1379,13 +1385,13 @@ static int __loc_database_enumerator_next_network_flattened(
        // Push excluded list onto the stack
        r = loc_network_list_merge(enumerator->stack, excluded);
        if (r) {
-               loc_network_list_unref(subnets);
+               loc_network_list_clear(enumerator->subnets);
                loc_network_list_unref(excluded);
 
                return r;
        }
 
-       loc_network_list_unref(subnets);
+       loc_network_list_clear(enumerator->subnets);
        loc_network_list_unref(excluded);
 
        // Drop the network and restart the whole process again to pick the next network