Blog do projektu Open Source JavaHotel

wtorek, 22 grudnia 2009

Go 64 bit

I decided recently to migrate my test C++ application (based on database flat files and Python interface) to 64 bit world keeping backward 32 bit compatibility and with minimal changes to code avoiding as much as possible branching the code with statements like that:

#ifdef 64BIT
.. something 64 bit specific
#else
.. something 32 bit specific
#endif

I achieved this goal but had to resolve the following problem.

Problem 1 : Code did not compile

#include <algorithm>
using namespace std;

unsigned int w;
.....
  max(w,sizeof(..));

The reason is quite simple, the sizeof operator is now 64 bit (unsigned long) so max template does not compile. In 32 bit version unsigned int and unsigned long are the same types. The solution is to use explicit conversion of one of the compared values.

Another solution could be to create custom MAX template:

template < class T1, class T2 >
T1 MAX( T1 x, T2 y ) {
  if ( x < y ) return y;
  return x;
}

But this solution could cause side effect if y>x - implicit conversion from T2 to T1. So I think that the better is explicit conversion.


Problem 2: Hard test that unsigned long is 4 bytes long.


In one piece was the test that unsigned long is 4 bytes long.

Something like:
config.h
...
#define SIZEOF_LONG 4

and somewhere in the code :

if (sizeof(usigned long) != SIZEOF_LONG) {
   throw error ....
}

The solution was to use (with heavy heart) conditional ifdef directive:

#ifdef BIT64
#define SIZEOF_LONG 8
#else
#define SIZEOF_LONG 4
#endif


 Problem 3: 32/64 file locking.

It took me some time to resolve another issue.

I needed simple mutex mechanism to allow only one process to do some administering task (like indexing common resources first time after installing). There are many synchronization methods available but to keep it as simple as possible I utilized lock mechanism on files.

Code snippet:

bool mutexOp(const std::string &semname,bool lock) {

   // use simple hash function for mapping string to number
   unsigned long no = 0l;
   for (int i=0; semname[i]; i++) no = (17*no) + (semname[i]-32);

   int lockfd;
   // get lockfd of file being used as semaphore

    struct flock fs;
    fs.l_type =  lock ? F_WRLCK : F_UNLCK;
    fs.l_whence = SEEK_SET;
    fs.l_start = no;
    fs.l_len = 1; // lock one byte only

    int res = fcntl( lockfd, F_SETLK, & fs );
    // ...........
    // analize res
}


According to Posix specification it is possible to lock bytes beyond the end of file so it works even having the "semaphore" file of 0 bytes long. But although off_t (type of l_start field) is 64 bit long the fcntl function does not work as expected for number grater than 2 ^ 32. On 32 bit machine unsigned long is 32 bit so hash function is automatically truncated to 32 bit, but on 64 bit it could be greater.
The solution is very simply, just do it yourself.

   unsigned long no = 0l;
   for (int i=0; semname[i]; i++) no = (17*no) + (semname[i]-32);
   no &= 0xffffffff;

Problem 4: Last but not least.

Application uses embedded indexed-sequential (ISAM) data base. One of the data types supported is 'unsigned long' keeping numbers 4 bytes long. 64 bit version should also support this 4 bytes unsigned longs to handle data bases created by 32 bit version. It was the problem I feared the most, it looked for me like an endless chain of fixing, patching, refactoring ... But there is also good news  that solution was very simple.

Application was originally designed that data base field types (int, long, double) could be differ than its counterpart in C++ program. So there is a common point of conversion between stream of bytes read from data base to C++ data types and vice versa and fix was very simple.

void convertStreamOfBytes(int fType, const void *sou, void *dest, bool todb)
{
  switch (fType) {
    case ...

    case ulongfield:
#ifdef BIT64
            if (todb) {
                *reinterpret_cast (dest) = *reinterpret_cast (sou);
            } else {
                *reinterpret_cast (dest) = *reinterpret_cast (sou);
            }
#else
            *reinterpret_cast (dest) = *reinterpret_cast (sou);
#endif
            break;
      case ...
   }
}

And it was all ! The design decision taken a long time ago pays off now !


Conclusion

So finally the goal was achieved. Application is 64 enabled, backward compatibility is kept and only few branchings inside the code.

But it is hard to say what real advantage it gives. The binaries are 10-15% greater. I don't think that it runs faster. Of course, I can address 64-bit space but this application is not memory thirsty. The only real advantage seems that it can be installed and run in pure 64 environment without necessity to install any 32 bit system components (e.g. 32 bit Python).

Welcome 64 bit world.

niedziela, 6 grudnia 2009

Programmer proof

I have been refreshing my math skills for some time. I'm reading on basics, limits of sequential. The limit can be finite, infinite or the sequence does not have a limit at all (is divergent). Sometimes the limit (finite or infinite) is obvious, sometimes it can be obtained by basic calculations, very often more advanced arithmetic should be applied to come to the conclusion.
I'm reading book (in Polish) http://pl.wikipedia.org/wiki/Grigorij_Fichtenholz G.M. Fichtenholz " Rachunek różniczkowy i całkowy"  and have come to the idea that pure math proof can be supported by "programmer proof", the program computing the numbers in the sequence and checking that the numbers are really getting closer to the limit. Of course, don't take "programmer proof" seriously, nothing can be proved that way.  But it can be useful to visualize how the sequence is running, the speed of convergence, or to start guessing on the limit.

Firstly it is necessary to create an architecture to define and run our sequences.

At the beginning let's define abstract class (interface) containing method signatures enabling polymorphic behavior for sequences.  Because very often sequence is defined recursively so more general methods 'getFirst' - 'getNext' are declared instead of 'getNthNumber'. This methods are pure virtual, there is no any defaults. Sometimes two sequences can be run at the same time so also methods for second sequence are declared with empty default definition. To emulate real numbers C++ double type is used.
Because very often recursive sequences use start values so also default constructors for 0, 1 or 2 start numbers are defined. Concrete sequence can also define custom constructor. Default constructors only set some const numbers at the beginning, it is up to concrete sequence to make use of it.

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/seqcommand.h


This sequence interface is enough to create a simple sequence runner, the first draft of this runner simply goes 'N' times through sequence and prints results. Interface loaded with concrete sequence instance is an example of command pattern, it contains all data and methods sufficient to do task any time. Having parameters as const makes sure that we can come to initial state of the sequence every time.
Sequence runner contains one method to visualize (here to print) first N numbers in sequence. One can imagine more sophisticated visualizing method (e.g. graphic) or more complicated running algorithms e.g sampling sequence in intervals. Also some behavior of the sequence can be analyzed - e.g. how fast sequence is getting closer to its limit.

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/seqengine.h

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/seqengine.cpp

Because every sequence mimics the same interface factory design pattern proved to be very useful. This way the user should know the name of the sequence and initializing method (starting parameters). Factory produces proper sequence instance, the implementation is deeply hidden and not visible outside.

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/seqcommandfactory.h

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/seqcommandfactory.cpp

All sequences implemented so far are define here.

http://code.google.com/p/javahotel/source/browse/trunk/examples/#examples/sequence/sequences

The implementation is very simple, it is enough to keep all concrete methods inlined in header file.

Very high isolation level was achieved. Sequence runner can run through sequence using polymorphic behavior, does not have any access to implementation. Only sequence factory can create concrete sequence. The user can only create sequence by its name and run it using sequence runner.


Finally our architecture looks as follows.
Sequence command and sequence runner.



Sequence command and sequence factory.


And finally how client brings and binds them all:




Now look at several sequences:

Very simple sequence:









http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seqharmcommand.h

That's obvious that the limit of this sequence is 0.

 Output

And it works ! This sequence really is getting close to 0.

Now more complicated sequence: (Fichtenholz, page 60)
http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seqfih60.h
Assume : 0 < c < 1
and define sequence:






The limit of this sequence is 1.

This sequence is approaching its limit very fast


Next sequence - arithmetic mean of two numbers.

(Fichtenholz - page 40)








http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seq23command.h

The limit is equal to:





Output

Next sequence - Fihtenholz page 62

Take number a and define a sequence:









http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seqc2.h

That's very interesting example of sequence, although the limit (if exists) is the same but the proof is different for different a.

For 0< a <=1  it can  be proved quite easily that limit is equal:





Output

For -3<=a<0 the limit is the same but the proof is more complicated because the sequence is not monotonic. It is monotonic for odd and even elements in the sequence.

Output

For a<-3 and a>1 the sequence is divergent, does not a limit at all. Example output for a = -3.1

Output

Next sequence - Fihtenholz page 60

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seqpower2.h

Sequence:


Assume 0<1






The limit of this sequence is 0.

Output

But this sequence is reluctant to achieve it's limit, milion object is still:

1000000 : 0.0005

Next sequence - Fihtenholz page 61

It is an example of two sequences running at the same pace. The first is arithmetic mean and the second harmonic mean of two numbers.

http://code.google.com/p/javahotel/source/browse/trunk/examples/sequence/sequences/seqavharm.h

Assume a>0 and b>0





The limit of this two sequences is the same and it is simply geometric mean of starting parameters:






Both sequences are getting close to the limit very fast.

Output

poniedziałek, 16 listopada 2009

Byliśmy na koncercie

Byliśmy na koncercie muzyki kameralnej 13 listopada 2009 roku.

http://www.zamek-krolewski.pl/?page=2063

Joseph Haydn – jego wczesna muzyka kameralna w kontekście epoki.

Wykonawcą był wiedeński zespół
Ensemble mvsica riservata. założony w 1997 roku i specjalizujący się w wykonywaniu muzyki z okresu 1600-1850 na intrumentach historycznych.

Na koncert złożyła sie muzyka kameralna Haydna oraz trzech współczesnym mu kompozytorów.
Matthiasa Georga Monna, Johanna Georga Zechnera oraz Johanna Georga Albrechtsbergera. Byli to kompozytorzy w swoim czasie cenieni i poważani (Albrechtsberger był nauczycielem Bethovena) ale dzisiaj zapomniani, ich muzyka albo spoczywa pokryta kurzem w archiwach, albo jest przypominana bardzo sporadycznie. Oczywiście bardzo trudno po jednym posłuchaniu stwierdzić, czy jest to muzyka do której warto wracać, ale słucha się z ogromną przyjemnością. Stylistycznie i estetycznie ogromnie przypomina dobrze znane utwory Haydna czy Mozarta, doskonale widać i słychać, że ci sławni kompozytorzy nie wyrośli na muzycznej pustyni, pełnymi garściami czerpali z otaczającego ich muzycznego świata. Czasami trudno zrozumieć, czym rządza gusta słuchaczy, dlaczego muzyka jednych kompozytorów trafia na trwałe do obiegu, zas muzyka innych ginie w archiwach. Suchając na przykład niektórych wczesnych symfonii Mozarta można odnieść wrażenie, ze przyczyną dla której orkiestry po nie sięgaja jest nazwisko kompozytora, a nie szczególne walory muzyczne. Może pech tych kompozytorów polegał na tym, że żyli w Wiedniu, gdzie w tym czasie muzycznych znakomitości byl wręcz nadmiar i dlatego ich muzyka nie zdołała na stałe zaistnieć w uszach słuchaczy.

Głownym bohaterem koncertu byl Haydn, na szczęście reklamy nie potrzebuje, jest to muzyka której się zawsze słucha z przyjemnością. Niezwykle efektownie zwłaszcza zabrzmiało wykonanie:

Divertimento, Hob. III:3 w wersji współczesnej:
Adagio, Menuet / Trio, Scherzo, Menuet / Trio, Finale

Jest to współczesna Haydnowi, nieznanego autorstwa, kompilacja fragmentów z kilku triów Haydna na baryton (instrument smyczkowy) przetransponowana na violę d'amore. Tutaj dodatkowo jeden z głosów był grany na mandorze (odmiana lutni), w sposób niezwykle brawurowy. Dało to efekt rewelacyjny, choćby dla tego wykonania warto bylo przyjść na koncert. Szczególnie wspaniale brzmiało, gdy dźwięki mandory  zbiegały się z glosem pozostałych instrumentów granych pizzolo (poprzez szarpanie strun palcami, a nie przeciąganie smyczkiem).

Miłe było, że w trakcie w przerwy można było porozmawiać z muzykami. Deborah Ullreich grająca na violi d'amore pokazywała i opowiadała o instrumencie. Jest ciekawostką, że nazwa instrumentu nie musi pochodzić koniecznie od tego, co jest pierwszym skojarzeniem. Moze także znaczyć: viol de more (włoskie Moro - Maur, Arab) lub de mare (włoskie mare - morze), pochodzące zza morza, z rejonu Bliskiego Wschodu. Widać więc tutaj wkład świata arabskiego do kultury europejskiego baroku. Cechą instrumentu jest drugi zestaw strun rozpiętych pod pierwszymi, melodycznymi. Są wprawianie w drganie rezonansowe podczas grania, efektem jest charakterystyczne brzmienie instrumentu. Pewnym problemem jest to, że instrument wymaga częstego strojenia, stąd przed każdym wykonaniem kolejnego utworu miało miejsce kazdorazowe zestrajanie się całego zespołu.

Gdy powiedziałem założycielowi zespołu Rainerowi Ullreichowi, że ogromnie mi sie podobalo wykonanie Divertimenta i bardzo chętnie bym usłyszał jeszcze raz, ten żartobliwie odpowiedział, że z tego niekoniecznie byłby zadowolony grający na mandorze Pietro Prosser. Wykonanie tego utworu jest związane z ogromnym dla niego wysiłkiem, musi cały czas przebiegać palcami obydwu dłoni po strunach, podczas gdy pozostali muzycy, jak to żartobliwie określił Rainer, spokojnie przeciągają smyczkami po strunach.

Program koncertu mocno przekroczył  ponad to, co było zapowiadane w programie, na pewno wszyscy słuchacze byli zadowoleni.

Dziwne było tylko słabe rozreklamowanie koncertu, odnieśliśmy wrażenie, że w kościele poza członkami organizatora koncertu, Oddzialu Warszawskiego Polskiego Towarzystwa Muzyki Dawnej było niewiele osób. A wielka szkoda, bo usłyszeć w Warszawie tak ciekawie ułożony koncert w tak dobrym wykonaniu to naprawdę wielka i rzadka okazja.

czwartek, 12 listopada 2009

Josephus problem

http://en.wikipedia.org/wiki/Josephus_problem

This problem is also described in detail in Chapter 1.3
http://en.wikipedia.org/wiki/Concrete_Mathematics

Keeping long story short:
If we have N =  2m+l persons than the number of person who survives is 2 * l+ 1 (first person in line has number 1).
It can be proved using induction.
But I decided to create small C++ program to verify it and prove the formula using "programmer proof".

Header:
http://code.google.com/p/javahotel/source/browse/trunk/examples/flavius/runflav.h
extern int CountFlavByExclusion(int no);

extern int CountFlavByFormula(int no)
First method counts "Josephus" number using direct algorithm, the second is using formula.

Implementation (STL std::vector is used) :
http://code.google.com/p/javahotel/source/browse/trunk/examples/flavius/runflav.cpp

Than finally test it ! (boost test framework is used)
http://code.google.com/p/javahotel/source/browse/trunk/examples/flavius/projflav.cpp
Result : !
Running 3 test cases...

*** No errors detected

Press Enter to continue!

środa, 11 listopada 2009

Podcast organizer

http://code.google.com/p/podcastorganizer/

I have been using this solution for ages and decided to share it as open source. It contains some scripts and simple java app to copy podcasts to mp3 player.

czwartek, 5 listopada 2009

Equivalence class and linear subspace

(Białynicki-Birula, Algebra liniowa z geometrią, str 55)

Assume that we have a linear space Z33 and let V be a set of three vectors: {(0,0,0),(1,0,1), (2,0,2)} .

Prove that:
1) V is a linear subspace of Z33
2) There are exactly 9 equivalence classes of V.

Explanation:
Z3 is a set {0, 1, 2} having operations defined in the set of integers modulo 3. Z3 is a field.

Z33 is a set of all 3-tuples (ordered) of Z3. Examples: (1,1,2), (0,1,2) etc. Z33 is a linear space over Z3.

Equivalence class: http://en.wikipedia.org/wiki/Quotient_space_(linear_algebra)

Proof:

It is very easy to prove 1).

Let's look at 2).

Equivalence class (Polish: warstwa) is a set of all vectors being the sum of any vector of Z33 minus V and all vectors belonging to V.
Example:
Consider the vector (1,0,0). The equivalence class defined by this vector (tuple) is: {(1,0,0), (2,0,1), (0,0,2)}.
Every equivalence class is defined by a vector (tuple). So what we have to do is to find the minimal set E (subset of Z33) that every vector of Z33 is the sum of one vector of E and one vector of V.

Let Z1 be a set of all vectors (a,b,c) where a != c. Forget for a moment about b.

Let V1 be a set {(0,0), (1,1), (2,2)}. It is clear that every vector (a,c) is the sum of one of the vector of V1 and (0,1) or (0,2).
For instance:
(2,0) = (2,2) + (0,1) (modulo 3 arithmetic) (0,2) = (0,0) + (0,2) etc.
So, with respect to b, we have a set E1 of six vectors = { (0,0,1),(0,0,2),(0,1,1),(0,1,2),(0,2,1),(0,2,2)} and it defines all vectors of Z1.

Let Z2 be a set of vectors (a,b,c) where a=c and vector does not belong to V . It is clear that a set E2 of three vector = { (0,1,0), (0,2,0), (2,0,2) } is enough to define every vector belonging to Z2.
For instance:
(2,1,2) = (2,0,2) + (0,1,0)
(1,0,1) = (1,0,1) + (2,0,2)
So set E = E1 + E2 (containing 9 vectors) defines Z1 + Z2.

QAD.

środa, 4 listopada 2009

Byliśmy na koncercie

Imeneo w Warszawskiej Operze Kameralnej

Byliśmy 31 października 2009 roku na przedstawieniu opery Handla "Imeneo" w Warszawskiej Operze Kameralnej. Widzowie jak my, którzy swoją przygodę ze scenicznymi przedstawieniami oper Handla zaczynali od "Giulio Cesare" mogą się czuć trochę rozczarowani. Nie ma tutaj efektownych, wibrujących arii, cała akcja nie jest tak dynamiczna. W "Giulio Cesare" mamy kolejne perypetie bohaterów prowadzące do szczęśliwego zakończenia, zaś tutaj widzimy pogrążone w rozterkach postacie i gorzkie zakończenie. Cały czas czekamy aż tytułowa postać, Imeneo, który dokonał bohaterskiego czynu zabijając piratów i uwalniając porwane siostry, Clomiri i Rosmenę, okaże się dalej równie wielkim bohaterem i wyrzeknie się przysługująych mu praw wyzwoliciela, ale nic takiego nie następuje.
Imeneo jest jedną z ostatnich oper Handla. Poniosła klapę w Londynie w 1740 roku, gdzie zeszła ze sceny po dwóch przedstawieniach, ale potem odniosła sukces na prowincjonalnej scenie w Dublinie, gdzie miała premierę w 1742 roku, zaś potem popadła w otchłań zapomnienia na ponad 200 lat.
Jest to bardzo dojrzałe dzieło Handla, intencją nie było tutaj olśnienie widza, jak w "Giulio Cesare", ale wyrażenie przez muzykę rozterek i niebłahych dylematów głównych bohaterów. Jest to dzieło wymagające uważnego słuchania, dopiero wtedy w pełni się zauważa piękno muzyki, partii wokalnych, jak i intrumentalnych. Orkiestra jest zadziwiająco skromna, partytuaa to dwa oboje, smyczki i klawesynowe basso continuo. Chór, jak przystało na Grecję i Ateny, nie bierze aktywnego udziału w akcji, ale śpiewa moralizatorskie komentarze na temat przebiegu akcji.

Tutułową partię śpiewa Wojciech Gerlach, ale jakoś nie była to rola zapadająca w pamięć. Czegoś tutaj zabrakło, na pewno nie jest to kwestia warszatu czy warunków głosowych, które są bez zarzutu. Zabrakło tutaj pełniejszej identyfikacji czy głębszego przemyślenia samej postaci. W konsekwencji w brawurowej arii "Sorge nell alma mia" (2 akt) śpiewak energicznie stąpa po scenie, wykonuje gwałtowne ruchy rękami i rzuca stanowcze spojrzenia mające pokazywać determinację Imenea w osiągnięciu swojego celu, ale mnie to pozostawiło obojętnym. A szkoda, bo przecież melodię tej arii wykorzystał potem Handel w słynnym Mesjaszu ("Why do the nations"). Inną arię Imenea "Di cieca notte" również znajdziemy w Mesjaszu ("The people that walked in darkness"). Charakterystyczne ponure oktawy, które w Mesjaszu obrazują błądzące w ciemności ludy czekające na światło bijące od Zbawiciela, tutaj mają zniechęcić Tirinta do podtrzymywania swojego uczucia do Rosmeny.

Ale to nie Imeneo jest głównym bohaterem tej opery, jest nią Rosmena i oczywiście Olga Pasiecznik. Rosmena musi dokonać wyboru między uczuciem do Tirinta a wypełnieniem oczekiwania nakazującego spłacenie długu wobec swojego wyzwoliciela, na co naciska ojciec i nawet czuwający nad społecznym porządkiem senat ateński. W tej roli doskonale odnajduje się Olga Pasiecznik posiadająca niezwykłą umiejętność identyfikacji z granymi przez siebie postaciami. Ogromnie mi się podobała piękna aria "Semplicetta, la saetta" (II akt), gdzie Rosmena wyjaśnia swojej młodszej siostrze niebezpieczeństwa miłości. W arii "In mezzo a voi dui", w scenie udawanego utracenia zmysłów, doskonale rozumiemy uczucia bohaterki mającej nadzieję, że ta próba zyskania na czasie ułatwi podjęcie decyzji, W tle pojawia się nawet zjawa z zaświatów, mająca wyobrażać Radamentesa, mitycznej postaci będącej symbolem bezstronności i sprawiedliwości. W końcowym duecie "Per le porte del tormento" śpiewanym razem z Tirinto słyszymy piękny śpiew, który nie niesie pocieszenia odtrąconemu kochankowi, ale dzieli z nim ból.

Z kolei Andrzej Klimczak w roli Argenio jakby nadmiernie utożsamił się z postacią, trochę sztywną i pompatyczną. W konsekwencji artysta, spiewający dźwięczym i brzmiącym basem nie zbierał oklasków, na jakie zasługiwal. Ale mi się ogromnie podobała rytmiczna i efektowna aria "Su l'arena di barbasa scena" z 2 aktu.

Marta Boberska ze swoją delikatną urodą i dźwięcznym, czystym sopranem znakomicie się odnalazła jako naiwna i niewinna Clomiri. Ogromnie mi się podobało wykonanie arii "Aria Se ricordar ten vuoi" z II aktu, gdzie Clomiri wyraża swoją miłość do Imeneo.

Jacka Laszczkowskiego, tutaj występującego jako Tirinto, doskonale pamiętamy z roli Sekstusa w "Giulio Cesare". Ten kontratenorowy śpiewak, posiadający głos o bardzo oryginalnej barwie, wyraźnie się specjalizuje w rolach złamanych bólem, targanych rozterkami postaci. Szczególnie elektryzuje publiczność wysokimi, sopranowymi ariami. Tutaj dobrze wprowadza w nastrój całej opery już pierwsza, melancholijna aria "La mia bella perduta Rosmena", wielkie brawa zebrała efektowna aria "Pieno Il Core Di Timore" z III aktu. W pamięć zapada końcowy duet z Rosmeną, "Per le porte del tormento", nie jest to radosne zakończenie, ale pełne bólu pogodzenie się z losem, nastrój podkreśla delikatna partia skrzypiec.
Jest to wszechstronny artysta, pamiętamy go także z koncertu Bożonarodzeniowego w bazylice na Kawęczynskiej 21 grudnia 2008 roku. W "Magnificat Bacha" bardzo się podobał w duecie "Et misericordia" oraz w arii "Deposuit potentes de sede".

"Imeneo" w Warszawskiej Operze Kameralnej jest na pewno warte obejrzenie i polecenia. Nam się bardzo podobało, chociaż pozostał jednak pewien niedosyt.

czwartek, 29 października 2009

Google and eggs

One of the famous "google puzzle" - questions asked while applying for a job in Google.

There's a 100 stories building, and you have 2 eggs. You need to find out which is the highest story you can throw the egg from, and it will stay intact with the minimal throws possible. If you threw and egg and it did not break, you may throw it again. We assume that egg always breaks when throws from 100th story.

First solution
Simply throw an egg starting from 1th story and go up until egg breaks. In the worst case you need 99 throws.

Second solution
Start from 50th floor than go up (if egg does not break) or down (if breaks). In the worst case you need 50 throws (1+49).

General solution
Take number N  (N > 0 and N < 100) than start throwing the first egg by 100/N, 2 * (100/N), 3* (100/N) until 100 is reached or egg breaks (assume that it is k*(100/N) story). Than take the second egg (or first if still in one piece) and start throwing from (k-1)(100/N).

The number of trials in the worst case is (100/N) -1 + N-2.

The question : what is the minimum of this function ?

Solution, very simple using basic analysis




(derivative) 


The F is minimal when F'(N) is equal 0, so it is minimal for N=10.

Answer
The worst case takes place if the "breaking" store is 100.
So you throw egg starting from 10,20... to 90 (9 trials). Then start 91...98 (8 trials) - it is not necessary to throw egg when 98th store does not break.
The minimum number of throws is 17.

Addition remark.
The worst case takes place when the breaking store is 89.  In this case the number of throws is 16 (8+8). In the case of 99 floor we still have 2 eggs. So we can throw from 93 and 96th floor and go on accordingly using less than 16 throws

So the final answer is: 16 throws.

wtorek, 27 października 2009

Byliśmy na koncercie

VII KONCERT ORGANOWY

Byliśmy na koncercie muzyki organowej dnia 25 października 2009. Po wejściu do kościoła uderza wystrój wnętrza - a ścisle rzecz biorąc, brak takiego wystroju. Gdyby nie krzyż stojący w miejscu, gdzie na ogół jest spodziewany ołtarz, można by odnieść wrażenie, że to synagoga. Ale to co przykuwa uwagę osoby z zewnątrz, jest normalnym widokiem dla wiernych Kościoła Ewangelicko-Reformowanego, inaczej zwanego kalwinizmem. Gdy rozglądałem się po kościele przychodziły mi na myśl lekcje historii z XVI wieku, reforma zapoczątkowana przez Lutra, Kalwina i Zwinglego, konflikty i dysputy z Kościołem Katolickim dotyczące odpustów, kultu świętych, obrazów i rzeżb o treści religinej czy kultu maryjnego. Dysputa aktualna po dziś dzień, ale na szczęście prowadzona w nie tak gwałtowej formie.

Wykonawca muzyki,  Michał Markuszewski, powiedział we wstępnym słowie, że intencją koncertu jest pokazanie organów, niemal automatycznie wiązanych z Bachem i epoką baroku. jako instrumentu służącego do wyrażania bardzo różnorodnej muzyki. Na poczatek usłyszeliśmy więc dwa utwory wchodzące w skład tzw. Gdańskiej Tabulatory Organowej, utwór Bextehudego, mistrza i wielkiego poprzednika Bacha i monumentalną. wypełniającą cały kościół "Fantasia super Komm, Heiliger Geist, BWV651" najsłynniejszego lipskiego organisty.

Potem koncert wypełniły utwory niemieckich kompozytorów romantycznych, muzyka romantyczna rzadko kojarzy się z organami. Lącznikiem był sam Mendelssohn-Bartoldy, który wydobył muzykę Bacha z otchłani zapomnienia i ponownie wprowadził do światowego obiegu muzycznego. Mendelssohna niestety spotkał także trochę podobny los co Bacha. Nieustającymi przebojami są utwory symfoniczne czy koncerty jak. np uwertura do Snu Nocy Letniej, symfonie lub słynny koncert skrzypcowy, ale pozostałą muzykę tego kompozytora rzadko się wykonuje i troche pokryta jest kurzem. Tutaj zostały przypomnianie dwa preludia i fugi - w pierwszej chwili uderzająco podobne do muzyki Bacha, ale jak uważnie posłuchać, to jest oczywiste, że to muzyka całkowicie odmienna.

Dalej mieliśmy muzykę mniej znanych w Polsce kompozytorów, jeden z nich, August Fryer, swoje życie związał z Polską i Warszawą. Były to zarówno utwory potężne i dynamiczne jak "Toccata ze Suity Gotyckiej" Boellmana, subtelna i wyciszona muzyka religijna Augusta Freyera, a także "Romanze" Josepha Rheinbergra.

Utwory wykonane na bis konsekwentnie domykały cały koncert, były to zagrane i stworzone na gorąco improwizacje wykonawcy. Jednym bisem była powolna i spokojna melodia troche przypominająca sentymentalne tematy z holywoodzkich filmów. Drugim bisem była improwizacja oparta na motywie popularnej pieśni kościelnej "Wszystkie nasze dzienne sprawy". Zwłaszcza ten drugi bis jest dobrym podsumowaniem całego koncertu. Pobożna pieśń śpiewana współcześnie przez wiernych na zakończenie wieczornego nabożeństwa, ale autorem jest Franciszek Karpiński. Sam Karpiński jest zaliczany do oświeceniowego nurtu naszej kultury, ale jako autor sentymentamych slelanek jest także zwiastunem romantyzmu. Pieśń jest obecna w tradycji pobożności katolickiej, ale tutaj grana na organach w surowym wnętrzu protestanckiego kościoła. Bardzo dużo różnorodnej treści ujętej w kilkuminutowym, wytworzonym sztuką wykonawczą, organowym utworze.

To samo mozna powiedziec o calym koncercie. Tak naprawdę jedynym czynnikiem łączącym jest tylko sam instrument, poprzez który artyści na przestrzeni wieków i epok wyrażali najróżniejsze intencje i emocje, stosując bardzo róznorodną estetykę.

Cały koncert bardzo nam się podobał, ogromnie załowaliśmy, ze umknęło nam sześć poprzednich koncertów z tego cyklu.

czwartek, 22 października 2009

Singleton without private constructor and static getInstance metod

Create SingletonFactory class. This class is the owner of the one Singleton instance. Add also a static switch "already created" and use this switch in constructor (public) to break the second and next Singleton initialization.

Code snippet below:

singleton.h 
#include <iostream

class Singleton {
public:
  Singleton() {
     if (exists_already) {
        std::cout << "You mustn't do that !" << std::endl;
        // failure action !!!
     }
     else {
       std::cout << "Singleton first init" << std::endl;
       exists_already = true;
     }
  }

  void singleAction() {
     std::cout << "Run single action" << std::endl;
  }

private:
  static bool exists_already;
};

SingleFactory.h
#include <singleton.h>

class SingleFactory {

  public:
    static Singleton *getInstance() {
      return &single;
    }

  private:
    static Singleton single;
};

SingleFactory.cpp
(pay attention that it keeps movables belonging to Singleton class)

#include <singlefactory.h>

Singleton SingleFactory::single;
bool Singleton::exists_already = false;

and finally the usage example
main.cpp

include <iostream>
#include <cstdlib>
#include <singlefactory.h>

using namespace std;

int main(int argc, char *argv[])
{
  Singleton *n = SingleFactory::getInstance();
  cout << "Hello, world!" << endl;
  n->singleAction();
  Singleton *nextS = new Singleton();
  Singleton singleS;


  return EXIT_SUCCESS;
}

wtorek, 20 października 2009

Math exercise and proof

(Michał Krych - Analiza Matematyczna część 1)

Assume that we have N positive numbers and the sum of this numbers is not greater than N.



Prove that multiplication of this numbers is not greater than 1.


Proof                                                                                                        
Assume that all number are equal - obvious.
Assume that not all numbers are equal.

Induction proof.
The statement is satisfied for N=1 - obvious.

Inductive step.
Assume that statement holds true for all 1...N-1
Now consider a set of N positive numbers, call their sum as S(n) and assume that S(n) is less or equal N. Call the product if this numbers as P(n).
Because the numbers are not equal at least one should be greater than 1 and at least one should be less than 1.
Call them a1 = 1 + x and a2 = 1 - y.
Consider set of N-2 number (all numbers except a1 and a2) and call its product as P(n-2) and sum as S(n-2)
Than add to this set the number 1 + x - y. This number is positive and call the sum of this numbers (including 1 + x - y) as S(n-1).

Call the product as P(n-1). Using the induction hypothesis P(n-1) is less or equal 1.

Now let's calculate P(n). Keep in mind that x*y is greater than 0.

Q.E.D

niedziela, 18 października 2009

When to use void* pointer

What is void* pointer in C++ ?
By standard it is a pointer to an object of unknown type ( of course, if not null).
"Unknown" means unknown for one type of users and known to the other type of users, particularly to the owner of this "unknown" type.
An example of usage of void* pointer is a proxy pointer to something which internal structure should be hidden, secret or invisible.

http://code.google.com/p/javahotel/wiki/UseVoidPointer#Top_secret_usage_of_void_pointer

"secretpointer" can point to anything but this way we get off C++ object oriented paradigm.

Another way is to split class declaration into two parts: public and private/hidden. Nothing new, one can say, all the time we can have public and private declarations in a class definition. But the disadvantage of the standard approach is that not only public but also private method and attributes should be exposed in a class declaration. Also every change in a private section involves recompiling the users of this classes. Below is an example of class splited into public and hidden part.

http://code.google.com/p/javahotel/wiki/UseVoidPointer#Partially_secret_class_definition

niedziela, 11 października 2009

Migration to Google App Engine and unit testing.

Summary

This post describes how to migrate existing test cases (JUnit4) to Google App Engine keeping backward compatibility. It extends solution described under link http://code.google.com/intl/pl/appengine/docs/java/howto/unittesting.html. The method described here is about testing in the local environment, it cannot be applied to the production environment.

Introduction

Like the main application it is unlikely to achieve 100% source compatibility while migrating test cases to Google App Engine.  But it does not mean that rewriting the whole test suite is necessary, quite the opposite. With minimal effort it is possible to set up environment where existing test cases can be executed and, what also very important, starting from that point the common test suite can be developed further without bothering about migrating and portability problems.

It is very good programming technique to have server side code separated from the client side and being tested independently. After porting application to Google App Engine further development should cover both frameworks, so keeping common and concise suite of tests plays very important role.

Google App Engine JPA/JDO implementation requires setting up additional environment - how to accomplish it is descibed under link http://code.google.com/intl/pl/appengine/docs/java/howto/unittesting.html. The disadvantage of this solution is that it is specific for Google App Engine, so a naive approach will break backward compatiblity. Additional code should be injected for Google App Engine and not Google App Engine testing but applying an injection framework (like Guice) for very simple and only one task is like using a steam hammer to crack a nut.

Solution description

Details:

http://code.google.com/p/javahotel/wiki/GooglaAppEngineUnitTesting


Addtional remarks.

  • In this example the amount of framework specific code is greater than framework independent code. But the amount of framework specific code is the same regardless of the application size. In real application the common code (data access service and test cases) is  huge and advantages of this approach is more visible.

niedziela, 4 października 2009

Math exercise and proof

Exercise from "Michał Krych, Analiza Matematyczna część 1".



Assume that we have an infinite grid filled with natural numbers. Every number P and four number a,b,c,d in adjacent cells should satisfy the equation 4*P <= a + b + c + d.
Prove that all numbers in grid are equal.






Proof                                                                                                                       

Notice that grid filed with equal numbers holds statement.

Assume that there exists a grid which satisfy equation and have different numbers.

Inductive proof.

Assume that P = 1. It involves that a,b,c,d should be also equal 1 because it is the only way to satisfy equation. The same can be applied for a, b,c d and their adjacent cells and on. So having number 1 in one cell cause all grid being filled with 1. So we have to exclude number 1 from grid.

Assume that all numbers from 1 to N are excluded. Look at the cell with number N+1 and having at least one number different than N+1 in adjacent cell (assume number a). "Different" means greater then N+1 because all number less than N are excluded. But if a > N and b, c and d  >= N then a+b+c+d > N which breaks equation.

That means that all natural number are excluded from the grid and the only grid holding statement must have all number equal.

Byliśmy na koncercie

29 września 2009 rok.

http://www.dkpraga.pl/index.php?option=com_eventlist&view=details&id=90&Itemid=71

Bardzo nam się podobało. Okazało się, że znany koncert organowy Handla bardzo  ładnie brzmi, nawet jeśli orkiestrę stanowi kwartet smyczkowy.Bardzo brawurowo zabrzmiało wykonanie kwartetu smyczkowego Mendelssohna.

W przeciągu godziny koncertu zaprezentowano cały przekrój muzyczny, od wielkich klasyków: Handla, Mendelssohna-Bartholdyego oraz Józefa Haydna aż po muzykę współczesnego kompozytora.

Ale to co było zaletą było także wadą. Za dużo muzyki wtłoczonej w krótki czas powodowało, że niestety nic się specjalnie nie utrwaliło w pamięci. A wielka szkoda, na przykład z wielką przyjemnością byśmy posłuchali dłużej muzyki Jarosława Ciecierskiego (zarazem organisty), ale zanim się na dobre zaczęło juz się skończyło. Gdzieś się zagubiła niestety gra organisty, za wykonanie muzyki Louisa Vierna nie zebrał oklasków. Ponieważ jest to mało znany kompozytor, więc publiczność zapewne nie zorientowała się, kiedy miał miejsce koniec. Na pewno przydałoby się tutaj jakieś wprowadzenie.

To jednak są drobiazgi, była to bardzo miło spędzona godzina.

Innym problem było słabe rozreklamowanie samego koncertu, w kościele naliczyliśmy może 30-40 osób, część z nich to zapewne osoby z parafii zachęcona ogłoszeniami parafialnymi.

Jest to jednak dopiero druga edycja Praskiego Festiwalu Muzyki Kameralnej i Organowej, to wspaniałe, że na bardzo ubogim muzycznym firnamencie Warszawy pojawiła się nowa gwiazda, miejmy nadzieję, że na stałe.

poniedziałek, 14 września 2009

Migration to Google App Engine


Google App Engine for Java (beta version) was released on April 2009. JPA (Java Persistence Api) interface encourages developers to port existing applications to Google clouds. It is possible but does not come cheap.


Introduction


John Keats "Hyperion"
“But cannot I create?   
“Cannot I form? Cannot I fashion forth   
“Another world, another universe,   
“To overbear and crumble this to nought?   
“Where is another chaos? Where?”

Unfortunately, for the time being we cannot form another world from newly found chaos. To avoid being crumbled we have to follow what more mighty discovered and settled.

It is very enticing to migrate to Google clouds and to be near heaven.  JPA implementation promises a lot and makes all process  possible. But it does not come cheap, below I highlight some problems I found during migration OpenSource project (EJB3/JPA) to Google App Engine keeping backward compatibility.

http://code.google.com/p/javahotel/

Problems and solutions

Problem #1


Google App Engine does not support @MappedSuperClass (open issue), also relationships like @ManyToMany could not work as expected (I will handle this problem later). Type 'com.google.appengine.api.datastore.Key' is not supported outside Google App Engine Google App Engine supports only GeneratedValue(strategy = GenerationType.IDENTITY). It means that it is rather unlikely that any no trivial entity classes will move to Google App Engine/JPA smoothly.

Solution:
Creating two different sets of entity classes (data classes), one for Google App Engine/JPA  and the second for non-Google App Engine/JPA. It means redundancy and code duplication but seems much simpler than trying to achieve 100% percent source code compatiblity. But this approach comes with a neccessity to have a different method for setting up a development environment and also two different ways for packaging and deploying the application. It comes also with all problems connected with having duplicated code like any other poor programming technics.

Example:

Google App Engine entity beans:
http://code.google.com/p/javahotel/source/browse/#svn/trunk/javahotel/src/hotelgaenginejpa/com/javahotel/db/hotelbase/jpa

non Google App Engine entity beans:
http://code.google.com/p/javahotel/source/browse/#svn/trunk/javahotel/src/hotelejb3jpa/com/javahotel/db/hotelbase/jpa


Problem #2

EJB3 annotation like @Local, @Remote, @TransacationAttribute are not supported. Also looking up beans through JNDI is not supported.

Solution:
Very simple, just create your own empty declaration. Also some substititution for remote EJB interface looking up should be created.

Example:
Empty EJB3 annotations:
http://code.google.com/p/javahotel/source/browse/#svn/trunk/javahotel/src/emptyejb3

Looking up substitution ("ServiceLocator" pattern proves to be very useful).
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hotellocallogin/com/javahotel/loginhelper/


Problem #3

It is not a Google App Engine limitation but simply it stems from the fact that Google App Engine environment is a clustered environment and also the application itself should be "cloud" aware. In standard J2EE application it is a matter of choice, application can be or cannot be run in clustered environment. In the case of Google App Engine application there is no choice.

Solution:
Application should be analyzed before migration if it is ready to run in the clustered environment. For instance: cannot be assumed that every request is run in the same JVM so any method keeping some data between requests other then datastore should be changed. Statefull beans are not supported and there is also no any substitution to functionality offered by this type of beans. Making application "cloud" aware could be very simple or very complicated if application relies heavily on statefull beans.

There is a very good presentation on "programming in the cloud".
http://www.infoq.com/presentations/programming-cloud-gregor-hohpe


Problem #4

Google App Engine implementation of JPA queries comes with a lot of limitations. It is listed in http://code.google.com/appengine/docs/java/datastore/queriesandindexes.html. Also Google App Engine does not have any SQL engine behind. It means that not onlyJPA createNativeQuery is not supported and does not make any sense but also a lot (and probably the most) JPA/JPQL createQuery will not work as expected.

Solution:
One solution is simply to rewrite all queries, reduce them to the "lowest common denominator" queries supported by Google App Engine and then, by means of multiply queries and filtering in memory, resolve all queries. But, of course, nobody will be happy with this "poor man" policy.
Better approach is to hide all queries behind a facade  then split the code into two parts: one for Google App Engine/JPA and the second for non-Google App Engine/JPA. This way "lowest common denominator" effect could be avoided but it comes with the cost of redundancy and code duplication.
Example:
Query facade Google App Engine/JPA
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hotelgaenginejpa/com/javahotel/db/hotelbase/queries/

Query facade for non Google App Engine/JPA
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hotelejb3jpa/com/javahotel/db/hotelbase/queries/

Another problem connected with Google App Engine/JPA queries.
Programmatic approach (multiply queries and filtering in memory) will work but could be very inefficient. Resolving queries by datastore engine is much more effective. More data should be read through by query, the greater is the difference between datastore engine and in memory filtering. The only solution (suggested by Google App Engine doc) is to break the "normalization" dogma and duplicate some properties. But it means changing the entity classes and the all persistence logic and makes backward compatibility more diffucult.

Problem #5:

Google App Engine comes with a different approach to relationships. Instead of standard terminology based on multiplicity (OneToOne, OneToMany ..) it uses its own terminology: "owned" and "unowned" relationships (http://code.google.com/appengine/docs/java/datastore/relationships.html). , "Owned" relationship is fully supported, "unowned" relationship is not supported at all. There is no simple mapping between relationships based on multiplicity and "owned/unowned", so it is not possible to decide which relationships falls into which category by looking at the definition. It means that porting existing entity classes keeping the same persistence logic could be non trivial.


Solution:
Analyze existing relationships, not only by looking at the annotations attached, but also analyze usage and logic connected with this relationships and decide if this relationships are "owned" or "unowned". "Unowned" relationship are not supported, there is a hint in Google App Engine doc (http://code.google.com/intl/pl/appengine/docs/java/datastore/relationships.html#Unowned_Relationships) "The App Engine implementation of JDO does not yet implement this facility, but don't worry, you can still manage these relationships using Key values in place of instances (or Collections of instances) of your model objects". This problem can be resolved in various ways, some logic should be implemented before persisting and after loading data classes.

Example:

http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hotelgaenginejpa/com/javahotel/db/hotelbase/jpa/RoomStandard.java
Annotation: @KeyObject(keyField = "hotelId", objectField = "hotel")

(Annotation handling)
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hotelgaenginejpa/com/javahotel/db/hotelbase/jpa/AfterBeforeLoadAction.java


Problem #6

Connected with Problem #5. How to avoid spoiling application code with constant adding something like 'beforePersist' or 'afterLoad' in every place where loading or persisting data is performed.

Solution:
Avoid calling JPA directly from application code. Create additional facade and hide core JPA there. This way all "dressing" is added in one module.

Example:

http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hoteldbjpa/com/javahotel/dbjpa/ejb3/JpaEntity.java


Problem #7

Changing to 'strategy=GenerationType.IDENTITY' (the only supported by Google App Engine) could cause problem. It is not Google App Engine limitation, it works as expected. But using  'strategy=GenerationType.IDENTITY'  could mean a problem if your application was banking on sequential or increasing order of keys (GenerationType.SEQUENTIAL).

Solution:
If 'GenerationType.SEQUENTIAL' or 'GenerationType.AUTO' strategy was used before migrating to Google App Engine it is necessary to analize the flow and make sure that no any specific order of keys is assumed. If so, than refactoring is needed before migrating to get rid of this assumption.

Problem #8

Debugging Google App Engine application after deploying to production environment is difficult. Cannot use standard java debugger.

Solution:
Debug and test application in local (development) environment and deploy to production environment only having all tests passed. But sometimes it is not enough and debugging application in production environment is necessary. But the only way is via cycles: adding more logging messages, deploy, run, analyze logs and go to the beginning with the next set of logging messages.

Problem #7

Cannot use query inside transaction. Only specific type of queries could be run inside transaction.

Solution:
Some refactoring is needed. All queries should be placed outside transaction boundaries. It could be easy or complicated, it depends how this query is entangled with partial results of transaction.

Problem #8

Cannot regard Long as a general type for identyfying and retrieving instances of entity classes (data classes). For instance: class being a child in a "owned relationship" should always has a 'Key' type declared as its key. Because sometimes it is necessary passing to and fro identity key between server and client part it could cause a problem. Additionaly, 'Key' type is not supported on client side

Solution:
This problem could be resolved in a different ways. Below is an example.

Example:
Create additional type to pass entity identifier between server and client side and split the code for decoding/coding and retrieving entity class object (data class) into two parts: Google App Engine/JPA and non Google App Engine/JPA.

Additional type.
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/hoteltypes/com/javahotel/types/LId.java

Google App Engine/JPA implementation:
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/#src/hotelgaenginejpa/com/javahotel/db/jtypes

non Google App Engine implementation:
http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/#src/hotelejb3jpa/com/javahotel/db/jtypes

Problem #9

Having an existing suite of EJB3 unit (junit) tests how to run them in Google App Engine. The problem is not Google App Engine limitation, it is a problem similar to: how to test local (not remote) EJB3 interface.

Solution:
This problem can be solved in different ways, below is an example.

Example:
Deploy junit.jar together with the rest of the application and run the tests on the server side. Simple servlet is necessary to start the process. Some simple coding is necessary to evaluate result. The solution implemented is very basic and rough.
Important information: this test "harness" is possible to run only in the local (development) environment. Cannot be run in the production environment in regard of 30 secund limitation per one request.

http://code.google.com/p/javahotel/source/browse/trunk/javahotel/src/gaetest/com/javahotel/javatest/

Another ways to test Google App Engine application
http://code.google.com/appengine/docs/java/howto/unittesting.html

Assuming that client is based on GWT (but keep in mind that it is a bad practice to test application only via UI).
http://code.google.com/intl/pl/webtoolkit/tutorials/1.6/JUnit.html


Problem #10

There is a limitation of 1000 entities returned in one query, also request time cannot be longer than 30 second. It is not a problem for a demo version or for an application that this limitation does not matter. But otherwise could have a significant impact because the application will not work when this limitation is hit.
http://code.google.com/appengine/docs/java/datastore/overview.html#Quotas_and_Limits

Solution.
There is no simple and ready to use solution. Before migrating existing application the analysis is needed if there is a scenario when that limitation could be hit. If so, a redesign and refactoring is needed. It could be simple or very complicated task.

Problem #11

Google App Engine comes with a specific approach to transactions.  Traditionally J2EE applications use  EntityTransaction interface and begin - commit/rollback method to set transaction boundaries (could be managed manually or by a framework). Google App Engine follows the same pattern but inside transaction boundaries only objects belonging to the same "entity group" could be manipulated. The first object touched defines the whole "entity group".

Entity group: http://code.google.com/appengine/docs/java/datastore/transactions.html#Entity_Groups

"Entity group" is defined by a primary key of the object. It means that during designing of the entity classes also transaction logic should be kept in mind. After object is persisted the primary key cannot be changed later. 
Also "optimistic" approach is used. Two (or more) competing requests are not hanged on "commit" method but less successful throws exception inside transaction and should have rescue plan on its own (for instance: retry transaction).

Solution:
There is no simple and ready to use solution or any obvious rule of thumb. It is unlikely that existing transactions will run successfully after migrating to Google App Engine. A thorough analysis of existing transaction managing code is necessary and changes applied. It could be simple or very difficult, not only breaking existing multi-record transactions into smaller, more atomic grouped around entity groups, but it could also involve changes in entity classes and a whole persistence logic.

http://code.google.com/events/io/sessions/DesignDistributedTransactionLayerAppEngine.html



Problem #12

The last but not least.
Google App Engine sandbox comes with a lot of restrictions and limitations.

http://code.google.com/appengine/docs/java/jrewhitelist.html
http://code.google.com/appengine/docs/java/runtime.html#The_Sandbox

Also application can use external tools which are not supported on Google App Engine.

Solution:
There is no any simple solution. Before migration application should be analyzed and refactored (if necessary) to be Google App Engine compatible. The same goes for external tools or jars used. This process could be very simple or very time consuming and complicated or impossible at all.

Summary, some advice on migrating.

Before doing any migration task it is necessary to have a sound understanding of Google App Engine concepts like: "entity groups", "owned relationships". Also well known concepts like "transactions" and "primary keys" are loaded with additional meaning. Spending some time on learning will save much more time in the future.
It is rather unlikely to achieve 100% source compatibility, the better way is to take on a more realistic approach and break "no redundancy" and "no duplication" dogma.

Before migration thorough analysis and "feasibility study" should be performed. The crucial points are:
  • External tool and jar used (Problem #12)
  •  Not being "clustered ready" (Problem #3),
  •  Limitation on query and request time (Problem #10).
  •  Transactions (Problem #11)


Particularly Problem #10 is very important because it could be easily neglected at the beginning of migration process. But neglecting this problem could have devastating effect later. Out of the blue application refuses to work without any workaround available.


Before doing any changes a huge and thorough suite of unit tests should be created (if not done already) and passed. Migration process involves a lot of changes and fixes with a great risk of regression and side effects.

Firstly apply all changes in existing, non-Google App Engine solution, and make sure that existing application still works as expected and no regression was injected. Then start development for the Google App Engine version. After that it is highly probable that again some changes are necessary for the non-Google App Engine solution and this cycle could be repeated several times in a row.

Some general thoughts on Google App Engine for Java.

Google App Engine is not just another J2EE container or another database. So it is unrealistic expectation for Google App Engine to be a better JBoss or a better MySql.

Google App Engine opens a window to Google internal infrastructure for the scalable, clustered application and it is the main advantage incomparable to the other solutions. The purpose of providing JPA/JDO interface is to make this process more easy for Java developers, to make a learning curve less steep.

The Google App Engine JPA/JDO implementation is full of holes but I don't think that the future of Google App Engine for Java is to have JPA or JDO well cooked. It is too much influenced by underlying technology and it is rather unlikely that, even having JPA/JDO full implemented, to forget that it is only a thin abstraction layer on the Big Table.

Google App Engine for Java is at his early childhood, it is an evolving platform. Of course, issues should be resolved and bugs fixed. But the main problem is the lack of good examples, patterns and best practices how to make the best usage of Big Table and advantages it offers: distribution, load balancing, replication. The quality of this solution is tested by millions of users every minute, so how to catch this train ?

Also some lessons should be learned as quick as possible. For instance, it is rather unlikely that migrating any EJB3/JPA application to Google App Engine makes any sense. Not only because of the problems described above, but simply that I cannot imagine any large scale business, database application without effective and general purpose query engine.

niedziela, 30 sierpnia 2009

Wstęp

pl.gif  To jest blog do projektu OpenSource JavaHotel. Celem projektu jest stworzenie na zasadach Open Source - z pełną dostępnością tekstu żródłowego - bezpłatnego programu do zarządzania hotelem, pensjonatem lub innym obiektem turystycznym.

Aplikacja ma być całkowicie bezpłatna, także bez żadnych ukrytych kosztów. Jednak jakość ma nie odbiegać od jakości podobnych produktów dostępnych na zasadach komercyjnych.

Jest to aplikacja webowa, obsługa programu odbywa się poprzez przeglądarkę internetową. Bardziej szczegółowy opis techniczny dostępny jest na stronie domowej projektu.

Aplikacja w obecnym kształcie nie nadaje się jeszcze do zastosowania. Do tej pory rozwiązane zostały problemy techniczne oraz skontruowana część po stronie serwera, tzw "business rules". Do tego jest dodany bardzo zgrubny interfejs.

W tej chwili zastał zaczęty drugi etap prac, bardziej szczegółowe dopracowanie interfejsu użytkownika.

W tym blogu będa opisywanie postępy prac. Dodawane będą także opisy techniczne (w języku angielskim) dotyczące róznych technicznych problemów i rozwiązań napotykanych w trakcie pracy.


flag_uk.gif Introduction

This blog is for JavaHotel OpenSource project. The project aims to create an Open Source - with a full availability of the source text - a free program to manage the hotel, guesthouse or other tourist place.

The application is to be completely free of charge, and without any hidden costs. However, the quality is not to deviate from the quality of similar products available on a commercial basis.

This is a web application, using the program takes place through a web browser. A more detailed technical description is available on the home page of the project.

The application in its current form is not yet ready for use. Until now, technical problems have been solved and created the part on the server side, the so-called "business rules". Also is added a very coarse interface.

Now, the second phase has begun, more detailed and better tuned the user interface.

This blog will describe progress. Also will be added he technical descriptions (in English) on various technical problems and solutions encountered during the working with the project