Skip to content
Snippets Groups Projects
Commit 43531b3f authored by Robert Anderson's avatar Robert Anderson
Browse files

Correctly handle large numbers for accounting_summary

Note: database schema for accounting_summary has been changed
parent 08ae2aac
No related branches found
No related tags found
No related merge requests found
r509: r538:
# Database
ALTER TABLE accounting_summary DROP COLUMN AcctSessionTime;
ALTER TABLE accounting_summary DROP COLUMN AcctInputOctets;
ALTER TABLE accounting_summary DROP COLUMN AcctInputGigawords;
ALTER TABLE accounting_summary DROP COLUMN AcctOutputOctets;
ALTER TABLE accounting_summary DROP COLUMN AcctOutputGigawords;
ALTER TABLE accounting_summary ADD COLUMN TotalSessionTime INT UNSIGNED;
ALTER TABLE accounting_summary ADD COLUMN TotalInput INT UNSIGNED;
ALTER TABLE accounting_summary ADD COLUMN TotalOutput INT UNSIGNED;
r509:
# Database # Database
ALTER TABLE accounting ADD PeriodKey VARCHAR(7); ALTER TABLE accounting ADD PeriodKey VARCHAR(7);
......
...@@ -255,13 +255,9 @@ CREATE TABLE @PREFIX@accounting_summary ( ...@@ -255,13 +255,9 @@ CREATE TABLE @PREFIX@accounting_summary (
PeriodKey DATETIME, PeriodKey DATETIME,
AcctSessionTime @INT_UNSIGNED@, TotalSessionTime @INT_UNSIGNED@,
AcctInputOctets @INT_UNSIGNED@,
AcctInputGigawords @INT_UNSIGNED@, TotalInput @INT_UNSIGNED@,
AcctOutputOctets @INT_UNSIGNED@,
AcctOutputGigawords @INT_UNSIGNED@ TotalOutput @INT_UNSIGNED@
) @CREATE_TABLE_SUFFIX@; ) @CREATE_TABLE_SUFFIX@;
...@@ -721,22 +721,22 @@ sub cleanup ...@@ -721,22 +721,22 @@ sub cleanup
# New datetime # New datetime
my $lastMonth = DateTime->new( year => $prevYear, month => $prevMonth, day => 1 ); my $lastMonth = DateTime->new( year => $prevYear, month => $prevMonth, day => 1 );
my $periodKey = $lastMonth->strftime("%Y-%m"); my $periodKey = $lastMonth->strftime("%Y-%m");
# Sanitize
$lastMonth = $lastMonth->ymd();
# Select totals for last month # Select totals for last month
my $sth = DBSelect(' my $sth = DBSelect('
SELECT SELECT
Username, Username,
SUM(AcctSessionTime) as AcctSessionTime, AcctSessionTime,
SUM(AcctInputOctets) as AcctInputOctets, AcctInputOctets,
SUM(AcctInputGigawords) as AcctInputGigawords, AcctInputGigawords,
SUM(AcctOutputOctets) as AcctOutputOctets, AcctOutputOctets,
SUM(AcctOutputGigawords) as AcctOutputGigawords AcctOutputGigawords
FROM FROM
@TP@accounting @TP@accounting
WHERE WHERE
PeriodKey = ? PeriodKey = ?
GROUP BY
Username
', ',
$periodKey $periodKey
); );
...@@ -747,161 +747,119 @@ sub cleanup ...@@ -747,161 +747,119 @@ sub cleanup
return; return;
} }
# Set blank array
my @allRecords;
# Load items into array # Load items into array
my $index = 0; my %usageTotals;
while (my $usageTotals = $sth->fetchrow_hashref()) { while (my $row = hashifyLCtoMC($sth->fetchrow_hashref(),
$usageTotals = hashifyLCtoMC(
$usageTotals,
qw(Username AcctSessionTime AcctInputOctets AcctInputGigawords AcctOutputOctets AcctOutputGigawords) qw(Username AcctSessionTime AcctInputOctets AcctInputGigawords AcctOutputOctets AcctOutputGigawords)
); )) {
# check if we've seen this user, if so just add up
if (defined($usageTotals{$row->{'Username'}})) {
# Look for session time
if (defined($row->{'AcctSessionTime'}) && $row->{'AcctSessionTime'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalSessionTime'} += ceil($row->{'AcctSessionTime'} / 60);
}
# Add input usage if we have any
if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalInput'} += ceil($row->{'AcctInputOctets'} / 1024 / 1024);
}
if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalInput'} += ceil($row->{'AcctInputGigawords'} * 4096);
}
# Add output usage if we have any
if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalOutput'} += ceil($row->{'AcctOutputOctets'} / 1024 / 1024);
}
if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalOutput'} += ceil($row->{'AcctOutputGigawords'} * 4096);
}
# This is a new record...
} else {
# 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;
}
# Total up the input usage
$usageTotals{$row->{'Username'}}{'TotalInput'} = 0;
if (defined($row->{'AcctInputOctets'}) && $row->{'AcctInputOctets'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalInput'} = ceil($row->{'AcctInputOctets'} / 1024 / 1024);
}
if (defined($row->{'AcctInputGigawords'}) && $row->{'AcctInputGigawords'} > 0) {
$usageTotals{$row->{'Username'}}{'TotalInput'} = ceil($row->{'AcctInputGigawords'} * 4096);
}
# Set array items # Total up the output usage
$allRecords[$index] = { $usageTotals{$row->{'Username'}}{'TotalOutput'} = 0;
Username => $usageTotals->{'Username'}, if (defined($row->{'AcctOutputOctets'}) && $row->{'AcctOutputOctets'} > 0) {
PeriodKey => $lastMonth->ymd, $usageTotals{$row->{'Username'}}{'TotalOutput'} = ceil($row->{'AcctOutputOctets'} / 1024 / 1024);
SessionTime => $usageTotals->{'AcctSessionTime'}, }
InputOctets => $usageTotals->{'AcctInputOctets'}, if (defined($row->{'AcctOutputGigawords'}) && $row->{'AcctOutputGigawords'} > 0) {
InputGigawords => $usageTotals->{'AcctInputGigawords'}, $usageTotals{$row->{'Username'}}{'TotalOutput'} = ceil($row->{'AcctOutputGigawords'} * 4096);
OutputOctets => $usageTotals->{'AcctOutputOctets'}, }
OutputGigawords => $usageTotals->{'AcctOutputGigawords'} }
};
# Increase size
$index++;
} }
# Begin transaction # Begin transaction
DBBegin(); DBBegin();
# Update totals for last month # Delete duplicate records
if ($index > 0) { my @dbDoParams;
@dbDoParams = ('
DELETE FROM
@TP@accounting_summary
WHERE
PeriodKey = ?',
$lastMonth
);
if ($sth) {
# Do query
$sth = DBDo(@dbDoParams);
}
# Delete duplicate records # Loop through users and insert totals
my @dbDoParams; foreach my $username (keys %usageTotals) {
@dbDoParams = (' @dbDoParams = ('
DELETE FROM INSERT INTO
@TP@accounting_summary @TP@accounting_summary
WHERE (
PeriodKey = ?', Username,
$lastMonth->ymd PeriodKey,
TotalSessionTime,
TotalInput,
TotalOutput
)
VALUES
(?,?,?,?,?)
',
$username,
$lastMonth,
$usageTotals{$username}{'TotalSessionTime'},
$usageTotals{$username}{'TotalInput'},
$usageTotals{$username}{'TotalOutput'}
); );
if ($sth) { if ($sth) {
# Do query # Do query
$sth = DBDo(@dbDoParams); $sth = DBDo(@dbDoParams);
} }
my @insertArray;
for (my $i = 0; $i < $index; $i++) {
# Check if this record exists
my $sth = DBSelect('
SELECT
COUNT(*) as rowCount
FROM
@TP@accounting
WHERE
PeriodKey = ?
AND Username = ?
',
$allRecords[$i]->{'PeriodKey'},
$allRecords[$i]->{'Username'}
);
if (!$sth) {
$server->log(LOG_ERR,"[MOD_ACCOUNTING_SQL] Cleanup => Failed to check for existing record: ".
awitpt::db::dblayer::Error());
return;
}
my $recordCheck = $sth->fetchrow_hashref();
$recordCheck = hashifyLCtoMC(
$recordCheck,
qw(rowCount)
);
if (defined($recordCheck->{'rowCount'}) && $recordCheck->{'rowCount'} > 0) {
@insertArray = (
$allRecords[$i]->{'SessionTime'},
$allRecords[$i]->{'InputOctets'},
$allRecords[$i]->{'InputGigawords'},
$allRecords[$i]->{'OutputOctets'},
$allRecords[$i]->{'OutputGigawords'},
$allRecords[$i]->{'Username'},
$allRecords[$i]->{'PeriodKey'}
);
@dbDoParams = ('
UPDATE
@TP@accounting_summary
SET
AcctSessionTime = ?,
AcctInputOctets = ?,
AcctInputGigawords = ?,
AcctOutputOctets = ?,
AcctOutputGigawords = ?
WHERE
Username = ?
AND PeriodKey = ?
',
@insertArray
);
if ($sth) {
# Do query
$sth = DBDo(@dbDoParams);
}
} else {
@insertArray = (
$allRecords[$i]->{'Username'},
$allRecords[$i]->{'PeriodKey'},
$allRecords[$i]->{'SessionTime'},
$allRecords[$i]->{'InputOctets'},
$allRecords[$i]->{'InputGigawords'},
$allRecords[$i]->{'OutputOctets'},
$allRecords[$i]->{'OutputGigawords'}
);
@dbDoParams = ('
INSERT INTO
@TP@accounting_summary
(
Username,
PeriodKey,
AcctSessionTime,
AcctInputOctets,
AcctInputGigawords,
AcctOutputOctets,
AcctOutputGigawords
)
VALUES
(?,?,?,?,?,?,?)
',
@insertArray
);
if ($sth) {
# Do query
$sth = DBDo(@dbDoParams);
}
}
}
} }
# Rollback with error if failed # Rollback with error if failed
if (!$sth) { if (!$sth) {
DBRollback(); DBRollback();
$server->log(LOG_ERR,"[MOD_ACCOUNTING_SQL] Cleanup => Failed to insert or update accounting record: ". $server->log(LOG_ERR,"[MOD_ACCOUNTING_SQL] Cleanup => Failed to insert accounting summary record: ".
awitpt::db::dblayer::Error()); awitpt::db::dblayer::Error());
return; return;
} }
# Commit if succeeded # Commit if succeeded
DBCommit(); DBCommit();
$server->log(LOG_NOTICE,"[MOD_ACCOUNTING_SQL] Cleanup => Totals have been updated"); $server->log(LOG_NOTICE,"[MOD_ACCOUNTING_SQL] Cleanup => Accounting summary updated");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment