Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use strict;
- use 5.010;
- use utf8;
- use Storable;
- use FindBin qw($Bin);
- use lib "$Bin/";
- use Simple qw(XMLin);
- use LWP;
- use Data::Dumper;
- #!Доделать! Что, если парсер в настройках будет только один?
- #Доделать. Проверить, как под UNIX работает stat
- my %result;
- my %storage = %{get_storage()};
- my $last_time = $storage{last_time};
- my %file_times;
- my @config_settings = @{get_config_settings()};
- #my @parsing_parts = @config_settings{parsing_parts};
- my @parsing_parts;
- my $it_is_win = it_is_win();
- foreach my $parsing_part (@config_settings) {
- my $parser_name = ${$parsing_part}{parser_name};
- #Получаем файлы, по маске, заданной в сеттингсах
- my @parsing_files = glob ${$parsing_part}{path};
- foreach my $parsing_file (@parsing_files) {
- #Получаем дату изменения файла
- ($file_times{$parsing_file}{mtime}, $file_times{$parsing_file}{ctime}, $file_times{$parsing_file}{inode}) = (stat($parsing_file))[9,10,1];
- if ($file_times{$parsing_file}{mtime} > $storage{last_time}) {
- #Если файл изменялся после того, как мы его смотрели в прошлый раз, то тэйлим его.
- parse_file($parsing_file, ${$parsing_part}{property},$parser_name, ${$parsing_part}{arch_path});
- }
- }
- }
- #Отправим данные куда надо.
- #Отладка
- END {say qq(i'm fine)}
- #SendData();
- #Сохраним хранимую информацию.
- set_storage ();
- #--------------------------------------------------------------------------------------------------------------------------------------------
- #Процедуры и функции
- sub get_config_settings {
- unless (-e "$Bin/settings.xml") {
- die "Couldn't find settings file";
- }
- my $ref = XML::Simple::XMLin("$Bin/settings.xml");
- die "Bad XML in settings" unless ($ref);
- #Если нет элемента парсер, значит херня в хмл.
- die "Bad XML in settings. Have not parser element." unless $ref->{parser};
- #Если элемент парсер одни, то $ref->{parser} будет хэш, а не массив, исправим это
- if (ref($ref->{parser}) ne "ARRAY") {
- my @parser;
- push @parser, $ref->{parser};
- return \@parser;
- }
- $ref->{parser};
- }
- sub get_storage {
- unless (-e "$Bin/storage") { #Если в директории, из которой запускается скрипт нет темп файла, то создаем его.
- open FILE, " > $Bin/storage" or die "Can't open storage file";
- close FILE or die "Can't save storage file";
- my %storage;
- $storage{last_time} = time;
- $storage{viewed_files} = {};
- store \%storage, "$Bin/storage";
- }
- retrieve("$Bin/storage");
- }
- sub set_storage {
- my $old_time = $last_time - 7200;
- foreach (keys %{$storage{viewed_files}}) {
- delete $storage{viewed_files}{$_} if ($file_times{$_}{mtime} < $old_time)
- }
- $storage{last_time} = time;
- store \%storage, "$Bin/storage";
- }
- sub parse_file {
- my ($parsing_file, $propertys_ref, $parser_name, $arch_path) = @_;
- my @propertys;
- my $its_new_file;
- # Если пропертис одно, то это будет ссылка не на массив, а на хэш, исправим это
- if (ref($propertys_ref) ne "ARRAY"){
- push @propertys, $propertys_ref;
- }
- else {
- @propertys = @{$propertys_ref};
- }
- #Если дата создания файла не совпадает с тем, что у нас до этого было
- #То мы должны дотэйлить предыдуший файл
- #Если это винда, то проверяем изменение даты создания у файла, если это юникс, то айноду
- if (exists $storage{viewed_files}{$parsing_file} && ($storage{viewed_files}{$parsing_file}{$it_is_win ? 'ctime' : 'inode'} != $file_times{$parsing_file}{$it_is_win ? 'ctime' : 'inode'})) {
- my $arch_file = find_rotated_file($parsing_file, $arch_path, $storage{viewed_files}{$parsing_file}{$it_is_win ? 'ctime' : 'inode'}); #Находим архивный файл
- $its_new_file = 1; #Устанавливаем флаг, того, что файл новый
- #Тэйлим архивный файл.
- tail_file($arch_file, $its_new_file, \@propertys, $parser_name, $storage{viewed_files}{$parsing_file}{label}) if $arch_file;
- }
- #Если это обычный файл, то продолжаем тэйлить его.
- tail_file($parsing_file, $its_new_file, \@propertys, $parser_name);
- }
- sub tail_file {
- my ($parsing_file, $its_new_file, $propertys_ref, $parser_name, $label) = @_;
- my @propertys = @$propertys_ref;
- open(FH, "<", $parsing_file) or warn "Can't open $parsing_file: $!";
- #если label заполнен, то значит мы дотейливаем архивный файл.
- if ($label) {
- seek FH, $label, 0;
- } #Проверяем, парсили ли мы этот файл раньше.
- elsif (exists $storage{viewed_files}{$parsing_file}{label}) {
- my $position = $storage{viewed_files}{$parsing_file}{label};
- #Устанавливаем указатель на то место, где остановились в прошлый раз, если это не новый файл.
- seek FH, $position, 0 unless ($its_new_file);
- }
- my $last_str;
- while (<FH>) {
- #Поочередно проверяем считанную строку на наличие в нем нужных нам вещей
- foreach my $property (@propertys) {
- my $expression = $$property{expression};
- $result{$parser_name}{$$property{count_name}}++ if /$expression/;
- $last_str = $_;
- }
- }
- #Если в последней строчке нашли какие-то совпадения, то удалим их, так как в следующий раз будем начинать с начала строчки.
- foreach my $property (@propertys) {
- my $expression = $$property{expression};
- $result{$parser_name}{$$property{count_name}}-- if $last_str =~ /$expression/;
- }
- #Если это не архивный файл, тогда записываем его метку и дату создания файла.
- unless ($label) {
- my $auxiliary_label = tell FH;
- #Смещаем указатель на начало строки.
- { use bytes;
- $auxiliary_label-= length($last_str)}
- $storage{viewed_files}{$parsing_file}{label} = $auxiliary_label;
- $storage{viewed_files}{$parsing_file}{ctime} = $file_times{$parsing_file}{ctime};
- $storage{viewed_files}{$parsing_file}{inode} = $file_times{$parsing_file}{inode};
- }
- }
- sub find_rotated_file {
- my ($parsing_file, $arch_path, $parsing_file_id) = @_;
- warn "Can't find archive in settings for $parsing_file" && return undef unless ($arch_path);
- $arch_path = prepare_arch_path($arch_path);
- my @arch_files = glob $arch_path."";
- foreach my $arch_file (@arch_files) {
- #Если это винда, то проверяем дату создания файла, если это юникс, то проверяем айноду Если это винда, то надо проверить помимо совпадения даты создания, входит ли в название архивного файла наименование исходного файла.
- return $arch_file if ( (stat($arch_file))[$it_is_win ? 10 : 1] == $parsing_file_id && (!$it_is_win || files_match($arch_file,$arch_file)) )
- }
- warn "Can't find archive file in $arch_path for $parsing_file";
- return undef;
- }
- sub SendData {
- {
- package MyAgent;
- use base 'LWP::UserAgent';
- sub get_basic_credentials {
- my $login = 'qmc_perl';
- my $pass = "qmc_ws321";
- return $login, $pass;
- }
- }
- my $url = "http://ngx-int.stage.fresh/int/qmc/ws/InputStatistics";
- my $hostname = get_hostname();
- my $string;
- foreach my $parser_name (keys %result) {
- foreach my $count_name (keys %{$result{$parser_name}}){
- my $add = qq($hostname.$parser_name.$count_name.$result{$parser_name}{$count_name};);
- $add =~ s/\s/_/g;
- $string.= $add;
- }
- }
- my $verbose = 1;
- my $file_content = <<XML;
- <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
- <soap:Header/>
- <soap:Body> <m:InputData xmlns:m="http://1c.ru">
- <m:inParam xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">$string</m:inParam>
- </m:InputData></soap:Body>
- </soap:Envelope>
- XML
- my $ua = MyAgent->new;
- my $res = $ua->post($url,
- Content_Type => 'text/xml; charset=utf-8',
- SOAPAction => 'http://1c.ru#InputStatistics:InputData',
- Content => $file_content,
- );
- print $res->content if $verbose && !$res->is_success || $verbose == 2;
- }
- # Служебные процедуры и функции
- sub get_hostname {
- my $hostname = `hostname`;
- chomp $hostname;
- $hostname =~ s/\..*$//;
- uc $hostname;
- }
- sub prepare_arch_path {
- my $arch_path = shift;
- $arch_path = $arch_path.get_os_separator() if $arch_path =~ /[\/\\].?$/;
- $arch_path = $arch_path."*" if $arch_path =~ /\*$/;
- $arch_path
- }
- sub it_is_win {
- 1 if `ver`;
- }
- sub get_os_separator {
- #Доделать, проверить!
- if (my $it_is_win) {
- '\\'
- }
- else {
- '/'
- }
- }
- sub files_match {
- my ($arch_file, $parsing_file) = @_;
- $arch_file =~ /\\(.+)$/;
- my $arch_only_file = $1;
- $parsing_file =~ /\\(.+)$/;
- my $parsing_only_file = $1;
- return 1 if $arch_only_file =~ /$parsing_only_file/;
- 0}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement