From 158685efd66d762817a591384b769431f5ba0b2d Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Wed, 15 Oct 2014 11:24:30 +0300 Subject: whoseip: bugfix * whoseip/Whoseip/DB.pm (ipdb_save_page): Split the page being created if the data don't fit into pagesize. (ipdb_insert): Don't use fixed entry length to compute maximum number of entries. --- whoseip/Whoseip/DB.pm | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/whoseip/Whoseip/DB.pm b/whoseip/Whoseip/DB.pm index 696afd2..1583390 100644 --- a/whoseip/Whoseip/DB.pm +++ b/whoseip/Whoseip/DB.pm @@ -251,15 +251,31 @@ sub ipdb_save_page($$) { print STDERR "saving leaf page $page->{off}\n" if $dbf->{debug}; my @a; + my $size = length(pack('LLL',0,0,0)); + my $i = 0; foreach my $ent (@{$page->{tab}}) { - push @a, @{$ent}[0 .. 3],freeze($ent->[4]); + my $x = pack('LLLa2L/a', @{$ent}[0 .. 3],freeze($ent->[4])); + my $l = length($x); + if ($size + $l > $dbf->{pagesize}) { + my $p = ipdb_alloc_page($dbf, IPDB_PAGE_LEAF); + $page->{next} = $p->{off}; + $p->{tab} = @{$page->{tab}}[$i .. $#{$page->{tab}}]; + $p->{dirty} = 1; + splice @{$page->{tab}}, $i; + last; + } + $size += $l; + push @a, $x; + } continue { + ++$i; } $ret = syswrite($dbf->{fd}, - pack('LLL(LLLa2L/a)*@'."$dbf->{pagesize}", + pack('LLLa*.', $page->{type}, $#{$page->{tab}} + 1, $page->{next}, - @a)); + @a, + $dbf->{pagesize})); } else { croak "unrecognized page type ($page->{type})"; } @@ -364,9 +380,10 @@ sub ipdb_get_page($$) { my ($x, @a) = unpack('LL257', $s); $ret{tab} = \@a; } elsif ($ret{type} == IPDB_PAGE_LEAF) { - print STDERR "found leaf page at $off\n" if $dbf->{debug}; (my $x, my $nent, $ret{next}) = unpack('LLL', $s); + print STDERR "found leaf page at $off, has $nent entries\n" + if $dbf->{debug}; my ($x1, $x2, $x3, @a) = unpack("LLL(LLLa2L/a)$nent", $s); for (my $i = 0; $i < $nent; $i += 5) { push @{$ret{tab}}, [ @a[$i .. $i+3], thaw $a[$i+4] ]; @@ -555,21 +572,6 @@ sub ipdb_insert { $page = $p; } - my $maxent = int(($dbf->{pagesize} - 12) / 14); - - while ($#{$page->{tab}} == $maxent) { - if ($page->{next}) { - $page = ipdb_cache_get($dbf, $page->{next}); - croak "$dbf->{filename}: index page found where leaf was expected" - unless $page->{type} == IPDB_PAGE_LEAF; - } else { - my $p = ipdb_alloc_page($dbf, IPDB_PAGE_LEAF); - $page->{next} = $p->{off}; - $page->{dirty} = 1; - $page = $p; - } - } - push @{$page->{tab}}, [ $ipn, $netmask, time(), $country, \%_ ]; $page->{dirty} = 1; -- cgit v1.2.1