Changeset 716 for trunk/cgi-bin
- Timestamp:
- 05/06/15 14:01:30 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/cgi-bin/IPDB.pm
r715 r716 208 208 209 209 } # end _compactFree() 210 211 212 ## IPDB::_deleteCascade() 213 # Internal sub. Deletes an allocation and all subcomponents 214 sub _deleteCascade { 215 my $dbh = shift; 216 my $id = shift; 217 218 my $binfo = getBlockData($dbh, $id); 219 220 ##fixme: special-case master blocks up here and quickly delete based on master_id, 221 # instead of wasting time tracing parent relations 222 223 # grab all allocations in the master within the CIDR of the block to be deleted 224 my %parents; 225 my %cidrlist; 226 ##fixme: limit by VRF? 227 my $sth = $dbh->prepare("SELECT cidr,id,parent_id FROM allocations WHERE cidr <<= ? AND master_id = ?"); 228 $sth->execute($binfo->{block}, $binfo->{master_id}); 229 while (my ($cidr, $cid, $pid) = $sth->fetchrow_array) { 230 $parents{$cid} = $pid; 231 $cidrlist{$cid} = $cidr; 232 } 233 234 # Trace the parent relations up the tree until we either hit parent ID 0 (we've found a master block 235 # but not the parent we're looking for - arguably this is already an error) or the parent ID matches 236 # the passed ID. If the latter, push the whole set into a second flag hash, so we can terminate 237 # further tree-tracing early. 238 my %found; 239 foreach my $cid (keys %parents) { 240 my @tmp; 241 if ($cid == $id) { 242 # "child" is the ID we've been asked to cascade-delete. 243 $found{$cid}++; 244 } elsif ($found{$cid}) { 245 # ID already seen and the chain terminates in our parent. 246 } elsif ($parents{$cid} == $id) { 247 # Immediate parent is the target parent 248 $found{$cid}++; 249 } else { 250 # Immediate parent isn't the one we're looking for. Walk the chain up until we hit our parent, 251 # the nonexistent parent id 0, or undefined (ID is not a child of the target ID at all) 252 # There are probably better ways to structure this loop. 253 while (1) { 254 # cache the ID 255 push @tmp, $cid; 256 # some very particularly defined loop ending conditions 257 if (!defined($parents{$cid}) || $parents{$cid} == $id || $parents{$cid} == 0) { 258 last; 259 } else { 260 # if we haven't found either the desired parent or another limiting condition, 261 # reset the ID to the parent next up the tree 262 $cid = $parents{$cid}; 263 } 264 } 265 # if the current chain of relations ended with our target parent, shuffle the cached IDs into a flag hash 266 if (defined($parents{$cid}) && $parents{$cid} == $id) { 267 foreach (@tmp) { $found{$_}++; } 268 } 269 } # else 270 } # foreach my $cid 271 272 # Use the keys in the flag hash to determine which allocations to actually delete. 273 # Delete matching freeblocks and pool IPs; their parents are going away so we want 274 # to make sure we don't leave orphaned records lying around loose. 275 my @dellist = keys %found; 276 push @dellist, $id; # Just In Case the target ID didn't make the list earlier. 277 my $b = '?'. (',?' x $#dellist); 278 $dbh->do("DELETE FROM allocations WHERE id IN ($b)", undef, (@dellist) ); 279 $dbh->do("DELETE FROM freeblocks WHERE parent_id IN ($b)", undef, (@dellist) ); 280 $dbh->do("DELETE FROM poolips WHERE parent_id IN ($b)", undef, (@dellist) ); 281 282 # Insert a new free block in the target's parent, unless we just deleted a whole master block. 283 if ($binfo->{type} ne 'mm') { 284 my $pinfo = getBlockData($dbh, $binfo->{parent_id}); 285 my $pt = (split //, $pinfo->{type})[1]; 286 $dbh->do("INSERT INTO freeblocks (cidr,city,routed,parent_id,vrf,master_id) VALUES (?,?,?,?,?,?)", undef, 287 $binfo->{block}, $pinfo->{city}, $pt, $binfo->{parent_id}, $pinfo->{vrf}, $binfo->{master_id}); 288 } 289 290 ##todo: and hey! bonus! we can return @dellist, or something (%cidrlist{@dellist}) 291 } # end _deleteCascade() 210 292 211 293
Note:
See TracChangeset
for help on using the changeset viewer.