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.