Advertisement
Guest User

Untitled

a guest
Feb 5th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Per 10.83 KB | None | 0 0
  1. use strict;
  2. use 5.010;
  3. use utf8;
  4. use Storable;
  5. use FindBin qw($Bin);
  6. use lib "$Bin/";
  7. use Simple qw(XMLin);
  8. use LWP;
  9. use Data::Dumper;
  10.  
  11. #!Доделать! Что, если парсер в настройках будет только один?
  12. #Доделать. Проверить, как под UNIX работает stat
  13.  
  14. my %result;
  15. my %storage = %{get_storage()};
  16. my $last_time = $storage{last_time};
  17. my %file_times;
  18.  
  19. my @config_settings = @{get_config_settings()};
  20. #my @parsing_parts = @config_settings{parsing_parts};
  21. my @parsing_parts;
  22. my $it_is_win = it_is_win();
  23.  
  24. foreach my $parsing_part (@config_settings) {
  25.    
  26.     my $parser_name = ${$parsing_part}{parser_name};
  27.    
  28.     #Получаем файлы, по маске, заданной в сеттингсах    
  29.     my @parsing_files = glob ${$parsing_part}{path};
  30.    
  31.     foreach my $parsing_file (@parsing_files) {
  32.        
  33.         #Получаем дату изменения файла
  34.         ($file_times{$parsing_file}{mtime}, $file_times{$parsing_file}{ctime}, $file_times{$parsing_file}{inode}) = (stat($parsing_file))[9,10,1];
  35.        
  36.         if ($file_times{$parsing_file}{mtime} > $storage{last_time}) {
  37.             #Если файл изменялся после того, как мы его смотрели в прошлый раз, то тэйлим его.
  38.             parse_file($parsing_file, ${$parsing_part}{property},$parser_name, ${$parsing_part}{arch_path});
  39.         }        
  40.     }
  41. }
  42.  
  43. #Отправим данные куда надо.
  44. #Отладка
  45. END {say qq(i'm fine)}
  46. #SendData();
  47.  
  48. #Сохраним хранимую информацию.
  49. set_storage ();
  50.  
  51. #--------------------------------------------------------------------------------------------------------------------------------------------
  52. #Процедуры и функции
  53. sub get_config_settings {
  54.  
  55.     unless (-e  "$Bin/settings.xml") {
  56.         die "Couldn't find settings file";
  57.     }
  58.    
  59.     my $ref = XML::Simple::XMLin("$Bin/settings.xml");
  60.    
  61.     die "Bad XML in settings" unless ($ref);
  62.    
  63.     #Если нет элемента парсер, значит херня в хмл.
  64.     die "Bad XML in settings. Have not parser element." unless $ref->{parser};
  65.    
  66.     #Если элемент парсер одни, то $ref->{parser} будет хэш, а не массив, исправим это
  67.     if (ref($ref->{parser}) ne "ARRAY") {
  68.         my @parser;
  69.         push @parser, $ref->{parser};
  70.         return \@parser;
  71.     }
  72.    
  73.     $ref->{parser};    
  74. }
  75.  
  76. sub get_storage {
  77.        
  78.     unless (-e  "$Bin/storage") { #Если в директории, из которой запускается скрипт нет темп файла, то создаем его.
  79.         open FILE, " > $Bin/storage" or die "Can't open storage file";
  80.         close FILE or die "Can't save storage file";
  81.        
  82.         my %storage;
  83.         $storage{last_time} = time;
  84.         $storage{viewed_files} = {};
  85.        
  86.         store \%storage, "$Bin/storage";
  87.     }    
  88.    
  89.    retrieve("$Bin/storage");
  90.    
  91. }
  92.  
  93. sub set_storage {
  94.        
  95.         my $old_time = $last_time - 7200;
  96.        
  97.         foreach (keys %{$storage{viewed_files}}) {
  98.             delete $storage{viewed_files}{$_}  if ($file_times{$_}{mtime} < $old_time)
  99.         }
  100.         $storage{last_time} = time;
  101.  
  102.         store \%storage, "$Bin/storage";
  103. }
  104.  
  105. sub parse_file {
  106.       my ($parsing_file, $propertys_ref, $parser_name, $arch_path) = @_;
  107.       my @propertys;
  108.       my $its_new_file;
  109.  
  110.       # Если пропертис одно, то это будет ссылка не на массив, а на хэш, исправим это
  111.       if (ref($propertys_ref) ne "ARRAY"){
  112.         push @propertys, $propertys_ref;
  113.       }
  114.       else {
  115.         @propertys = @{$propertys_ref};
  116.       }    
  117.  
  118.       #Если дата создания файла не совпадает с тем, что у нас до этого было
  119.       #То мы должны дотэйлить предыдуший файл
  120.       #Если это винда, то проверяем изменение даты создания у файла, если это юникс, то айноду
  121.       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'})) {
  122.           my $arch_file = find_rotated_file($parsing_file, $arch_path, $storage{viewed_files}{$parsing_file}{$it_is_win ? 'ctime' : 'inode'}); #Находим архивный файл
  123.           $its_new_file = 1;  #Устанавливаем флаг, того, что файл новый
  124.           #Тэйлим архивный файл.
  125.           tail_file($arch_file, $its_new_file, \@propertys, $parser_name, $storage{viewed_files}{$parsing_file}{label}) if $arch_file;
  126.       }
  127.      
  128.       #Если это обычный файл, то продолжаем тэйлить его.
  129.       tail_file($parsing_file, $its_new_file, \@propertys, $parser_name);
  130.      
  131.  }
  132.  
  133. sub tail_file {
  134.        
  135.       my ($parsing_file, $its_new_file, $propertys_ref, $parser_name, $label) = @_;
  136.       my @propertys = @$propertys_ref;
  137.        
  138.       open(FH, "<", $parsing_file) or warn "Can't open $parsing_file: $!";
  139.      
  140.       #если label заполнен, то значит мы дотейливаем архивный файл.
  141.       if ($label) {
  142.           seek FH, $label, 0;
  143.       } #Проверяем, парсили ли мы этот файл раньше.          
  144.       elsif (exists $storage{viewed_files}{$parsing_file}{label}) {
  145.          
  146.           my $position = $storage{viewed_files}{$parsing_file}{label};
  147.          
  148.           #Устанавливаем указатель на то место, где остановились в прошлый раз, если это не новый файл.
  149.           seek FH, $position, 0 unless ($its_new_file);      
  150.       }
  151.      
  152.       my $last_str;
  153.       while (<FH>) {
  154.           #Поочередно проверяем считанную строку на наличие в нем нужных нам вещей
  155.           foreach my $property (@propertys) {
  156.               my $expression =  $$property{expression};
  157.               $result{$parser_name}{$$property{count_name}}++ if /$expression/;
  158.               $last_str = $_;
  159.           }
  160.       }
  161.       #Если в последней строчке нашли какие-то совпадения, то удалим их, так как в следующий раз будем начинать с начала строчки.
  162.       foreach my $property (@propertys) {
  163.               my $expression =  $$property{expression};
  164.               $result{$parser_name}{$$property{count_name}}-- if $last_str =~ /$expression/;
  165.           }
  166.      
  167.       #Если это не архивный файл, тогда записываем его метку и дату создания файла.
  168.       unless ($label) {
  169.          my $auxiliary_label = tell FH;
  170.          #Смещаем указатель на начало строки.
  171.          {   use bytes;
  172.              $auxiliary_label-= length($last_str)}
  173.          $storage{viewed_files}{$parsing_file}{label} = $auxiliary_label;
  174.          $storage{viewed_files}{$parsing_file}{ctime} = $file_times{$parsing_file}{ctime};
  175.          $storage{viewed_files}{$parsing_file}{inode} = $file_times{$parsing_file}{inode};
  176.       }
  177. }
  178.  
  179. sub find_rotated_file {
  180.    
  181.     my ($parsing_file, $arch_path, $parsing_file_id) = @_;
  182.    
  183.     warn "Can't find archive in settings for $parsing_file" && return undef unless ($arch_path);
  184.    
  185.     $arch_path = prepare_arch_path($arch_path);    
  186.     my @arch_files = glob $arch_path."";
  187.     foreach my $arch_file (@arch_files) {
  188.         #Если это винда, то проверяем дату создания файла, если это юникс, то проверяем айноду    Если это винда, то надо проверить помимо совпадения даты создания, входит ли в название архивного файла наименование исходного файла.
  189.         return $arch_file if (  (stat($arch_file))[$it_is_win ? 10 : 1] == $parsing_file_id  && (!$it_is_win || files_match($arch_file,$arch_file))  )
  190.     }
  191.    
  192.     warn "Can't find archive file in $arch_path for $parsing_file";    
  193.     return undef;
  194.    
  195. }
  196.  
  197. sub SendData {
  198.         {
  199.         package MyAgent;
  200.         use base 'LWP::UserAgent';
  201.        
  202.         sub get_basic_credentials {
  203.             my $login = 'qmc_perl';
  204.             my $pass = "qmc_ws321";
  205.        
  206.             return $login, $pass;
  207.         }
  208.         }
  209.        
  210.         my $url = "http://ngx-int.stage.fresh/int/qmc/ws/InputStatistics";
  211.         my $hostname = get_hostname();
  212.         my $string;
  213.         foreach my $parser_name (keys %result) {
  214.                 foreach my $count_name (keys %{$result{$parser_name}}){
  215.                         my $add = qq($hostname.$parser_name.$count_name.$result{$parser_name}{$count_name};);
  216.                         $add =~ s/\s/_/g;
  217.                         $string.= $add;
  218.                 }
  219.         }
  220.         my $verbose = 1;
  221.         my $file_content = <<XML;
  222. <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  223.         <soap:Header/>
  224.         <soap:Body> <m:InputData xmlns:m="http://1c.ru">
  225.         <m:inParam xmlns:xs="http://www.w3.org/2001/XMLSchema"
  226.                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">$string</m:inParam>
  227. </m:InputData></soap:Body>
  228. </soap:Envelope>
  229. XML
  230.  
  231.         my $ua = MyAgent->new;
  232.         my $res = $ua->post($url,
  233.                  Content_Type => 'text/xml; charset=utf-8',
  234.                  SOAPAction   => 'http://1c.ru#InputStatistics:InputData',
  235.                  Content      => $file_content,
  236.         );
  237.         print $res->content if $verbose && !$res->is_success || $verbose == 2;
  238. }
  239.  
  240. # Служебные процедуры и функции
  241. sub get_hostname {
  242.         my $hostname = `hostname`;
  243.         chomp $hostname;
  244.         $hostname =~ s/\..*$//;
  245.         uc $hostname;
  246. }
  247.  
  248. sub prepare_arch_path {
  249.       my $arch_path = shift;
  250.       $arch_path = $arch_path.get_os_separator() if $arch_path =~ /[\/\\].?$/;
  251.       $arch_path = $arch_path."*" if $arch_path =~ /\*$/;
  252.       $arch_path
  253. }
  254.  
  255. sub it_is_win {
  256.         1 if `ver`;
  257. }
  258.  
  259. sub get_os_separator {
  260.     #Доделать, проверить!
  261.         if (my $it_is_win) {
  262.                 '\\'
  263.         }
  264.         else {
  265.                 '/'                
  266.         }
  267. }
  268.  
  269. sub files_match {
  270.     my ($arch_file, $parsing_file) = @_;
  271.     $arch_file =~ /\\(.+)$/;
  272.     my $arch_only_file = $1;
  273.     $parsing_file =~ /\\(.+)$/;
  274.     my $parsing_only_file = $1;
  275.     return 1 if $arch_only_file =~ /$parsing_only_file/;
  276.     0}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement