Modul eXTreme Event Persitence (XEP)
a Java

Tento článek navazuje na text, ve kterém jsme se
věnovali Caché eXTreme
– sadě technologií společnosti InterSystems, které
zpřístupňují vlastnosti vysoce výkonné objektové
databáze prostředkům programovacího jazyka Java
k vytváření XTP (eXtreme Transaction Processing)
aplikací.

Caché eXTreme Event Persitence umožňuje pracovat s
projekcí jednoduchých objektů Javy jako
s persistentními událostmi. Architektonicky XEP je
tenká vrstva softwaru sedící na vrchu API eXTreme
Globals, a implementující jednoduché mapování objektů
na globály. Pro samotné používání XEP však znalost
API eXTreme Globals není potřeba.

Jakmile jsou objekty Javy promítnuty do Caché jako
persistentní události, je možné použít XEP
k ukládání, prohledávání, aktualizování a mazání
obrovského objemu dat za velice krátký časový
okamžik.

Jako ilustraci toho, jakého výkonu je schopno XEP
dosáhnout, lze uvést již zmíněný projekt Evropské
kosmické agentury (ESA) nazvaný Gaia, jehož úkolem je
shromažďovat data potřebná pro vytvoření 3-D mapy
naší galaxie. Caché eXTreme má v tomto projektu za
úkol dosáhnout nepřetržitého výkonu minimálně 130 000
insertů za vteřinu na každém serveru. Každý insert je
uložen jako reálný objekt přístupný pomocí SQL.

Kromě vysokého výkonu při ukládání, podporuje XEP
též filtrování projekcí. To umožňuje ukládat pouze ty
vlastnosti objektů, které je třeba ukládat. Jakmile
jsou data jednou uložena, je možné je současně
indexovat pro rychlejší vyhledávání. Uložené události
jsou okamžitě k dispozici pro dotazovací jazyk SQL a
pro další zpracování.

Klíčovým pojmem v XEP je pojem „persistentní
událost“
. Jedná se o projekci objektů Javy na
persistentní třídy Caché, které lze extrémně rychle
uložit a vyvolat zpět do paměti. Úložiště v Caché je
nakonfigurováno zcela automaticky, takže data jsou
k dispozici všemi prostředky, které Caché podporuje,
tj. jako objekty pomocí SQL či přímo jako globály.

cache2_1

Dalším důležitým pojmem je „schéma XEP“.
Schéma definuje, jakým způsobem je datová struktura,
která je definovaná v Javě, mapována na persistentní
událost v Caché. Schéma může mapovat data z Javy do
Caché buď jako tzv. „ploché schéma“ nebo
jako tzv. „plné schéma“.

Standardním modelem mapování je „ploché
schéma“
, ve kterém všechny referencované
objekty jsou serializovány jako součást importované
třídy, a všechny vlastnosti poděděné od rodičů jsou
serializovány, jako kdyby byly nativní součástí
importované třídy. Toto je nejrychlejší a
nejefektivnější způsob serializace, avšak neuchovává
veškeré informace o originální struktuře původního
javovského vzoru. Pokud je potřeba zachovat při
serializaci událostí veškeré informace o datové
struktuře a vzájemné provázanosti všech zdrojových
tříd Javy, je nutné mapovat data z Javy do Caché
pomocí „plného schématu“.

Jakmile je schéma naimportováno, je možné použít
XEP k ukládání, dotazování, aktualizaci a mazaní dat
v extrémně krátkých časech. V případě použití
„plochého schématu“ je možné též asynchronně
aktualizovat indexy, optimalizující SQL dotazování.
V okamžiku, kdy jsou data uložena, jsou k dispozici
jak pomocí SQL, objektového přístupu nebo pro přímý
přístup pomocí globálů.

Celé API rozhraní XEP je uloženo v balíčku „com.intersys.xep“ a je implementováno pomocí
následujících tříd a rozhraní:

  • EventPersiter: hlavní vstupní
    bod modulu XEP.
  • Event: poskytuje metody pro
    ukládání, mazání, vytváření dotazů, indexů atd.
  • EventQuery: vykonává dotazy
    nad množinou událostí uložených v databázi.
  • EventQueryIterator:
    implemetace rozhraní „java.util.iterator“.

Níže uvedené programy mají za úkol ve zjednodušené
formě demonstrovat klíčové vlastnosti modulu XEP, tj.
uložení několika jednoduchých událostí do databáze a
jejich následné vyvolání.

Program StoreEvents vytvoří instanci
třídy EventPersiter, která se připojí
k danému jmennému prostoru v Caché. Pak se
naimportuje schéma pro třídu „SingleStringSample“ a
inicializuje se databáze vymazáním všech dat
v databázi. Instance třídy „Event“ pak
uloží pole objektů typu „SingleStringSample“ do databáze jako persistentní události, poté se
ukončí spojení s databází.

Program StoreEvents:

 

import
com.intersys.xep.*;


import xep.samples.SingleStringSample;

public class
StoreEvents {




private static String className =
"xep.samples.SingleStringSample";


private static SingleStringSample[] eventData =
SingleStringSample.generateSampleData(12);

// vytvori se
vzorek dat

public static
void main(String[] args) {

for (int i=0; i
< eventData.length; i++) {

eventData[i].name = "String event " + i;

}

try {

System.out.println("Connecting and importing schema
for " + className);


EventPersister myPersister =
PersisterFactory.createPersister();





// prihlasovaci udaje k databazi


myPersister.connect("User","_SYSTEM","sys");





try{

// vymaze
puvodni data v databazi a naimportuje schema


myPersister.deleteExtent(className);


myPersister.importSchema(className);

}


catch (XEPException e) { System.out.println("import
failed:\n" + e); }

// vytvori se
instance udalosti


Event newEvent = myPersister.getEvent(className);








// ulozeni pole udalosti


long[] itemIDs = newEvent.store(eventData);





System.out.println("Stored " + itemIDs.length + " of
" + eventData.length + " objects. Closing
connection...");





// ukonceni spojeni


newEvent.close();


myPersister.close();

}


catch (XEPException e) {System.out.println("Event
storage failed:\n" + e);}

} // end
Main()

} // end class
StoreEvents

 

Po kompilaci a spuštění programu je možné se
podívat do úložiště Caché, jakým způsobem jsou
uložena data, viz obrázky níže:

cache2_2

 

cache2_3

Program QueryEvents předpokládá, že bude spouštěn
po běhu programu StoreEvents. Po startu se naváže
nové spojení s databází a vytvoří se instance typu
„EventQuery<>“, která provede dotaz
nad uloženými událostmi. Získaná data se vypíší na
obrazovku.

Program QueryEvents:

 

import
com.intersys.xep.*;


import xep.samples.SingleStringSample;

public class
QueryEvents {

public static
void main(String[] args) {

EventPersister
myPersister = null;


EventQuery<SingleStringSample> myQuery =
null;


try {

// Vytvori
spojeni a vykona SQL dotaz


System.out.println("Connecting to query
SingleStringSample events");


myPersister = PersisterFactory.createPersister();


myPersister.connect("User","_SYSTEM","sys");

try {

Event newEvent
=
myPersister.getEvent("xep.samples.SingleStringSample");


String sql = "SELECT * FROM
xep_samples.SingleStringSample WHERE %ID BETWEEN 3
AND ?";


myQuery = newEvent.createQuery(sql);


newEvent.close();


myQuery.setParameter(1,12); // assign value 12 to SQL
parameter 1


myQuery.execute();

}


catch (XEPException e)
{System.out.println("createQuery failed:\n" +
e);}




// Iteruje se pres ziskany resultset, tisk a mazani
dat


SingleStringSample currentEvent;


currentEvent = myQuery.getNext(null); // bez na první
polozku


while (currentEvent != null) {

System.out.println("Retrieved " +
currentEvent.name);


myQuery.deleteCurrent();


currentEvent = myQuery.getNext(currentEvent); // bez
na další polozku

}


myQuery.close();


myPersister.close();

}


catch (XEPException e)
{System.out.println("QueryEvents failed:\n" +
e);}

} // end
Main()

} // end class
QueryEvents

 

cache2_4

 

Jak již bylo výše uvedeno, dříve než může být
instance javovské třídy uložena jako persistentní
událost, musí být naimportováno odpovídající schéma.
Toto schéma definuje strukturu, do které budou
ukládána data. V mnoha případech je možné importovat
schéma bez dalších doplňujících informací. Pokud
vznikne potřeba podrobněji definovat, jaká struktura
má být na straně Caché použita, je možné použít
upřesňující anotace v definici javovské třídy.
Použitelné anotace a jejich použití jsou popsané
v dokumentaci XEP.

Standardně XEP importuje schéma, které odkazované
objekty „zploští“. Jinými slovy to znamená, že toto
ploché schéma neuchovává na straně Caché informace o
tom, co a jak bylo od koho získáno pomocí dědění.
Níže uvedený jednoduchý příklad názorně ilustruje
celý proces mapovaní.

Uvažujme tři javovské třídy A, B, C:

 

class A {

String a;

}

class B extends
class A {

String b;

}

class C extends
class B {

String c;

}

 

Instance třídy C bude v Caché reprezentována
v případě „plochého schématu“ mapována na instanci
reprezentovanou v Caché třídou:

 

Class C Extends
%Persistent ... {

Property a As
%String;


Property b As %String;


Property c As %String;

}

 

Celý popis toho, jak se XEP chová při použití „plného schématu“ zde není možné probírat, ale
můžete se s ním seznámit v dokumentaci.



Závěr


Článek si kladl za úkol seznámit v krátkosti
čtenáře s možnostmi frameworku Caché eXTreme. Tyto
technologie jsou určeny pro vývojáře v Javě, kteří
chtějí využít bohatou škálu vlastností a omračující
výkonnost, kterou Caché nabízí. Z důvodu rozsahu
nebylo možné podrobně probrat všechny vlastnosti
Caché eXTreme a ani probrat komplikovanější příklady,
které jsou součástí instalace produktu. Pokud
některého ze čtenářů článek alespoň trochu zaujal,
může si ze stránek InterSystems stáhnout volně
dostupný instalační kit Caché a po nainstalování si
vše vyzkoušet.