
0. Собственно, сама таблица:
1. В Abills/mysql/Ipn_Collector.pm в функции traffic_add_user() в условии добавляется:CREATE TABLE `ipn_traffic_summary` (
`uid` int(10) unsigned NOT NULL,
`traffic_class` smallint(5) unsigned NOT NULL,
`traffic_in` bigint(20) unsigned NOT NULL,
`traffic_out` bigint(20) unsigned NOT NULL,
UNIQUE KEY `ipn_traffic_summary_uniq` (`uid`,`traffic_class`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
2. В traffic_user_get() череда if/elsif/else (до foreach) окружается в if/else:if ($DATA->{INBYTE} + $DATA->{OUTBYTE} > 0) {
....
$self->query($db,
"UPDATE ipn_traffic_summary
SET traffic_in=traffic_in+'$DATA->{INBYTE}', traffic_out=traffic_out+'$DATA->{OUTBYTE}'
WHERE uid='$DATA->{UID}' AND traffic_class='$DATA->{TARFFIC_CLASS}';", 'do');
}
Обратите внимание что изменение полностью обратно-совместимо и не затронуло текущей функциональности: чтобы получить новую ф-ть нужно послать traffic_user_get() аттрибут MONTHLY_TRAFFIC_HACK => 1.if ($attr->{MONTHLY_TRAFFIC_HACK}) {
$self->query($db, "SELECT traffic_class, traffic_in / $CONF->{MB_SIZE}, traffic_out / $CONF->{MB_SIZE}
FROM ipn_traffic_summary
WHERE uid='$uid';");
} else {
череда if/elseif/else что была раньше
}
foreach my $line (@{ $self->{list} }) {
3. В traffic2sql в единственный вызов traffic_user_get() добавляется этот самый аттрибут:
В общем-то все остальное делалось ради этого 3-го шага. Теперь traffic2sql у меня выполняется в 10-15 раз быстрее.my($used_traffic) = $Ipn->traffic_user_get({ UID => $uid, MONTHLY_TRAFFIC_HACK => 1 });
4. В Abills/mysql/Users.pm в функцию добавления нового пользователя add() добавляется в самый конец (разумеется перед return

Это подразумевает, что у вас как и у меня два класса траффика для каждого тарифного плана (0 - инет, 1 - страна). Можете добавить или удалить классы при необходимости - UPDATE, приведенный в 1-м шаге прозрачно подхватит ваши изменения.$self->query($db, "INSERT INTO ipn_traffic_summary (uid, traffic_class)
VALUES ('$self->{UID}',0), ('$self->{UID}',1);", 'do');
5. Накопленный в таблице ipn_traffic_summary трафик нужно в начале очередного учетного периода обнулять. Для этого:
а) в traffic2sql поближе к началу добавляем:
Тем самым узнав текущий час и минуту.my ($hour, $min) = (localtime)[2,1];
б) Теперь объяснить где изменить немножко сложно: в traffic2sql, функции processing(), внутри условия
сразу ПОСЛЕ большого условия while:if ($Ipn->{INTERIM}{$ip}) {
Добавляем:while(my($k, $v)=each %$ip_stats) {
...
}
Важно это добавить внутри if ДО этого else:# XXX this must occur _after_ a "periodic monthly", so that we deal with updated activate date here:
if ($hour == 0 && $min == 1) {
$db->do("UPDATE ipn_traffic_summary t JOIN users u USING (uid)
SET traffic_in=0, traffic_out=0
WHERE activate=DATE_FORMAT(NOW(), '%Y-%m-%d')");
}
С индентацией в файле не очень гладко, но учтя указанные моменты найти несложно.}
#If user Don't have interium traffic
elsif($total_user_sum > 0 && $uid > 0) {
Как сказано в комментарии обнулять нужно строго после periodic monthly. У меня periodic monthly запускается ровно в полночь, а подчистка UPDATE через минуту после него в 00:01 ежедневно. У меня учетный период длится с числа по число (это требует не указанных здесь изменений в Абиллсе), но вполне можно приспособить для тех, у кого с 1-го по 1-е.
Перед началом эксплуатации необходимо мигрировать существующую юзерскую базу. Это тривиально и происходит двумя запросами MySQL 5.1 (для двух классов трафика):
Вот и все! В результате traffic2sql длится 1-2 секунды.begin;
insert into ipn_traffic_summary (uid,traffic_class) (select distinct(uid),0 from users);
insert into ipn_traffic_summary (uid,traffic_class) (select distinct(uid),1 from users);
commit;