Index: /trunk/cgi-bin/IPDB.pm
===================================================================
--- /trunk/cgi-bin/IPDB.pm	(revision 714)
+++ /trunk/cgi-bin/IPDB.pm	(revision 715)
@@ -150,5 +150,69 @@
 
 
-# Let's initialize the globals.
+## IPDB::_compactFree()
+# Utility sub to compact a set of free block entries down to the minimum possible set of CIDR entries
+# Not to be called outside of an eval{}!
+sub _compactFree {
+  my $dbh = shift;
+
+  my $parent = shift;
+
+  # Rather than having the caller provide all the details
+  my $pinfo = getBlockData($dbh, $parent);
+  my $ftype = (split //, $pinfo->{type})[1];
+
+# NetAddr::IP->compact() attempts to produce the smallest inclusive block
+# from the caller and the passed terms.
+# EG:  if you call $cidr->compact($ip1,$ip2,$ip3) when $cidr, $ip1, $ip2,
+#	and $ip3 are consecutive /27's starting on .0 (.0-.31, .32-.63,
+#	.64-.95, and .96-.128), you will get an array containing a single
+#	/25 as element 0 (.0-.127).  Order is not important;  you could have
+#	$cidr=.32/27, $ip1=.96/27, $ip2=.0/27, and $ip3=.64/27.
+
+##fixme: vrf
+##fixme:  simplify since all containers now represent different "layers"/"levels"?
+
+  # set up the query to get the list of blocks to try to merge.
+  my $sth = $dbh->prepare(q{
+	SELECT cidr,id FROM freeblocks
+	WHERE parent_id = ?
+	ORDER BY masklen(cidr) DESC
+	});
+  $sth->execute($parent);
+
+  my (@rawfb, @combinelist, %rawid);
+  my $i=0;
+  # for each free block under $parent, push a NetAddr::IP object into one list, and
+  # continuously use NetAddr::IP->compact to automagically merge netblocks as possible.
+  while (my ($fcidr, $fid) = $sth->fetchrow_array) {
+    my $testIP = new NetAddr::IP $fcidr;
+    push @rawfb, $testIP;
+    $rawid{"$testIP"} = $fid;  # $data[0] vs "$testIP" *does* make a difference for v6
+    @combinelist = $testIP->compact(@combinelist);
+  }
+
+  # now that we have the full list of "compacted" freeblocks, go back over
+  # the list of raw freeblocks, and delete the ones that got merged.
+  $sth = $dbh->prepare("DELETE FROM freeblocks WHERE id = ?");
+  foreach my $rawfree (@rawfb) {
+    next if grep { $rawfree == $_ } @combinelist;	# skip if the raw block is in the compacted list
+    $sth->execute($rawid{$rawfree});
+  }
+
+  # now we walk the new list of compacted blocks, and see which ones we need to insert
+  $sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,parent_id,master_id) VALUES (?,?,?,?,?)");
+  foreach my $cme (@combinelist) {
+    next if grep { $cme == $_ } @rawfb;	# skip if the combined block was in the raw list
+    $sth->execute($cme, $pinfo->{city}, $ftype, $parent, $pinfo->{master_id});
+  }
+
+} # end _compactFree()
+
+
+##
+## Public subs
+##
+
+
 ## IPDB::initIPDBGlobals()
 # Initialize all globals.  Takes a database handle, returns a success or error code
@@ -1998,46 +2062,6 @@
 	}
 
-##fixme: vrf
-##fixme:  simplify since all containers now represent different "layers"/"levels"?
-	# set up the query to get the list of blocks to try to merge.
-	$sth = $dbh->prepare("SELECT cidr,id FROM freeblocks ".
-		"WHERE parent_id = ? ".
-		"ORDER BY masklen(cidr) DESC");
-
-	$sth->execute($p_id);
-
-# NetAddr::IP->compact() attempts to produce the smallest inclusive block
-# from the caller and the passed terms.
-# EG:  if you call $cidr->compact($ip1,$ip2,$ip3) when $cidr, $ip1, $ip2,
-#	and $ip3 are consecutive /27's starting on .0 (.0-.31, .32-.63,
-#	.64-.95, and .96-.128), you will get an array containing a single
-#	/25 as element 0 (.0-.127).  Order is not important;  you could have
-#	$cidr=.32/27, $ip1=.96/27, $ip2=.0/27, and $ip3=.64/27.
-
-	my (@rawfb, @combinelist, %rawid);
-	my $i=0;
-	# for each free block under $parent, push a NetAddr::IP object into one list, and
-	# continuously use NetAddr::IP->compact to automagically merge netblocks as possible.
-	while (my @data = $sth->fetchrow_array) {
-	  my $testIP = new NetAddr::IP $data[0];
-	  push @rawfb, $testIP;
-          $rawid{"$testIP"} = $data[1];  # $data[0] vs "$testIP" *does* make a difference for v6
-	  @combinelist = $testIP->compact(@combinelist);
-	}
-
-	# now that we have the full list of "compacted" freeblocks, go back over
-	# the list of raw freeblocks, and delete the ones that got merged.
-	$sth = $dbh->prepare("DELETE FROM freeblocks WHERE id = ?");
-	foreach my $rawfree (@rawfb) {
-	  next if grep { $rawfree == $_ } @combinelist;	# skip if the raw block is in the compacted list
-	  $sth->execute($rawid{$rawfree});
-	}
-
-	# now we walk the new list of compacted blocks, and see which ones we need to insert
-	$sth = $dbh->prepare("INSERT INTO freeblocks (cidr,city,routed,parent_id,master_id) VALUES (?,?,?,?,?)");
-	foreach my $cme (@combinelist) {
-	  next if grep { $cme == $_ } @rawfb;	# skip if the combined block was in the raw list
-	  $sth->execute($cme, $pcity, $ptype, $p_id, $binfo->{master_id});
-	}
+        # Walk the free blocks in the parent and reduce them to the minimal set of CIDR ranges necessary
+        _compactFree($dbh, $p_id);
 
       } # done returning IPs to the appropriate place
