>Как же провайдеры выставляют счет за трафик который у клиента был в
>позапрошлом месяце если соедиенние продолжалось при переходе на новый месяц?
Да, да. Интересно, как?
В своей реализации системы учета трафика (которую так и не дописал
ввиду того что отпала в ней необходимость) сделал так:
ввел понятие "разрешения" (интервала, с точностью до которого
можно задавать период при выставлении счетов, получении детальной
статистики, с начала которого может начаться расчетный период, ...),
равного 1 суткам.
Для хранения информации о трафике используются 2 таблицы: в одной
хранятся записи о фловах как они есть, в другой - счетчики
пакетов и байтов на определенную дату. Т.е. если флов прожил например
3 суток - во второй таблице будет 3 записи.
Парсер парсит файл нетрамета и заносит данные в первую таблицу,
во второй они формируются автоматически посредством триггеров.
Может быть можно и по-другому как-нибудь...
Ниже приведены определения таблиц и функций (СУБД PostgreSQL):
CREATE TABLE flows (
source_peer_address inet NOT NULL,
dest_peer_address inet NOT NULL,
to_octets bigint NOT NULL,
from_octets bigint NOT NULL,
to_pdus bigint NOT NULL,
from_pdus bigint NOT NULL,
source_trans_address integer NOT NULL,
dest_trans_address integer NOT NULL,
source_trans_type integer NOT NULL,
flow_kind integer NOT NULL,
flow_index integer NOT NULL,
start_time timestamp(2) without time zone NOT NULL,
end_time timestamp(2) without time zone NOT NULL,
flow_ruleset integer NOT NULL,
PRIMARY KEY (flow_index, flow_ruleset, start_time)
);
CREATE TABLE flows_on_days (
flow_index integer NOT NULL,
flow_ruleset integer NOT NULL,
start_time timestamp(2) without time zone NOT NULL,
date date NOT NULL,
to_octets bigint NOT NULL,
from_octets bigint NOT NULL,
to_pdus bigint NOT NULL,
from_pdus bigint NOT NULL,
PRIMARY KEY (flow_index, flow_ruleset, start_time, date),
CONSTRAINT flows_on_days_fkey
FOREIGN KEY (flow_index, flow_ruleset, start_time)
REFERENCES flows (flow_index, flow_ruleset, start_time)
ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TRIGGER flows_insert
AFTER INSERT ON flows
FOR EACH ROW
EXECUTE PROCEDURE flows_insert ();
CREATE TRIGGER flows_update
AFTER UPDATE ON flows
FOR EACH ROW
EXECUTE PROCEDURE flows_update ();
CREATE FUNCTION flows_insert () RETURNS "trigger"
AS '
BEGIN
INSERT INTO flows_on_days
(flow_index, flow_ruleset, start_time, date,
to_octets, from_octets, to_pdus, from_pdus)
VALUES
(NEW.flow_index, NEW.flow_ruleset, NEW.start_time,
date(NEW.end_time),
NEW.to_octets, NEW.from_octets, NEW.to_pdus, NEW.from_pdus);
RETURN NEW;
END;
'
LANGUAGE plpgsql;
CREATE FUNCTION flows_update () RETURNS "trigger"
AS '
BEGIN
UPDATE flows_on_days SET
to_octets = to_octets + NEW.to_octets - OLD.to_octets,
from_octets = from_octets + NEW.from_octets - OLD.from_octets,
to_pdus = to_pdus + NEW.to_pdus - OLD.to_pdus,
from_pdus = from_pdus + NEW.from_pdus - OLD.from_pdus
WHERE flow_index = NEW.flow_index
AND flow_ruleset = NEW.flow_ruleset
AND start_time = NEW.start_time
AND date = date(NEW.end_time);
IF NOT FOUND THEN
INSERT INTO flows_on_days
(flow_index, flow_ruleset, start_time, date,
to_octets, from_octets, to_pdus, from_pdus)
VALUES
(NEW.flow_index, NEW.flow_ruleset, NEW.start_time,
date(NEW.end_time),
NEW.to_octets - OLD.to_octets,
NEW.from_octets - OLD.from_octets,
NEW.to_pdus - OLD.to_pdus,
NEW.from_pdus - OLD.from_pdus);
END IF;
RETURN NEW;
END;
'
LANGUAGE plpgsql;