From be25085fabf316f934a48102f5491e1d29568437 Mon Sep 17 00:00:00 2001 From: Robert Anderson <randerson@lbsd.net> Date: Fri, 5 Mar 2010 07:52:10 +0000 Subject: [PATCH] * Calculate accounting based on bytes for log line entires and round up to Mbyte for totals accounting/mod_accounting_sql.pm | 97 ++++++++++++++++++++++++++------------- system/mod_config_sql_topups.pm | 36 +++++++++----- 2 files changed, 89 insertions(+), 44 deletions(-) --- .../modules/accounting/mod_accounting_sql.pm | 97 +++++++++++++------ .../modules/system/mod_config_sql_topups.pm | 36 ++++--- 2 files changed, 89 insertions(+), 44 deletions(-) diff --git a/smradius/modules/accounting/mod_accounting_sql.pm b/smradius/modules/accounting/mod_accounting_sql.pm index 9a42350b..92933cff 100644 --- a/smradius/modules/accounting/mod_accounting_sql.pm +++ b/smradius/modules/accounting/mod_accounting_sql.pm @@ -29,6 +29,7 @@ use smradius::util; use POSIX qw(ceil); use DateTime; use Math::BigInt; +use Math::BigFloat; # Exporter stuff @@ -335,9 +336,9 @@ sub getUsage # Our usage hash my %usageTotals; - $usageTotals{'TotalTimeUsage'} = 0; - $usageTotals{'TotalDataInput'} = 0; - $usageTotals{'TotalDataOutput'} = 0; + $usageTotals{'TotalSessionTime'} = Math::BigInt->new(); + $usageTotals{'TotalDataInput'} = Math::BigInt->new(); + $usageTotals{'TotalDataOutput'} = Math::BigInt->new(); # Pull in usage and add up while (my $row = hashifyLCtoMC($sth->fetchrow_hashref(), @@ -346,30 +347,41 @@ sub getUsage # Look for session time if (defined($row->{'AcctSessionTime'}) && $row->{'AcctSessionTime'} > 0) { - $usageTotals{'TotalTimeUsage'} += ceil($row->{'AcctSessionTime'} / 60); + $usageTotals{'TotalSessionTime'}->badd($row->{'AcctSessionTime'}); } # Add input usage if we have any if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) { - $usageTotals{'TotalDataInput'} += ceil($row->{'AcctInputOctets'} / 1024 / 1024); + $usageTotals{'TotalDataInput'}->badd($row->{'AcctInputOctets'}); } if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) { - $usageTotals{'TotalDataInput'} += ceil($row->{'AcctInputGigawords'} * 4096); + my $inputGigawords = Math::BigInt->new($row->{'AcctInputGigawords'}); + $inputGigawords->bmul(UINT_MAX); + $usageTotals{'TotalDataInput'}->badd($inputGigawords); } # Add output usage if we have any if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) { - $usageTotals{'TotalDataOutput'} += ceil($row->{'AcctOutputOctets'} / 1024 / 1024); + $usageTotals{'TotalDataOutput'}->badd($row->{'AcctOutputOctets'}); } if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) { - $usageTotals{'TotalDataOutput'} += ceil($row->{'AcctOutputGigawords'} * 4096); + my $outputGigawords = Math::BigInt->new($row->{'AcctOutputGigawords'}); + $outputGigawords->bmul(UINT_MAX); + $usageTotals{'TotalDataOutput'}->badd($outputGigawords); } } DBFreeRes($sth); + # Convert to bigfloat for accuracy + my $totalData = Math::BigFloat->new(); + $totalData->badd($usageTotals{'TotalDataOutput'})->badd($usageTotals{'TotalDataInput'}); + my $totalTime = Math::BigFloat->new(); + $totalTime->badd($usageTotals{'TotalSessionTime'}); + # Rounding up - $usageTotals{'TotalDataUsage'} = $usageTotals{'TotalDataInput'} + $usageTotals{'TotalDataOutput'}; - $usageTotals{'TotalTimeUsage'} = $usageTotals{'TotalTimeUsage'}; + my %res; + $res{'TotalDataUsage'} = $totalData->bdiv('1024')->bdiv('1024')->bceil()->bstr(); + $res{'TotalSessionTime'} = $totalTime->bdiv('60')->bceil()->bstr(); - return \%usageTotals; + return \%res; } @@ -750,49 +762,58 @@ sub cleanup if (defined($usageTotals{$row->{'Username'}})) { # Look for session time if (defined($row->{'AcctSessionTime'}) && $row->{'AcctSessionTime'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalSessionTime'} += ceil($row->{'AcctSessionTime'} / 60); + $usageTotals{$row->{'Username'}}{'TotalSessionTime'}->badd($row->{'AcctSessionTime'}); } # Add input usage if we have any if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalInput'} += ceil($row->{'AcctInputOctets'} / 1024 / 1024); + $usageTotals{$row->{'Username'}}{'TotalDataInput'}->badd($row->{'AcctInputOctets'}); } if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalInput'} += ceil($row->{'AcctInputGigawords'} * 4096); + my $inputGigawords = Math::BigInt->new($row->{'AcctInputGigawords'}); + $inputGigawords->bmul(UINT_MAX); + $usageTotals{$row->{'Username'}}{'TotalDataInput'}->badd($inputGigawords); } # Add output usage if we have any if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalOutput'} += ceil($row->{'AcctOutputOctets'} / 1024 / 1024); + $usageTotals{$row->{'Username'}}{'TotalDataOutput'}->badd($row->{'AcctOutputOctets'}); } if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalOutput'} += ceil($row->{'AcctOutputGigawords'} * 4096); + my $outputGigawords = Math::BigInt->new($row->{'AcctOutputGigawords'}); + $outputGigawords->bmul(UINT_MAX); + $usageTotals{$row->{'Username'}}{'TotalDataOutput'}->badd($outputGigawords); } # This is a new record... } else { + + # Make BigInts for this user + $usageTotals{$row->{'Username'}}{'TotalSessionTime'} = Math::BigInt->new(); + $usageTotals{$row->{'Username'}}{'TotalDataInput'} = Math::BigInt->new(); + $usageTotals{$row->{'Username'}}{'TotalDataOutput'} = Math::BigInt->new(); + # Look for session time if (defined($row->{'AcctSessionTime'}) && $row->{'AcctSessionTime'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalSessionTime'} = ceil($row->{'AcctSessionTime'} / 60); - } else { - $usageTotals{$row->{'Username'}}{'TotalSessionTime'} = 0; + $usageTotals{$row->{'Username'}}{'TotalSessionTime'}->badd($row->{'AcctSessionTime'}); } - - # Total up the input usage - $usageTotals{$row->{'Username'}}{'TotalInput'} = 0; + # Add input usage if we have any if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalInput'} = ceil($row->{'AcctInputOctets'} / 1024 / 1024); + $usageTotals{$row->{'Username'}}{'TotalDataInput'}->badd($row->{'AcctInputOctets'}); } if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalInput'} = ceil($row->{'AcctInputGigawords'} * 4096); + my $inputGigawords = Math::BigInt->new($row->{'AcctInputGigawords'}); + $inputGigawords->bmul(UINT_MAX); + $usageTotals{$row->{'Username'}}{'TotalDataInput'}->badd($inputGigawords); } - - # Total up the output usage - $usageTotals{$row->{'Username'}}{'TotalOutput'} = 0; + # Add output usage if we have any if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalOutput'} = ceil($row->{'AcctOutputOctets'} / 1024 / 1024); + $usageTotals{$row->{'Username'}}{'TotalDataOutput'}->badd($row->{'AcctOutputOctets'}); } if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) { - $usageTotals{$row->{'Username'}}{'TotalOutput'} = ceil($row->{'AcctOutputGigawords'} * 4096); + my $outputGigawords = Math::BigInt->new($row->{'AcctOutputGigawords'}); + $outputGigawords->bmul(UINT_MAX); + $usageTotals{$row->{'Username'}}{'TotalDataOutput'}->badd($outputGigawords); } + } } @@ -816,6 +837,18 @@ sub cleanup # Loop through users and insert totals foreach my $username (keys %usageTotals) { + + # Convert to bigfloat for accuracy + my $totalDataOutput = Math::BigFloat->new($usageTotals{$username}{'TotalDataOutput'}); + my $totalDataInput = Math::BigFloat->new($usageTotals{$username}{'TotalDataInput'}); + my $totalTime = Math::BigFloat->new($usageTotals{$username}{'TotalSessionTime'}); + + # Rounding up + my $res; + $res->{'TotalDataInput'} = $totalDataInput->bdiv('1024')->bdiv('1024')->bceil()->bstr(); + $res->{'TotalDataOutput'} = $totalDataOutput->bdiv('1024')->bdiv('1024')->bceil()->bstr(); + $res->{'TotalSessionTime'} = $totalTime->bdiv('60')->bceil()->bstr(); + @dbDoParams = (' INSERT INTO @TP@accounting_summary @@ -831,9 +864,9 @@ sub cleanup ', $username, $lastMonth, - $usageTotals{$username}{'TotalSessionTime'}, - $usageTotals{$username}{'TotalInput'}, - $usageTotals{$username}{'TotalOutput'} + $res->{'TotalSessionTime'}, + $res->{'TotalDataInput'}, + $res->{'TotalDataOutput'} ); if ($sth) { diff --git a/smradius/modules/system/mod_config_sql_topups.pm b/smradius/modules/system/mod_config_sql_topups.pm index 19f823da..ee48eebe 100644 --- a/smradius/modules/system/mod_config_sql_topups.pm +++ b/smradius/modules/system/mod_config_sql_topups.pm @@ -30,6 +30,8 @@ use smradius::attributes; use POSIX qw(ceil); use DateTime; use Date::Parse; +use Math::BigInt; +use Math::BigFloat; @@ -358,9 +360,9 @@ sub cleanup # Our usage hash my %usageTotals; - $usageTotals{'TotalTimeUsage'} = 0; - $usageTotals{'TotalDataInput'} = 0; - $usageTotals{'TotalDataOutput'} = 0; + $usageTotals{'TotalSessionTime'} = Math::BigInt->new(); + $usageTotals{'TotalDataInput'} = Math::BigInt->new(); + $usageTotals{'TotalDataOutput'} = Math::BigInt->new(); # Pull in usage and add up while (my $row = hashifyLCtoMC($sth->fetchrow_hashref(), @@ -369,28 +371,38 @@ sub cleanup # Look for session time if (defined($row->{'AcctSessionTime'}) && $row->{'AcctSessionTime'} > 0) { - $usageTotals{'TotalTimeUsage'} += ceil($row->{'AcctSessionTime'} / 60); + $usageTotals{'TotalSessionTime'}->badd($row->{'AcctSessionTime'}); } # Add input usage if we have any if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) { - $usageTotals{'TotalDataInput'} += ceil($row->{'AcctInputOctets'} / 1024 / 1024); + $usageTotals{'TotalDataInput'}->badd($row->{'AcctInputOctets'}); } if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) { - $usageTotals{'TotalDataInput'} += ceil($row->{'AcctInputGigawords'} * 4096); + my $inputGigawords = Math::BigInt->new($row->{'AcctInputGigawords'}); + $inputGigawords->bmul(UINT_MAX); + $usageTotals{'TotalDataInput'}->badd($inputGigawords); } # Add output usage if we have any if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) { - $usageTotals{'TotalDataOutput'} += ceil($row->{'AcctOutputOctets'} / 1024 / 1024); + $usageTotals{'TotalDataOutput'}->badd($row->{'AcctOutputOctets'}); } if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) { - $usageTotals{'TotalDataOutput'} += ceil($row->{'AcctOutputGigawords'} * 4096); + my $outputGigawords = Math::BigInt->new($row->{'AcctOutputGigawords'}); + $outputGigawords->bmul(UINT_MAX); + $usageTotals{'TotalDataOutput'}->badd($outputGigawords); } } DBFreeRes($sth); + # Convert to bigfloat for accuracy + my $totalData = Math::BigFloat->new(); + $totalData->badd($usageTotals{'TotalDataOutput'})->badd($usageTotals{'TotalDataInput'}); + my $totalTime = Math::BigFloat->new(); + $totalTime->badd($usageTotals{'TotalSessionTime'}); + # Rounding up - $usageTotals{'TotalDataUsage'} = $usageTotals{'TotalDataInput'} + $usageTotals{'TotalDataOutput'}; - $usageTotals{'TotalTimeUsage'} = $usageTotals{'TotalTimeUsage'}; + $usageTotals{'TotalDataUsage'} = $totalData->bdiv('1024')->bdiv('1024')->bceil()->bstr(); + $usageTotals{'TotalSessionTime'} = $totalTime->bdiv('60')->bceil()->bstr(); # Get user traffic and uptime limits from group attributes # FIXME - Support for realm config @@ -756,7 +768,7 @@ sub cleanup if (defined($capRecord{'UptimeLimit'})) { # Check traffic used against cap - $uptimeOverUsage = $usageTotals{'TotalTimeUsage'} - $capRecord{'UptimeLimit'}; + $uptimeOverUsage = $usageTotals{'TotalSessionTime'} - $capRecord{'UptimeLimit'}; # If there is no limit, this may be a prepaid user } else { $capRecord{'UptimeLimit'} = 0; @@ -766,7 +778,7 @@ sub cleanup foreach my $topup (@uptimeTopups) { $capRecord{'UptimeLimit'} += $topup->{'Value'}; } - $uptimeOverUsage = $usageTotals{'TotalTimeUsage'} - $capRecord{'UptimeLimit'}; + $uptimeOverUsage = $usageTotals{'TotalSessionTime'} - $capRecord{'UptimeLimit'}; } # User has started using topup uptime.. -- GitLab