Ян. 302009
 

В момента правим тестове за това колко държи ЕСОЕД. Както знаете (от лекцията ми на пролетния семинар на БГПО миналата година), това е част от проекта за електронно правителство. В този проект аз участвам като database експерт – направих дизайна на БД и, по-важно, начините, по които Java приложението ЕСОЕД я достъпва.

Хавата е следната: влизат едни съобщения документи и се записват във входящата опашка. После се обработват на нещо като конвейер – проверяват се разни неща, подписват се, криптират се и т.н; готовите документи отиват в изходящата опашка, от където ги вземат Java процесите, които се занимават с изпращане и ги изпращат. Тук има една тъжна подробност: докато всички предишни обработки могат да стават колкото си искат паралелно, при изпращането трябва да изпращаме само по един документ към всяка система-получател, като този документ е изрично най-стария, т.е. документите се изпращат подредени. Това е един от най-конфликтните моменти, по който сме спорили мнооого дни, защото спъва скалируемостта. Но техническата му реализация е относително проста: има една функция в БД, която се извиква от всеки свободен изпращач. Тази функция намира документ, който:
– е в изходящата опашка, т.е. готов е за изпращане
– не е заключен от друг изпращач
– е най-стария неизпратен документ за тази дестинация, т.е. няма по-стар от него документ за същия получател, в никоя опашка
Щом намери такъв документ, функцията го заключва и връща неговото ID на Java-та, да си се занимава с изпращането.

Цялото това търсене на подходящ документ съм го реализирал с 1 (една!) заявка, която се пада най-тежката заявка в целия ЕСОЕД. И днес се изкефих колко оптимална е тя. В голяма степен заслугата за това е много добре измисления дизайн на БД и на работата с нея, за което претендирам да е моя заслуга.

Та тази заявка, оказа се, е изпълнена 631 147 пъти от последния рестарт на БД до сега, като за това е отнела общо 17 463 906 250 микросекунди процесорно време или общо около 17 960 692 000 микросекунди с включени всички други изчаквания (дискови операции и т.н.). Това е около 0,027670 CPU секунди на изпълнение или 0,028457 секунди по часовник. Пак казвам, това е най-тежката заявка в системата!

А най-красивото е, че при този дизайн, колкото и да се натовари системата (с много съобщения и стари данни), това време няма да скочи значително.

Обичам си професията! 🙂

 Posted by at 18:12
Ян. 302009
 

Реших да понауча малко Perl. Всички го хвалят, че бил супер гъвкав език. Аз, обаче, не съм програмирал от години (ако не броим по някоя друга процедурка на PL/SQL тук-там). Оказа се, че програмирането като работа не се забравя, но сблъсъка с нов език ме изненада.

Както и да е. Предисторията е следната: тази седмица трябваше да инсталираме един тестов Oracle 10.2 на Linux и в знак на оптимизъм избрах Oracle Unbreakable Linux 4 Update 2 x86_64, защото от Oracle 10.2 на RHEL 5 имам лоши спомени. Интересното тук е архитектурата. Не знам RHEL4 дали се държи по същия начин, но се сблъскахме с един много тъп проблем. Преди инсталацията на Oracle DB, когато слагах всички необходими пакети, rpm започна да се държи странно – обясняваше ми, че един пакет го няма, а rpm -q показваше, че го има. Оказа се, че инсталатора е сложил i386 версията, а на мен ми трябва x86_64 версията. И двете си стоят мирно на инсталационното CD, но инсталера по най-тъпия начин е избрал 32 битовата.

Това го преборихме. Но то ме вдъхнови за първата, може би не много смислена, но ПЪРВА за мен програмка на perl. Реших да изнамеря всички пакети, които са инсталирани, но не и в x86_64 вариант.

Почнах наистина а началото, но с много оптимизъм. Примерно, за да взема името на всеки пакет реших най-оптимистично да се боря с regular exressions – това само по себе си е едно дълбоко море. Започнах така:

#!/usr/bin/env perl

use strict;
use warnings;

#my $s = "world";
#print "Hello, $s\n";
my $pn;
my @in=`rpm -qa`;
chomp @in;

foreach (@in) {
  $pn = $_;
  if ($pn =~ /((\w|-)+)-(\d+[-\.]+[-\w\.]*)/) {
        print "For $pn";
        print ", name is $1";
        print " and version is $3\n";
...

Този regexp сам по себе си е голямо заклинание, обаче колкото и да се мъча, не можах да хвана всички случаи. Най-брадатия пакет се оказа java-1.4.2-gcj-compat-1.4.2.0-27jpp – просто няма (или аз не мога да направя) regexp, който да се справи с отделянето на името от версията. Странното е, че като го погледна и ми става ясно коя част е име и коя – версия; но не мога да формулирам точния алгоритъм, поне в тази нова за мен среда. Като стана дума за среда, използвам просто vim, за по-трудно.

Както и да е. Пробите и грешките бяха много. Пешо помага, Xerxes също удари едно рамо в момент, в който бях забил по много тъп начин. И на края успях да стигна до Първата Работеща Програма на Perl (ПРПП), която съм писал лично аз:

#!/usr/bin/env perl

use strict;
use warnings;

my $Str64 = "x86_64";

sub GetArch {
# This procedure checks if some package's architecture is $Str64
# If thеre is more than one package with the same name
# (and different architectures), it will return $Str64
# If there is no package installation with #Str64 architecture
# it will return the first architecture occured

  # get package name from the parameters
  my $PckName = shift;
  # get installed architectures for the package
  my @PckArchs = `rpm --query --queryformat \"%{ARCH}\n\" $PckName`;
  # init $Result with the first architecture found
  my $Result = $PckArchs[0];
  my $CurrArch;

  # lop through architectures
  foreach (@PckArchs) {
      chomp;
      $CurrArch = $_;
      # Check if the architecture is what we are looking for
      if ($CurrArch eq $Str64)  {
          # Victory!
          $Result = $CurrArch;
          }
      }
  return $Result;
}

my $pn;
# we take all package names
my @in=`rpm -qa --queryformat \"%{NAME}\n\"`;
#sort the package names (will look better)
@in = sort(@in);
# remove the new line character
chomp @in;
my $pa;
my $PckCount = 0;

#loop through the package names
foreach (@in) {
    # take thе current package name
    $pn = $_;
    # get package's architecture
    $pa = GetArch($pn);
    chomp($pa);
    #check if the architecture is fine 
    #(and if thе package has architecture at all)
    if (($pa ne $Str64 ) && ($pa ne "noarch")) {
        # this package is not fine, let's report it
        print "$pn is $pa\n";
        $PckCount++;
    }
}
print "Number of bad packages: $PckCount\n";

Може би може да се направи много по-елегантно, но за ПРПП и това е ОК 🙂

P.S. оказа се че има инсталирани цели 41 такива пакета.

P.P.S. Highlight Source Pro плъгина на WordPress, който си сложих днес, не се справя много блестящо с обратните кавички (`)

P.P.P.S. Оправих си Highlight Source Pro. Във файла wp-content\plugins\highlight-source-pro\geshi\geshi\perl.php на ред 63 вместо
'QUOTEMARKS' => array('"'),
написах
'QUOTEMARKS' => array('"','`'),

 Posted by at 15:58