INTRODUZIONE Xindice Apache Xindice è un database progettato per memorizzare dati in formato XML, o meglio un database nativo XML, ed è sviluppato in Java. Marco Buzzoni INTRODUZIONE (1) Il vantaggio di una soluzione nativa è che non occorre preoccuparsi di mappare l'XML in qualche altra struttura dati. I dati vengono inseriti e recuperati in formato XML. Si ha anche molta flessibilità con la natura semi-strutturata di XML e il modello indipendente di Xindice, e ciò si può riscontrare quando si hanno strutture XML complesse che sarebbe difficile o impossibile mappare in un singolo database. LINGUAGGI SUPPORTATI Al momento Xindice usa XPath come linguaggio per le query e XUpdate per gli aggiornamenti, ovvero rende possibile la modifica di dati in un documento XML. ARCHITETTURA Durante l'esecuzione, una istanza del programma deve memorizzare un certo numero di dati: ● Gerarchia delle collezzioni ● Informazzioni sulla connessione del client ● Vari oggetti in cache Una collezzione è un insieme di documenti XML e può contenere a sua volta collezioni per formare una gerarchia. La radice, chiamata anche Database, è speciale perchè: ● Non ha parenti ● Contiene solo collezioni figlie, non documenti XML MEMORIZZAZIONE DEI DATI I dati XML contenuti nei documenti XML di una collezione sono memorizzati in un singolo file dati con estensione .tbl (posizionato nella cartella delle collezioni da qualche parte nella cartella radice del database). Una classe speciale Java (chiamata filer) è responsabile di leggere e scrivere i dati XML in questo file .tbl. MEMORIZZAZIONE DEI DATI: PAGED FILES Il paging fornisce un accesso efficiente ad un file ad accesso casuale mappando parti del file (pagine) nella memoria principale. Le pagine hanno lunghezza fissa. Le dimensioni dell'header e delle pagine possono essere modificati nel codice sorgente in: org.apache.core.filer.Pag e MEMORIZZAZIONE DEI DATI: PAGED FILES HEADER MEMORIZZAZIONE DEI DATI: PAGED FILES HEADER (1) ● header size (2 bytes): 4096 (0x1000), la dimensione dell'header. ● page size (4 bytes): set to 4096 (0x00001000), la dimensione di una pagina. ● page count (8 bytes): questo campo non è più usato, è presente solo per ragioni storiche. ● total page count (8 bytes): numero totale di pagine presenti nel file. ● first free page (8 bytes): numero della prima pagina non utilizzata nel file. ● last free page (8 bytes): numero dell'ultima pagina non utilizzata nel file. ● ● page header size (1 byte): dimensione di ogni page header. Il valore standard è 64 (0x40). record count (8 bytes): numero di record memorizzati nel file. MEMORIZZAZIONE DEI DATI: PAGINE E RECORDS Se la lunghezza dei dati di un record sta nello spazio disponibile in una sola pagina, nessun problema. Se invece il record è più grande di una pagina, si usano più pagine collegato tra loro per contenerlo. I puntatori sono negli header delle pagine. MEMORIZZAZIONE DEI DATI: PAGE HEADER Ogni pagina ha un suo header la cui struttura è mostrata sopra. ● ● ● ● ● ● status (1 byte): le pagine nel file sono usate o inutilizzate. key length (2 bytes): le pagine hanno la possibilità di memorizzare una chiave. La lunghezza massima della chiave è impostata a 256 (0x0100). key hash (4 bytes): Quest camp memorizza un valore hash di 32 bit calcolato dalla chiave, per ottimizzare le ricerche. data len (4 bytes): La lunghezza dei dati nella pagina. Se una parte di essa continua in un'altra pagina, questo compo contiene solo la lunghezza della parte di dati di questa pagina. record len (4 bytes): La lunghezza totale dei dati di cui una parte è memorizzata in questa pagina. next page (8 bytes): Il numero di pagina della pagina che contiene i dati seguenti del record di questa pagina. Se questa è l'ultima pagina, il record contiene -1 (0xFFFFFFFF). MEMORIZZAZIONE DEI DATI: B-TREE Xindice implementa B-Trees usando i page file. Ogni nodo del B-Tree è memorizzato in un record contenuto in una o più pagine. MEMORIZZAZIONE DEI DATI: B-TREE PAGED FILE HEADER I 2 campi più significativi sono: ● root node page number (8 bytes): numero di pagina della radice del B-Tree. ● total bytes (8 bytes): la dimensione in byte del file che contiene i nodi del B-Tree e i record dei dati. MEMORIZZAZIONE DEI DATI: B-TREE PAGE HEADER ● ● ● ● status (1 byte): questo campo è usato pper indicare se un record è: o un record usato per memorizzare un nodo intermedio, allora lo stato è 0x01. o un record usato per memorizzare un nodo foglia, allora lo stato è 0x02. o un record usato per memorizzare i dati, allora lo stato è 0x14. val_count (2 bytes): se il record è usato per memorizzare un nodo, questo record contiene il numero di chiavi nel nodo.. created (8 bytes): se il record è usato per memorizzare dati, contiene la data(in formato UNIX long) di memorzzazione. modified (8 bytes): contiene la data dell'ultima modifica, sempre nel caso di memorizzazione di dati. MEMORIZZAZIONE DEI DATI: B-TREE NODE Che si tratti di un nodo intermedio o di un nodo foglia, il nodo viene memorizzato nel modo seguente: ● Le chiavi, che in Xindice sono stringhe utf-8, vengono precedute da 2 byte ciascuna che contengono la lunghezza. ● Subito dopo ci sono i puntatori, che occupano 8 byte ciascuno e sono scritti uno dopo l'altro. XML STORAGE Per ogni documento XML, Xindice calcola il DOM compresso. Esso è un arrey di byte che può essere usato per ricostruire il documento XML completo. Un documento XML è memorizzato come coppia chiave-valore nel B-Tree, dove la chiave è il nome del documento XML e il valore è il DOM calcolato. TAVOLA SIMBOLI Una tavola simboli viene utilizzata per memorizzare i contenuti XML in maniera efficiente. Essa è a sua volta un file XML che associa un numero di 16 bit per ogni copia (Qname, namespace) usata come elemento o attributo in XML per tutti i file in una collezione. TAVOLA SIMBOLI: ESEMPIO Documento XML che sarà aggiunto ad una collezione Xindice: <?xml version="1.0"?> <p:person xmlns:p="http://www.xindice.org/Examples/PersonData" gender="female" xml:lang="fr"> <p:first-name>Susanne</p:first-name> <p:last-name>Carpentier</p:last-name> <p:e-mail active="yes">[email protected]</p:e-mail> </p:person> TAVOLA SIMBOLI: ESEMPIO (1) Quando questo documento è immagazzinato in una collezione vuota, viene creata la seguente tavola simboli: <?xml version="1.0"?> <?xindice-class org.apache.xindice.xml.SymbolTable?> <symbols> <symbol name="p:first-name" nsuri="http://www.xindice.org/Examples/PersonData" id="4" /> <symbol name="p:e-mail" nsuri="http://www.xindice.org/Examples/PersonData" id="6" /> <symbol name="p:last-name" nsuri="http://www.xindice.org/Examples/PersonData" id="5" /> <symbol name="gender" id="2" /> <symbol name="xml:lang" id="3" /> <symbol name="p:person" nsuri="http://www.xindice.org/Examples/PersonData" id="0" /> <symbol name="active" id="7" /> <symbol name="xmlns:p" nsuri="http://www.w3.org/2000/xmlns/" id="1" /> </symbols> DOM COMPRESSO Per generarlo Xindice scorre ricorsivamente il documento costruendo una sequenza di byte per un particolare nodo nella rappresentazione ad albero dell'XML. Questa contiene i dati per i nodi figli, che a loro volta conterranno i dati per i relativi figli, ecc.... QUERY Il compito principale del query engine di Xindice è quello di creare uno o più QueryResolver. Essi sono istanze di una classe java che fornisce un'implementazione di tutte le funzionalità dei linguaggi per query Xpath e Xupdate. L'interfaccia che viene implementata dalle due classi per i linguaggi è situata in org.apache.xindice.core.query.QueryResolver. Come utenti noi potremmo creare altre implementazioni per supportare nuovi linguaggi. QUERY: XPATH Quando una query deve essere valutata, viene scelto un insieme di documenti candidati della collezione. Poi Xpath viene valutato usando le classi Xalan (analizzatore e compilatore per Xpath) con ognuno dei documenti a turno: il documento è caricato in un albero DOM usando il le classi B-Tree filer, e Xpath è valutato con questo albero DOM. I risultati di tutte le valutazioni sono aggregati e restituiti. QUERY: XPATH E SCELTA DEI DOCUMENTI CANDIDATI Quando si esegue una query, è possibile specificare quali documenti dovrebbero essere considerati. Se ciò avviene, Xindice userà l'insieme dei candidati ed eseguirà la query su di essi, spostandoli prima in memoria. Se nessun insieme è specificato esplicitamente, Xindice proverà a creare un appropriato indice basato sulla query, il quale fornirà un insieme logico di documenti come candidati. Se non trova neanche un indice appropriato, Xindice ricorre al metodo “brute force”: valuta ogni documento della collezione, leggendolo, convertendolo e cercando i risultati. QUERY: XUPDATE Le query di tipo Xupdate inviano istruzioni di aggiornamento a Xindice. Questo tipo di query consiste in un documento XML che può contenere un numero qualsiasi di istruzioni di update. Come nel caso di Xpath, si ha un query resolver, che prima di tutto compila le query poi può decidere se eseguirle in un secondo momento oppure subito (metodo query()) Per convertire ed eseguire le istruzioni Xupdate, Xindice usa il Lexus Engine. QUERY: XUPDATE E LA SCELTA DEI DOCUMENTI DA AGGIORNARE Nel caso la query sia sottomessa a uno specifico insieme di documenti, le istruzioni di Xupdate sono eseguite su ognuno di essi. Se non vengono specificati documenti, Xindice procede nel modo seguente: ● Per ogni istruzione di modifica, cerca l'espressione di selezione, che conseste in una espressione Xpath per indicare quale nodo del documento deve essere modificato. ● Poi una query Xpath viene eseguita su tutta la collezione, usando il QueryResolver per trovare tutti i nodi che corrispondono alla query nei documenti, e i documenti contenenti questi nodi vengono conservati. Questo passaggio può fare uso di tutti gli indici impostati per Xpath, come determinato nel comportamento della classe QueryResolver di Xpath. ● Le istruzioni di modifica XUpdate sono eseguite su tutti i documenti conservati. QUERY: XUPDATE E L'ESECUZIONE DEGLI AGGIORNAMENTI L'insieme dei documenti è processato come segue: ● Per ogni documento viene creato un albero DOM in memoria usando le classi DOM Compressor e B-Tree filer. ● Lexus aggiorna questa rappresentazione DOM secondo le modifiche ● Xindice riscrive l'intero documento usando le stesse classi. La data di modifica del documento è aggiornata. QUERY: RISULTATI Le query in Xindice restituiscono, sempre dei risultati, e le query Xupdate restituiscono un risultato con una risorsa XML che appare così: <?xml version="1.0"?> <src:modified xmlns:src="http://xml.apache.org/xindice/Query">4</src:modified> Essa indica essenzialmente il numero di aggiornamenti (in questo caso 4) che la query ha eseguito. RISORSE Tutte le informazioni sono reperibili all'indirizzo: http://xml.apache.org/xindice/dev/guide-internals.html