martedì 27 dicembre 2011

Open Street Map - Java - Routing

Ero alla ricerca di un metodo semplice per il calcolo delle distanze km stradali tra un due punti.  Dopo varie ricerche arrivo ad una prima soluzione quella di utilizzare osm2po.

Per fare un test ho scaricato il file del Piemonte di OSM da questa cartella.

Successivamente ho eseguito (dopo aver decompresso il file bz2 e le varie lib osm2po)

java -jar osm2po-core-4.2.30-signed.jar prefix=hh piemonte.osm

dopo varie elaborazioni da questa app ottengo la cartella hh che contiene tutti i dati elaborati per eseguire un navigatore. Sempre seguendo i sample sul sito :

package osmtest;

import de.cm.osm2po.routing.DefaultRouter;
import de.cm.osm2po.routing.Graph;
import de.cm.osm2po.routing.Graph.SegmentHolder;
import de.cm.osm2po.routing.SingleTargetRouter;
import java.io.File;
import java.util.Properties;

public class OsmTest {

    public static void main(String[] args) throws Exception {
        
        File dir = new File("C:\\Documents and Settings\\marco\\Documenti\\Downloads\\hh"); // path to g*.2po Files
        Graph graph = new Graph(dir); // CTOR loads graph into memory
        SingleTargetRouter router = new DefaultRouter(); // Dijkstra with specials

        // via palestro n.8 santhià
        int sourceId = graph.findClosestVertexId(45.367874f, 8.177251f);
        // piazza cavour vercelli
        int targetId = graph.findClosestVertexId(45.2693237f, 8.3586324f);

        // Possible params for DefaultRouter
        Properties params = new Properties();
        params.put("findShortestPath", false);
        params.put("ignoreRestrictions", false);
        params.put("ignoreOneWays", false);
        params.put("heuristicFactor", "1.0"); // 0.0 Dijkstra, 1.0 good A*

        router.traverse(graph, sourceId, targetId, Float.MAX_VALUE, params);
        
        if (router.isVisited(targetId)) { // Found!
            int[] path = router.makePath(targetId);
            float tot_km = 0;
            for (int i = 0; i < path.length; i++) {
                SegmentHolder sh = graph.lookupSegment(path[i]);
                int segId = sh.getConstPart().getId();
                String segName = sh.getVarPart().getName().toString();
                float km = sh.getConstPart().getKm();
                System.out.println(segId + "\t" + segName + "\t" + km);
                tot_km += km;
                
            }
            System.out.println();
            System.out.println("tot km: " + tot_km);
            
        }
        
        graph.close();
    }
}

-- RUNNING --


INFO   Loading Graph from C:\Documents and Settings\marco\Documenti\Downloads\hh
INFO   Loading Vertices from gv_fwd.2po
INFO   92.523 Vertices loaded. - 252.219k
INFO   Loading Coordinates from gc_all.2po
INFO   92.523 Coords loaded. - 251.465k
INFO   Loading Edges from ge_fwd.2po
INFO   249.174 Edges loaded. - 246.669k
INFO   Graph is in memory - 246.754k free
29622 Via Fratelli Cervi 0.043157257
29621 Via Fratelli Cervi 0.056928575
29620 Via Fratelli Cervi 0.14821757
29619 Via Fratelli Cervi 0.013569439
26519 Via Tagliamento 0.0052738246
51988 Via Tagliamento 0.02373628
25153 Corso 25 Aprile 0.009190599
51981 Corso 25 Aprile 0.03348493
54642 Corso 25 Aprile 0.06539526
27074 Corso 25 Aprile 0.34717533
54771 Corso 25 Aprile 0.050330035
54644 Corso 25 Aprile 0.15120597
54643 Corso 25 Aprile 0.021295577
27073 Corso 25 Aprile 0.20046103
34253 Corso 25 Aprile 0.025631124
34252 Corso 25 Aprile 0.017132074
34251 Corso 25 Aprile 0.015333741
34250 Corso 25 Aprile 0.13944228
50410 Corso Vercelli 0.13845648
34254 Corso Vercelli 2.1409712
40898 Strada Provinciale 143 Vercellese 1.6996256
40897 Strada Provinciale 143 Vercellese 0.073485486
26505 Strada Provinciale 143 Vercellese 0.027207151
26510 Via per Torino 0.010309117
26511 Via per Torino 0.018367754
26512 Via per Torino 0.020955488
46939 Via per Torino 0.050319146
46942 Via per Torino 0.2733953
46943 Via per Torino 0.04208151
46944 Via per Torino 0.09343862
46945 Via per Torino 0.0420112
50046 Corso Giacomo Matteotti 0.0526508
50047 Corso Giacomo Matteotti 0.05815405
50048 Corso Giacomo Matteotti 0.10033821
50049 Corso Giacomo Matteotti 0.112137705
50420 Corso Giacomo Matteotti 0.08796594
50421 Corso Giacomo Matteotti 0.0055127908
50417 Corso Giacomo Matteotti 0.14630358
50413 Corso Giacomo Matteotti 0.015465715
50045 Strada Statale 11 Padana Superiore 0.63335454
50422 Strada Statale 11 Padana Superiore 0.087082945
50415 Strada Statale 11 Padana Superiore 2.1165488
50416 Strada Statale 11 Padana Superiore 1.9363447
50424 Strada Statale 11 Padana Superiore 0.067266665
50425 Strada Statale 11 Padana Superiore 1.5284381
50426 Strada Statale 11 Padana Superiore 0.37070882
50427 Strada Statale 11 Padana Superiore 0.274278
50428 Strada Statale 11 Padana Superiore 0.06099027
50429 Strada Statale 11 Padana Superiore 0.051663306
50430 Strada Statale 11 Padana Superiore 0.09464438
50431 Strada Statale 11 Padana Superiore 0.622247
50432 Strada Statale 11 Padana Superiore 1.9672685
50433 Strada Statale 11 Padana Superiore 0.020940712
50434 Strada Statale 11 Padana Superiore 0.019205108
50435 Strada Statale 11 Padana Superiore 1.1245883
31369 Strada Statale 11 Padana Superiore 0.020982204
27430  0.019469375
31366 Strada Statale 31 del Monferrato 0.041809272
31365 Strada Statale 31 del Monferrato 0.8612228
31371 Strada Statale 31 del Monferrato 0.019620165
27935 SP31 0.06312612
31372 Strada Statale 31 del Monferrato 0.021187807
31374 Strada Statale 31 del Monferrato 0.16272391
50462 Strada Statale 31 del Monferrato 0.005521775
50449 Strada Statale 31 del Monferrato 0.66337603
26054  0.16612104
26531  0.16449298
26529  0.12807508
30301 Via Trino 0.106118426
30300 Via Trino 1.1253898
42838 SS455 0.06568793
25744  0.028293554
25738  0.041163616
42827 SS455 0.049763422
42836 Strada statale Vercelli-Trino 0.14589156
42837 Strada statale Vercelli-Trino 0.047293313
33927 Strada statale Vercelli-Trino 0.3165596
43957 Strada statale Vercelli-Trino 0.056310877
43946 Strada statale Vercelli-Trino 0.3662844
33926 Strada statale Vercelli-Trino 0.3887234
43958 SS455 0.011191902
33042 Strada statale Vercelli-Trino 0.8628093
33043 Strada statale Vercelli-Trino 0.23586215
49910  0.0446586
27271  0.04874075
52907 Via Vercelli 0.030868573
52908 Via Vercelli 0.5514064
52909 Via Vercelli 0.007921268
52910 Via Vercelli 0.041300017
52911 Via Vercelli 0.02520492
52912 Via Vercelli 0.008553665
52913 Via Vercelli 0.06177261
52914 Via Vercelli 0.04884419
52915 Via Vercelli 0.21045697
54341 Corso Marconi 0.23005071
54342 Corso Marconi 0.060422346
54343 Corso Marconi 0.053981215
49908 Piazza Cavour 0.018594721

tot km: 25.179537
tot time execution:468





ottimo i 468 millisecondi il percorso completo, potrebbe essere quello che mi serve.

giovedì 1 dicembre 2011

MongoDB : Doctrine ODM vs. Mandango

MongoDB Doctine ODM:

pro:
  • semplice e intuitivo
  • i field di tipo array si dichiarano in modo semplice
  • possibilità di _id autogenerati negli embed 
  • Nessun problema con Embed dentro embed e Reference dentro ad embed etc.
  • Id generati anche negli embed in modo semplice

contro:
  • definisco gli indici negli object ma questi non vengono effettivamente creati
  • è lento rispetto a Mandango altri ODM
  • E' in Beta
  • E' difficile trovare documentazione.
da capire:

  • Devo capire se la velocità aumenta configurando gli object in xml.
Mandango

pro:

  • Molta velocità rispetto a Doctine
  • con Mandator crea automaticamente i modelli partendo da un array().
  • i modelli base vengono rigenerati quelli che devono essere estesi da noi no. (ottima cosa)
  • una volta presa la mano con le conf degli object diventa molto veloce.
  • molto utile la funzionalità references/relations
contro:
  • ReferenceOne non molto chiara in db.
  • E' difficile trovare documentazione.
  • Per definire un tipo di dato array bisogna definirlo di tipo 'raw'.
  • Per la definizione dei campi sulle reference bisogna definire un polymorphic per comodità (vedi sotto l'esempio)
  • Non sono riuscito a trovare il metodo per configurare un campo Data a default now().
  • Comportamento strano con gli embed, es : creo un embed di tipo indirizzo e lo salvo in una collection nel field via1, riuso sempre nello codice qualche riga sotto  l'embed salvandolo sempre nella collection indirizzo ma nel campo via2. l'Embed non viene salvato, come se fosse flushato quando è stato agganciato al primo campo.
  • Problemi segnalati con il GridFS
  • Poco supporto sul gruppo 
  • Ho riscontrato un problema nelle reference contenuti negli embed.



ReferenceOne:

Doctrine : definizione molto completa nella collection.



 Mandango: definizione meno accurata.



a mio avviso è meglio usare il field di tipo polymorphic in modo da avere la definizione esatta della classe collegata per facilitare l'eventuale consultazione del db:


è ridondante ma più comprensibile.



altri..

Morph : mancano diversi parti (embed, etc.)
Shanty-Mongo: da verificare sembra valido ad una prima occhiata.

Questo post sarà in aggiornamento continuo.


lunedì 7 novembre 2011

Java e Open Office - JodConverter

Alle volte nasce l'esigenza di convertire dei documenti in vari formati, file di tipo pdf/doc/rtf.

Per la generazione di PDF e RTF ho eseguito qualche prova con Apache FOP, strumento molto valido, ma ridotto solo su determinati formati di output.

Su suggerimento di Frank decido di utilizzare Open Office come servizio su un server Ubuntu. Aggancio una piccola servlet in java su un tomcat che esegue la generazione del documento a fronte di un file in ingresso (nel mio caso passo un .odt e genero un doc e un pdf) Per supportare il tutto uso la libreria JodConverter che attraverso la lib uno si connette ad una istanza di Open Office avviata come server in ascolto su una porta definita (di default la 8100) ed esegue la conversione.

Installazione su server ubuntu da console:


apt-get install jodconverter  
apt-get install tomcat6
apt-get install tomcat6-admin

creato il file /etc/init.d/openoffice.sh
chmod 0755 /etc/init.d/openoffice.sh
lo script [via] piccola modifica al file openoffice.sh per la cartella dei bin

...
OOo_HOME=/usr/lib/openoffice/program/
....

a questo punto dopo aver fatto partire il nostro script di openoffice server possiamo usarlo come servizio.

In allegato un semplicissima web-app in java (in NetBeans) per gestire la conversione di un file in input in qualsiasi formato supportato da OpenOffice. Come da Documentazione si consiglia di installare la app che gestisce la conversione sulla stessa macchina su cui viene eseguito l'OpenOffice Server.

risorse:

Open Office Service
JodConverter
da Php a Odt
JodPackage
Open Office Formati di Import/export


venerdì 14 ottobre 2011

MongoDB and Java - Checking cluster status

Java Example for monitoring MongoDB Cluster.

package freedbtoMongoDb;

import com.mongodb.DB;
import com.mongodb.Mongo;
import java.util.ArrayList;
import java.util.List;

public class CheckCluster {

    static String host = "192.168.0.72";
    static int[] ports = {
        //replica1
        20001, 20002, 20003, 20005,
        //replica11
        20011, 20012, 20013,
        //configsvr1
        20050,
        //configsvr2
        20060,
        //configdb1
        20100,
        //configdb2
        20101
    };

    public static void main(String[] args) {

        try {

            while (true) {
                Thread.sleep(10000);

                for (int port : ports) {

                    try {
                        Mongo m = new Mongo(host, port);
                        List add_l = m.getAllAddress();
                        System.out.println("address:" + add_l);
                        System.out.println("Version: " + m.getVersion());

                        if (m.getReplicaSetStatus() != null) {
                            System.out.println("Replica Name: " + m.getReplicaSetStatus().getName());
                        }

                        ArrayList db_ll = (ArrayList) m.getDatabaseNames();
                        System.out.println("db_list:" + db_ll);
                        for (String db_name : db_ll) {
                            DB d = m.getDB(db_name);
                            System.out.println(db_name + ": " + d.getStats().get("ok") + " - fileSize: " + Double.parseDouble(d.getStats().get("fileSize").toString()) / 1024 + "MB");
                        }

                        m.close();

                        System.out.println();
                    } catch (Exception e) {
                        System.out.println("Problemi sul db: " + port + "\n" + e.getMessage());
                        //send Mail
                    }
                }

            }
        } catch (Throwable t) {
                   //send Mail
        }
    }
}

[download source]

mercoledì 12 ottobre 2011

MongoDB - Cluster - Sharding and Replica Set


Questa è una configurazione di prova per eseguire dei test sulle possibilità di Cluster con Treplica Set e e bilanciamento del carico con MongoDB (Sharding), il test viene eseguito su una macchina sola, in realtà ogni server mongo deve essere residente su una macchina separata

  •  creo le cartelle per i vari db


/data/r1
/data/r2
/data/r3

/data/r11
/data/r12
/data/r13

/data/cfg1
/data/cfg2

  • configuro ed eseguo i due blocchi di replica (2 blocchi da 3 server)


./mongod --replSet replica1 --dbpath /data/r1 --port 20001 --rest 
./mongod --replSet replica1 --dbpath /data/r2 --port 20002 --rest
./mongod --replSet replica1 --dbpath /data/r3 --port 20003 --rest

./mongod --replSet replica11 --dbpath /data/r11 --port 20011 --rest 
./mongod --replSet replica11 --dbpath /data/r12 --port 20012 --rest
./mongod --replSet replica11 --dbpath /data/r13 --port 20013 --rest

nota: per ogni server è possibile avere l'esecuzione in background e il logging su file aggiungendo --fork --logpath /mongodb/log/<nome_del_file>.log --logappend 
  • eseguo la configurazione per agganciare i server replica.
./mongo localhost:20001

config = {
"_id" : "replica1",
"members" : [
{
"_id" : 1,
"host" : "localhost:20001"
},
{
"_id" : 2,
"host" : "localhost:20002"
},
{
"_id" : 3,
"host" : "localhost:20003"
}
]
}

rs.initiate(config);

----

./mongo localhost:20011

config = {
"_id" : "replica11",
"members" : [
{
"_id" : 1,
"host" : "localhost:20011"
},
{
"_id" : 2,
"host" : "localhost:20012"
},
{
"_id" : 3,
"host" : "localhost:20013"
}
]
}

rs.initiate(config);

----


è possibile accedere alla parte di info via web (opzione --rest) su http://192.168.0.75:21001/ e http://192.168.0.75:21011/

  •  server cfg

./mongod --configsvr --dbpath /data/cfg1 --port 20050 --rest

da qui l'interfaccia web:

http://192.168.0.75:21050/


./mongod --configsvr --dbpath /data/cfg2 --port 20060 --rest

  • Mongo finali

 due mongod per accedere con i client

 ./mongos --configdb localhost:20060 --port 20100 
 ./mongos --configdb localhost:20050 --port 20101 

  • Configurazione Sharding

Collego al mogos finale (che rappresentano la punta del mio sistema)

./mongo localhost:20100
use admin
db.runCommand( { addshard : "replica1/localhost:20001,localhost:20002,localhost:20003" } );
db.runCommand( { addshard : "replica11/localhost:20011,localhost:20012,localhost:20013" } );
  
db.runCommand( { listshards : 1 } );

 a questo punto lo shard su replica è configurato

Primo test, se mi collego al ./mongo localhost:20100 ed eseguo db.runCommand( { listshards : 1 } ); ottengo le configurazioni uguali quindi le info sono propagate a tutto il cluster

------

- a questo punto il client a cui devo accedere sono localhost:20100 e localhost:20101 che sono due erogazioni che dovrebbero essere gestite automaticamente dal driver della mia app.

- il parametro --rest serve ad abilitare l'interfaccia rest del browser. Ogni server è raggiungibile da ip:<porta+1000> es se il server è su localhost:20003 la sua parte web è su http://localhost:21003
  • Test di propagazione
- Collego con una piccola app in java al mongos 20100.
- Carico su un db qualche milione di riga, il cluster propaga e sparpaglia i db interi creati su un ramo di replica e l'altro (replica1 e replica11).
  •  Shard del singolo db: 
./mongo localhost:20100
use admin
db.runCommand( { enablesharding : "freedb" } );
  • Shard di una collection
eseguo uno shard della collection

db.runCommand( { shardcollection : "freedb.disc" , key : { filename : 1 } } );


Dopo diversi db creati e milioni di righe inserite trovo con un ramo di shard corposo e uno quasi libero con soli con 2 db, questo è il risultato dell' autobalancer che appunto bilancia il carico.

  • Consistenza

Caduta di una macchina di replica:

ecco che mi cade un mongo del ramo  localhost:20002 (2), le repliche tengono senza problemi, 
la macchina si è demolita... (elimino il contenuto della cartella /data/r2).
dall'interfaccia web vedo che il server va in recovery: 
localhost:20002 2 RECOVERING initial sync need a member to be primary or secondary to do our initial sync 0:0
poi 
localhost:20002 2 RECOVERING initial sync cloning db: freedb21
etc.

Caduta di due macchina di replica:
butto giù le macchine localhost:20001 e localhost:20002
lancio la mia app, mentre sta girando la app si blocca (forse messa in attesa da driver), il ramo di replica localhost:20003 sembra bloccato, fermo la app.. nulla da fare.
rifaccio ripartire il server 20001, finalmente il 20003 si elegge primary e la app riprende le sue insert, quindi se cadono due macchine sul ramo è possibile che tutto si blocchi e rappresenta la criticità del cluster.

soluzione: creare un server arbiter che aiuti la elezione del master: 
http://tebros.com/2010/11/mongodb-arbiters-with-only-two-replicas/
http://www.mongodb.org/display/DOCS/Upgrading+to+Replica+Sets#UpgradingtoReplicaSets-AddingAnArbiter

mkdir /data/arb1
./mongod --rest --replSet replica1 --dbpath /data/arb1 --port 20005

poi.. cerco chi è il primary all'interno della replica1 dall'interfaccia web http://192.168.0.73:21001/_replSet è il localhost:20003

mongo localhost:20003
use admin
rs.addArb("localhost:20005");
rs.status();

a questo punto dall'interfaccia web http://192.168.0.73:21001/_replSet il server arbitrario è online.

..... il server localhost:20002 va in errore..... :  RECOVERING error RS102 too stale to catch up

http://www.mongodb.org/display/DOCS/Resyncing+a+Very+Stale+Replica+Set+Member

Elimino tutto il contenuto della cartella del cluster 20002  - rm -rf /data/r2/* rifaccio ripartire il server 20002 e riparte di resync

ok, a questo punto le conf sono le seguenti:

localhost:20001 - PRIMARY
localhost:20002 - SECONDARY
localhost:20003 - SECONDARY
localhost:20005 - ARBITER

proseguo con il test per verificare il funzionamento dell'ARBITER.
interrompo i server 20002 e 20001.
..no nulla da fare il server 20003 non viene eletto PRIMARY.. 
..neanche tentando di forzare il server 20003  a PRIMARY la cosa non funziona. 
...quindi per avere una replica consistente è necessario avere almeno 3 server in replica oppure 2 in replica e 1 con arbiter.

-------------

- elimino il contenuto della cartella /data/r2
- inserisco dei dati nel db

./mongo localhost:20100
mongos> use freedb21
switched to db freedb21
mongos> for(i=0;i<100000;i++) db.pippo.insert({"test":"prova","c":i});
mongos> db.pippo.count();
100001
......
......
mongos> db.pippo.count();
5418885

-- db sharding

 ./mongo localhost:20101
MongoDB shell version: 2.0.0
connecting to: localhost:20101/test
mongos> use admin
switched to db admin
mongos> db.runCommand( { enablesharding : "freedb21" } );
{ "ok" : 1 }

- il ramo /data/r2 non ricrea i vari file, devo fermare e far ripartire il server r2, a questo punto il server si sincronizza con tutti i rami della sua replica.

--------









martedì 4 ottobre 2011

MongoDB query e qualche test con indici

Utilizzando il db precedentemente creato eseguo qualche query per verificare la velocità:

db.freedb.disk.find({"artist":"Porcupine Tree"}).skip(0).limit(0)

324 risultati
92,81 secondi

Eseguo nuovamente la query precedente ed ottengo gli stessi tempi, quindi non si è creato una cache per la query.

Eseguo la stessa operazione dal codice java:



package freedbtoMongoDb;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;

public class Queries {

    static String host = "mongodb1";
    static int port = 27017;
    static String db_name = "freedb";

    public static void main(String[] args) {

        try {

            Mongo m = new Mongo(host, port);

            DB db = m.getDB(db_name);
            DBCollection coll = db.getCollection("disk");

            BasicDBObject query = new BasicDBObject();
            long t1 = System.currentTimeMillis();
            query.put("artist", "Porcupine Tree");


            DBCursor cur = coll.find(query).limit(0).skip(0);
            long t2 = System.currentTimeMillis();
            System.out.println("Tot time Find: " + (t2 - t1));

            while (cur.hasNext()) {
                System.out.println(cur.next());
            }
            long t3 = System.currentTimeMillis();
            System.out.println("Tot time cursor: " + (t3 - t2));

            m.close();

        } catch (Exception e) {

            System.out.println("Exception :" + e.getMessage());
        }
    }
}


Ottengo i seguenti risultati suddivisi per farte di find e retrive dei dati, da quello che si nota la lentezza è nel periodo di retrive dei dati.





Tot time Find: 2
{ "_id" : { "$oid" : "4e846f2330042d8d3130aad3"} , "id" : "blues_480f5d06" , "filename" : "blues/480f5d06" , "revision" : "7" , "title" : "The Sky Moves Sideways" , "genre" : "Rock" , "artist" : "Porcupine Tree" , "length" : "3935" , "year" : "1995" , "extd" : "YEAR: 1995 ID3G: 17" , "tracks" : { "3" : { "title" : "Prepare Yourself"} , "2" : { "title" : "The Moon Touches Your Shoulder"} , "1" : { "title" : "Dislocated Day"} , "0" : { "title" : "The Sky Moves Sideways (phase one)"} , "5" : { "title" : "The Sky Moves Sideways (phase two)"} , "4" : { "title" : "Moonloop"}}}}
etc..
etc..

Tot time cursor: 61270 (1 minuto abbondante)
BUILD SUCCESSFUL (total time: 1 minute 2 seconds)

adesso provo a restringere la query su determinati campi, ad esempio sul nome dell'album (field title).

db.freedb.disk.find({"artist":"Porcupine Tree"}, {title:1}).skip(0).limit(0)

con il terminale stesso risultato precedente:


324 risultati
92,81 secondi
con il seguente codice java:


package freedbtoMongoDb;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.Mongo;

public class Queries {

    static String host = "mongodb1";
    static int port = 27017;
    static String db_name = "freedb";

    public static void main(String[] args) {

        try {

            Mongo m = new Mongo(host, port);

            DB db = m.getDB(db_name);
            DBCollection coll = db.getCollection("disk");

            BasicDBObject query = new BasicDBObject();


            query.put("artist", "Porcupine Tree");

            BasicDBObject field = new BasicDBObject();
            field.put("title", "1");

            long t1 = System.currentTimeMillis();
            DBCursor cur = coll.find(query, field).limit(0).skip(0);
            long t2 = System.currentTimeMillis();
            System.out.println("Tot time Find: " + (t2 - t1));

            while (cur.hasNext()) {
                System.out.println(cur.next());
            }
            long t3 = System.currentTimeMillis();
            System.out.println("Tot time cursor: " + (t3 - t2));

            m.close();

        } catch (Exception e) {

            System.out.println("Exception :" + e.getMessage());
        }
    }
}





Risultato:

Tot time Find: 1
{ "_id" : { "$oid" : "4e846f2330042d8d3130aad3"} , "title" : "The Sky Moves Sideways"}
{ "_id" : { "$oid" : "4e846f2330042d8d3130add5"} , "title" : "The Sky Moves Sideways"}
{ "_id" : { "$oid" : "4e846f2330042d8d3130bb1a"} , "title" : "The Sky Moves Sideways"}
{ "_id" : { "$oid" : "4e846f5830042d8d3134caaa"} , "title" : "BBC Sessions 1993 & 1995"}
{ "_id" : { "$oid" : "4e846faa30042d8d31379b9d"} , "title" : "XM ReTracked"}
{ "_id" : { "$oid" : "4e846fba30042d8d3138cc14"} , "title" : "Lightbulb Sun"}
etc.
etc.
etc.
Tot time cursor: 73556
BUILD SUCCESSFUL (total time: 1 minute 14 seconds)



Le tempistiche si mantengono molto vicine al precedente test anche con l'estrazione di un singolo campo.

A questo punto creo un indice semplice sul campo artist.

Eseguo nuovamente i test precedenti.

il primo:


console:
db.freedb.disk.find({"artist":"Porcupine Tree"}).skip(0).limit(0)

324 risultati tempo 0,01 s

in java:


Tot time cursor: 557

il secondo:


console:
db.freedb.disk.find({"artist":"Porcupine Tree"}, {title:1}).skip(0).limit(0)



324 risultati tempo 0,00 s

in java:

Tot time cursor: 63

diciamo che gli indici aiutano parecchio....



[sorgenti in NetBeans]



sabato 1 ottobre 2011

MongoTorino - 1st Ottobre 2011 - appunti sparsi



Appunti sparsi della giornata

Politecnico di Torino 1 ottobre 2011 aula 10d.

----------------------------
@FlaPer87

- memory mapped files : alloca memoria (usare free)
- lock gloabal : molti possono leggere ma uno solo lo può scrivere.
- scritture asincrone in coda di scrittura.
- usare il lock per collection (prossima release).
- indici: non possono essere cambiati solo b-tree, possono essere interpretate in modo diverso (es index di geoloc). MongoDB elabora solo un indice per volta.
- cpu: la scrittura usa un core solo, in lettura usa più core, Spidermonkey in javascript è single core mono thred.
- map reduce non disponibile fino alla v8, locks in lettura,locks sulla map, lock sulla reduce, lock sulla write, (lock di scrittura su tutta l'istanza del db).
Usare mapreduce non su strutture principali.
- Scripting usa Spidermonkey, v8 multithreading.
- java jpa si può implementare uno scripting in jvm.
- mongodb mapreduce single core causato dalla limitante dell'engine javascript.
- mongodb è un document store, molto vicino a json e python utile e vicino al linguaggio di programmazione.
- mongoodb spedisce molte info in parallelo, no join e le transaction.
- sharding: molto complesso sulla concororrenza e consistenza del dato.

che db usare:
- che tipo di gestione del dato devo fare?
- che tipo di interazione del dato?
- che modelli devo disegnare? ( oppure ristrutturare i modelli)
- adattare i modelli al db che si usa.
- se estraggo un doc e mi serve sempre un doc correlato uso un embedding altrimenti una reference.
- In memoria (cache) rimane il documento e non la query (uso degli indici sul b-tree), cache a lista.
- sharding degli indici (vedi Kristina della 10gen), esiste un master punti a mongoS che conosce dove viene posizionati gli indici, quindi gli indici sono distribuiti.
- limiti del doc in collection di 16 MB.
- Foursquare tutti i check-in sono in mongodb.

update degli appunti direttamente da @FlaPer nei commenti.


-----------------------------------------------

Diego Guenzi - CSP (centro ricerca)

Web scalabile con Nginx e MongoDB
- test su Nginx - php - mongodb
- scalabilità verticale (comprare hardware della macchina più costi) /orizzontale (più server meno costi)
- rdmbs poca scalabilità orizzontale.
- nosql molta scalabilità orizzontale.
- teorema CAP (Partition Tolerance,Availability,Consistency).
- teorema CAP - C.A. per rdbms
- teorema CAP - P.A. per nosql
- teorema CAP - C.P. per nosql
- bisogna decidere da che tipologia di prestazioni si vogliono avere.
- rdbma modello ACID
- dbms modello BASE (dato non consistente in maniera completa)
- Replica distibuisco su più nodi le stesse info nel caso di network partitionig il db replica i dati e aggiorna successivamente (eventuali conflitti).
- sharding: le info sono distribuite su più server.
- si può mischiare sharding e replica per ottenere buone performance.
- test specifici con ycsb di yahoo.
- mongos per sharding, l'ottimale è sharding+repliche (le repliche devono essere dispari).
- client nginx.
- oracle Exadata (si può clonare con mongo).
- nosql senza standard.
- server web scalabili: tornado,lighttpd, cherokee (sfida delle 10000 connessioni).
- nginx - veloce e low balancing compreso.
- nginx - php - mongodb - aggiungo una macchina clono il tutto ed ogni macchina ha tutto.
- altra soluzione nginx davanti, cluster di nginx e php con solo il driver e una macchina per lo storage.
- altra nginx sul load balancer, macchine con php e macchine sotto con storage.

------------------------------------------------
ore 14:00 - Brendan McAdams 10gen, inc.

mongodb and the jvm
- java driver 2.6.5
- vari esempi di codice basilari...
- scala...
- object -> document
- ODMS in java Morphia (JPA inspired,Annotation driven) e Spring-DataDocument (data-system,Spring paradigms,mutiple datastorage)
- Hadoop + Mongo
- no-web app : logging (graylog2,flume sink)
- WTF:
- le dimensioni collection sono disegnate oer la Replica.
- i documenti sono mantenuti in ordine di inserimento
- cursore di tipo Tailable. (molto efficiente per le query senza indici)
- Messaggistica veloce sul broadcast.

-----------------------------------------------
ore 14:30 - Realtime Analytics using mongodb, phyton source forge.

- couchdb no performance
- new platfom with mongodb
- zarkov (async tpc server,inc validate).
- Bson - ZeroMQ - journal - write log - commit greenlet - Mongo Cronjob.
- mongorestore is fast, but locks a lot.
- indexing is nice, but slows use _id when you can.
- use databases to partition really big data, not collections.

------------------------------------------------
15:14 - new fetured v 2.0 Brendan McAdams 10gen

- journaling compressed
- command compact (old repair)
- old repair (double space on database on disk)
- command compat (defrag individual collections,more fash and light)
- replica sets (priorirties (node with highest prioirty become primary), reconf,tags,majority write concerns)
- indici pù leggeri
- stack defaul 1mb
- geospatial indexing

------------------------------------------------
15:40 - GridFS - Mitch Pirtle

- i metadata sono separati e possono comodamente stare in un array di metadata
- add attribute to store file
- Replica set - ridondare
- master-slave - performance
- sharding - scalare
- i file vengono splittati a blocchi


----

Questi sono solo appunti, che dovrò approfondire, presi durante l'ottima giornata.

giovedì 29 settembre 2011

FreeDB to MongoDB


Ultimamente mi trovo a lavorare con MongoDB, ed ecco subito un test di import di massa scritto in java per testare le tempistiche di import e Query del db.

Come al solito utilizzo il freedb, trasformo tutti il db in un succoso file json da 800MB con la classe FreeDbToJson (progetto completo linkato al fondo del post).

questa è una riga del json:

{
   "id":"soundtrack_fe13d011",
   "filename":"soundtrack/fe13d011",
   "revision":"0",
   "title":"100 Love Songs Stage 4 Cd4",
   "genre":"Soundtrack",
   "artist":"IndianDigitalAudio.com",
   "length":"5074",
   "year":"2011",
   "extd":"",
    "tracks":{
              "15":{"title":"Mausam Achanak"},
              "16":{"title":"I Dont Know What To Do"},
              "13":{"title":"Aaja Maahi"},
              "14":{"title":"Janeman"},
              "11":{"title":"Roshan Dil Ka Jahan"},
              "12":{"title":"Yaad Teri Aaye"},
             "3":{"title":"Jo Ghumshuda"},
              "2":{"title":"Dhadke Jiya"},
              "1":{"title":"Nazrein Karam"},
              "10":{"title":"Tum Bhi Ho Wahi"},
             "0":{"title":"Aao Milo Chalo"},
              "7":{"title":"Mausam"},
              "6":{"title":"Mera Pehla Pehla Pyaar"},
              "5":{"title":"Raat Ke Dhai Baje"},
              "4":{"title":"Jaane Tu Meri Kya Hai"},
              "9":{"title":"Pyaar Ki Yeh Kahani"},
              "8":{"title":"Miss You Everyday"}
  }

}
Dopo aver ottenuto questo file eseguo un'altro piccolo programmino in java per importare di massa tutti i record utilizzando la funzionalità requestStart().


package freedbtoMongoDb;

import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.util.JSON;
import java.io.IOException;

public class JsonToMongoDB {

    static String host = "hostname";
    static int port = 27017;
    static String db_name = "freedb";
    static String target_folder = "/marco/mongodb/file/";

    public static void main(String[] args) throws IOException {

        Mongo m = new Mongo(host, port);
        DB db = m.getDB(db_name);
        db.requestStart();

        System.out.println("File: " + target_folder + "disk.json");
       BigFile file = null;
        try {
            file = new BigFile(target_folder + "disk.json");
        } catch (Exception ex) {
            System.out.println("exception: " + ex.getMessage());
        }

        long ts = System.currentTimeMillis();
        int i = 0;
        for (String line : file) {
            db.getCollection("disk").insert((DBObject) JSON.parse(line));
            System.out.println("line: " + i);
            i++;
        }

        System.out.println("tot time: " + (System.currentTimeMillis() - ts));
        db.requestDone();

    }
}

il db mongo server è installato su una vm dedicata invece il programma sopra gira in locale in netbeans, le tempistiche sono state:  - tot time: 959532 ( circa 16 minuti) per 3057298 righe inserite.

[sorgenti]

giovedì 22 settembre 2011

Doctrine MongoDB - @ReferenceOne to different target class






<?

/**
 * @Document
 * @InheritanceType("SINGLE_COLLECTION")
 * @DiscriminatorField(fieldName="type")
 * @DiscriminatorMap({"student"="Student","customer"="Customer"})
 */

class People {


/** @Id */
protected $id;



/** @String */
protected $name;


/** @String */
protected $surname;


        ..etc.. etc...



}





/**
 * @Document
 */
class Student extend People {


/** @String */
protected $course;

/** @String */
protected $year;


        ..etc.. etc...



}




/**

 * @Document

 */

class Customer extend People {


/** @String */
protected $code;

/** @String */
protected $name;


        ..etc.. etc...


}


/**

 * @Document

 */

class MixedPeople {


/** @Id */
protected $id;

        /** @ReferenceOne(targetDocument="People") */
protected $mixedpeople;

        ..etc.. etc...


}

mercoledì 14 settembre 2011

Strumenti per progettare i DB?

Un tempo usavo carta e matita per disegnare i db...
.. fino a che non sono diventati dei mostri di tabelle... (questa volta con MongoDB)


..adesso sotto consiglio di fede sono passato a OmniGraffle, i risultati non sono sempre buoni...

qualcuno mi consiglia un software più definito per lo scopo? (sotto Mac magari anche free... :) )

lunedì 5 settembre 2011

Jetty - Hot Deploy e Reload

per eseguire un reload della singola app è necessario eseguire un

touch /etc/jetty/context/configurazione-webapp.xml


oppure inserire al volo una nuova conf.xml e jetty esegue l'Hot deploy senza bisogno del restart del service.




[grazie a Fabrizio]

martedì 30 agosto 2011

Kill Postgres Connection


select procpid from pg_stat_activity where datname='<dbname>';


from bash: kill <procpid>

mercoledì 24 agosto 2011

MongoDB - Backup e Restore


come eseguire un backup ed un restore di un intero db.

dalla console di root

./mongodump

viene creata la cartella /dump/* contenente i db in formato binario

per eseguire il restore:

./mongorestore -v /dump/<nome_db>

[via]

lunedì 22 agosto 2011

Htc Desire S - problema con la tastiera e il Locale

Sono passato dall'HTC Hero all'HTC Desire S, comprato online su Expansys l'unica pecca è che non era presente la tastiera Italiano (Italia). Tra i foum trovo questo programma sul market che aggiunge i locali al piccolo android.

MoreLocale 2

venerdì 5 agosto 2011

Vcast chiude il 9 Agosto 2011

Caro utente,
dopo anni di onorato servizio, Vcast e la funzionalita' FaucetPVR hanno terminato la propria missione di sperimentazione
e il giorno 9 Agosto 2011 il progetto verra' definitivamente chiuso.

In questi anni abbiamo imparato molto, anche grazie a tutti voi, senza i quali il servizio non sarebbe potuto diventare funzionale.

Vi ringraziamo sinceramente per questi anni trascorsi insieme, per la vostra fedelta' e pazienza dimostrata.

Molti utenti ci hanno chiesto di indircargli quali servizi possono sostituire Vcast, in realta' servizi
analoghi di registrazione TV su Internet a nostra conoscenza non ne estistono piu', NextTV di Telecom Italia
ha chiuso il trial il 2 Agosto e anche Bong.Tv ha cessato la registrazione dei canali italiani da tempo.

Per un ambito piu' ridotto relativo alla sola gestione dei podcast e delle radio DriveCast (http://drivecast.eu)
rappresenta una ottima soluzione.

Per chi vuole la vita facile e non complicarsela con le varie chiavette USB da collegare al PC e con i loro
programmi di registrazione, la BLOBBOX (http://bit.ly/pCNE9M) e' una ottima alternativa, e gli sviluppatori
prevedono di introdurre la programmazione delle registrazioni da web entro l' autunno.

Con sincera stima,
Il Vcast Team.

martedì 2 agosto 2011

le Novità di Java 7 - Presentazione al Jug - Torino





Le novità di Java 7 from Federico Fissore on Vimeo.

completo di slide

Facebook - Account Commemorativo

Dopo che è mancato lo Zio Teresio ho scoperto che su facebook posso trasformare il suo Account in commemorativo, dopo aver fatto la richiesta mi arriva questa mail:

Salve,
Siamo veramente addolorati per la tua perdita. Analizzeremo la tua segnalazione e prenderemo le misure appropriate in base alle nostre normative descritte di seguito. Anche se potresti non ricevere un'e-mail di conferma nel momento in cui prenderemo le misure appropriate, ci teniamo a farti sapere che analizziamo tutte le segnalazioni.
Account commemorativo
In base alla nostra politica, tutti gli account appartenenti a utenti deceduti che ci vengono segnalati diventano commemorativi. Con tale azione, la privacy viene impostata in modo che solo gli amici confermati possano vedere il profilo o trovare l'utente deceduto nelle ricerche. Il profilo, inoltre, non verrà più visualizzato nella sezione "Suggerimenti" della home page. La bacheca invece rimarrà nel profilo, in modo che amici e familiari possano lasciare dei post per ricordare l'utente defunto. Non possiamo fornire per nessun motivo le informazioni di accesso all'account.
Rimozione dell'account
I parenti più stretti possono richiedere la rimozione dell'account di un loro caro. Con questa operazione, l'account verrà rimosso del tutto da Facebook e non potrà più essere visualizzato da nessuno. Non ripristineremo in nessun caso l'account né divulgheremo le informazioni in esso contenute, a meno che non sia la legge a richiederlo. Se stai chiedendo la rimozione di un account e non sei un parente stretto della persona deceduta, la tua richiesta non verrà elaborata, ma l'account sarà comunque reso commemorativo.
Se desideri inviare una richiesta speciale relativa all'account di una persona deceduta, usa questo modulo:
http://www.facebook.com/help/contact.php?show_form=memorialize_special_requests
Tieni presente che potremmo non essere in grado di soddisfare tutte le richieste.
Per qualsiasi altra domanda, visita il nostro Centro assistenza a questo indirizzo:
http://www.facebook.com/help/?page=842
Grazie,
Il team di Facebook

mercoledì 8 giugno 2011

Facebook - Scarica le tue informazioni

Non sapevo l'esistenza di questa possibilità! Ovvero di poter scaricare da Facebook tutte le nostre info attualmente salvate:

Questo strumento ti consente di scaricare una copia delle tue informazioni, comprese le foto e i video, i post in bacheca, tutti i tuoi messaggi, la lista dei tuoi amici e altri contenuti che hai condiviso sul tuo profilo. Questo file zip ti consentirà di accedere ai tuoi dati e di consultarli in modo semplice. Maggiori informazioni su come scaricare una copia delle tue informazioni.
Protezione
Ecco una copia di tutte le informazioni personali che hai condiviso su Facebook. Per proteggere la tua sicurezza, abbiamo bisogno di verificare la tua identità.
ATTENZIONE: questo file contiene informazioni riservate. Dal momento che questo download contiene le tue informazioni del profilo, ti consigliamo di salvarlo in un luogo sicuro e di valutare con attenzione prima di archiviarlo, inviarlo o caricarlo su altri servizi.

per arrivare a questo dopo essersi loggati in alto adestra selezionare:

Account > Impostazioni Account 

poi selezionare la penultima voce in fondo:

Scarica le tue informazioni



a questo punto quando lo zip sarà generato arriverà una mail con il link per il download.

Arrivata la mail mi manda a questa pagina:


dove mi scarico un succoso file zip di 23 MB

al suo interno trovo tutti i miei album, l'elenco dei miei amici (solo nome e cognome nessun dato personale..), eventi, messaggi, note, profilo, video e la bacheca completa. Non male.. anche se avere qualche dato sugli amici non sarebbe male...


martedì 24 maggio 2011

MBFastUrl - nuova beta - vari fix - nuove stats

- cron con statistiche per ip
- fix sulla grafica
- varie ottimizzazione sulle conf
- stats log sui qrcode
- cron e stats con sommatoria degli ip nelle varie fasi view,save,qrcode

il server di test attualmente è arrivato ad avere 460 Link salvati e più di 12500 click sui link, non male visto che lo utilizzo solo io per propagare i link sui vari social.

per ora il db dei link in SqLite è 26 MB invece quello di elaborazione delle statistiche 19 MB.

Per ora SqLite tiene, magari prossimamente ci sarà un porting a OrientDB.

lunedì 23 maggio 2011

From Freedb.org to OrientDB - #4

#1 - #2 - #3

Download a big file about 170 Mb.
Uncompress  ... about 614 Mb and 2630481 file...

to speed up the importation are processed only 1000 files per folder.

sample porting schema from FreeDB to OrientDB:



import code




import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx;
import com.orientechnologies.orient.core.metadata.schema.OProperty.INDEX_TYPE;
import com.orientechnologies.orient.core.metadata.schema.OType;
import com.orientechnologies.orient.core.record.impl.ODocument;
import com.orientechnologies.orient.core.sql.query.OSQLSynchQuery;
import com.orientechnologies.orient.server.OServer;
import com.orientechnologies.orient.server.OServerMain;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import org.apache.commons.io.FileUtils;

private String base = "/Users/marco/orientdb/";
private String root_dir = base + "/file_freedb/freedb-complete-20090101/";
private HashMap cache_year = new HashMap();
private HashMap cache_genre = new HashMap();

  private void import_data() {

        try {

            OServer server = OServerMain.create();
            server.startup(new File(base + "/file/conf.xml"));

            ODatabaseDocumentTx db = new ODatabaseDocumentTx("local:" + base + "/freedb");
            if (!db.exists()) {
                db.create();
                System.out.println("create new DB");
            } else {
                db.delete();
                db.create();
                System.out.println("delete and create new DB");
            }


            FileFilter directoryFilter = new FileFilter() {

                public boolean accept(File file) {
                    return file.isDirectory();
                }
            };

            //default index on odocument
            db.begin();


            ODocument oArtist = new ODocument(db, "artist");
            oArtist.field("name", "Various", OType.STRING);
            oArtist.save();

            db.getMetadata().getSchema().getClass("artist").createProperty("name", OType.STRING).createIndex(INDEX_TYPE.FULLTEXT);
            db.getMetadata().getSchema().save();


            ODocument oTrack = new ODocument(db, "track");
            oTrack.field("title", "Various", OType.STRING);
            oTrack.save();

            db.getMetadata().getSchema().getClass("track").createProperty("title", OType.STRING).createIndex(INDEX_TYPE.FULLTEXT);
            db.getMetadata().getSchema().save();


            ODocument oGendr = new ODocument(db, "genre");
            oGendr.field("name", "Various", OType.STRING);
            oGendr.save();

            db.getMetadata().getSchema().getClass("genre").createProperty("name", OType.STRING).createIndex(INDEX_TYPE.UNIQUE);
            db.getMetadata().getSchema().save();


            ODocument oYear = new ODocument(db, "year");
            oYear.field("data", "19000101", OType.DATE);
            oYear.save();

            db.getMetadata().getSchema().getClass("year").createProperty("data", OType.DATE).createIndex(INDEX_TYPE.UNIQUE);
            db.getMetadata().getSchema().save();


            db.commit();


            File[] dirs = new File(root_dir).listFiles(directoryFilter);
            int i = 0;
            for (File dir : dirs) {

                if (!dir.isDirectory()) {
                    continue;
                }

                System.out.println("" + dir);

                int max_file_for_debug = 0;
                Collection files = FileUtils.listFiles(dir, null, true);
                for (File file : files) {
                    if (file.getName().startsWith(".")) {
                        continue;
                    }


                    try {
                        List lines = FileUtils.readLines(file);

                        db.begin();
                        ODocument oDisk = new ODocument(db, "disk");

                        ArrayList tracks = new ArrayList();

                        String titles = "";
                        String extd = "";
                        for (String line : lines) {

                            if (line.startsWith("# Disc length:")) {
                                String length = line.replaceAll("# Disc length:", "").replaceAll("seconds", "").replaceAll("secs", "").trim();

                                oDisk.field("Disc Length", length, OType.INTEGER);
                            }

                            if (line.startsWith("# Revision:")) {
                                String revision = line.replaceAll("# Revision:", "").trim();


                                oDisk.field("revision", revision, OType.INTEGER);
                            }


                            if (line.startsWith("#")) {
                                continue;
                            }

                            String ele[] = line.split("=");

                            if (ele == null || ele.length == 1) {
                                continue;
                            }

                            String key = ele[0];
                            String value = ele[1];


                            if (key.equals("DISKID")) {
                                oDisk.field(key.toLowerCase(), value, OType.STRING);
                            }

                            if (key.equals("DYEAR")) {
                                oDisk.field("year", check_and_create_year(value + "0101", db), OType.LINK);
                            }

                            if (key.equals("DGENRE")) {

                                oDisk.field("genre", check_and_create_genre(value, db), OType.LINK);
                            }

                            //concatenate multiple title lines
                            if (key.equals("DTITLE")) {
                                titles += value;
                            }

                            if (key.equals("EXTD")) {
                                extd += value;
                            }



                            //tracks list
                            if (key.startsWith("TTITLE")) {
                                oTrack = new ODocument(db, "track");
                                oTrack.field("n", key.replaceAll("TTITLE", ""), OType.INTEGER);

                                String tartist = "";


                                oTrack.field("title", getTitle(value));

                                tartist = getAuthor(value);

                                if (!tartist.equals("")) {

                                    oTrack.field("artist", check_and_create_artist(tartist, db), OType.LINK);
                                } else {
                                    oTrack.field("artist");
                                }


                                oTrack.save();
                                tracks.add(oTrack);

                            }

                        }

                        //add track_list
                        if (!tracks.isEmpty()) {
                            oDisk.field("tracks", tracks, OType.EMBEDDEDLIST);
                        }

                        //title and artist disk
                        if (!titles.equals("")) {

                            oDisk.field("title", getTitle(titles));
                            oDisk.field("artist", check_and_create_artist(getAuthor(titles), db), OType.LINK);

                        }

                        //title and artist disk
                        if (!extd.equals("")) {
                            oDisk.field("extd", extd);
                        }

                        oDisk.save();
                        db.commit();

                    } catch (IOException ex) {
                        System.out.println("ex (1):" + ex.getMessage() + ex.getStackTrace().toString());

                        for (StackTraceElement s : ex.getStackTrace()) {
                            System.out.println("" + s);
                        }

                        db.rollback();
                        continue;

                    }


                    i++;
                    if ((i >= 1000) && (i % 1000) == 1) {
                        System.out.println("\t" + file);
                        for (String s : db.getClusterNames()) {
                            System.out.println("cluster: " + s + " - " + db.countClusterElements(s));

                        }

                        //for debug max 1000 file for folder
                        break;
                    }

                }

            }


            db.close();

            //server
            server.shutdown();
        } catch (Exception ex) {
            System.out.println("ex (2):" + ex.getMessage() + ex.getStackTrace().toString());


            for (StackTraceElement s : ex.getStackTrace()) {
                System.out.println("" + s);
            }

        }

    }

    private ODocument check_and_create_artist(String name, ODatabaseDocumentTx db) {


        if (name.equals("")) {
            return null;
        }


        OSQLSynchQuery query = new OSQLSynchQuery("select from artist where name = ?");
        List result = db.command(query).execute(name);


        if (!result.isEmpty()) {
            return (ODocument) result.get(0);

        } else {

            ODocument oArtist = new ODocument(db, "artist");
            oArtist.field("name", /*a*/ name, OType.STRING);
            oArtist.save();

            return oArtist;
        }


    }

    private ODocument check_and_create_year(String year, ODatabaseDocumentTx db) {

        if (cache_year.containsKey(year)) {
            return cache_year.get(year);
        }


        OSQLSynchQuery query = new OSQLSynchQuery("select from year where data = ?");
        List result = db.command(query).execute(year);


        if (!result.isEmpty()) {
            cache_year.put(year, (ODocument) result.get(0));
            return (ODocument) result.get(0);

        } else {

            ODocument oYear = new ODocument(db, "year");
            oYear.field("data", year, OType.DATE);
            oYear.save();
            cache_year.put(year, oYear);

            return oYear;
        }


    }

    private ODocument check_and_create_genre(String genre, ODatabaseDocumentTx db) {

        if (cache_genre.containsKey(genre)) {
            return cache_genre.get(genre);
        }

        OSQLSynchQuery query = new OSQLSynchQuery("select from genre where name = ?");
        List result = db.command(query).execute(genre);

        if (!result.isEmpty()) {
            cache_genre.put(genre, (ODocument) result.get(0));
            return (ODocument) result.get(0);

        } else {

            ODocument oGenre = new ODocument(db, "genre");
            oGenre.field("name", genre, OType.STRING);
            oGenre.save();
            cache_genre.put(genre, oGenre);
            return oGenre;
        }


    }

    private String getTitle(String value) {


        if (value.indexOf("/") == -1) {
            return escape(value);
        }

        try {
            return escape(value.split("/")[0]);
        } catch (Exception e) {
            return "";
        }

    }

    private String getAuthor(String value) {

        if (value.indexOf("/") == -1) {
            return "";
        }

        if (value.split("/").length == 0) {
            return "";
        }

        try {
            return escape(value.split("/")[1]);
        } catch (Exception e) {
            return "";
        }


    }

    private String escape(String s) {
        if (s == null) {
            return s;
        }
        return s.trim().replaceAll("\\[", "").replaceAll("\\]", "").replaceAll("'", "\\\\'");
    }



Lib:

  • commons-io-2.0.1.jar
  • orient-commons-1.0rc2-SNAPSHOT.jar
  • orientdb-client-1.0rc2-SNAPSHOT.jar
  • orientdb-core-1.0rc2-SNAPSHOT.jar
  • orientdb-enterprise-1.0rc2-SNAPSHOT.jar
  • orientdb-server-1.0rc2-SNAPSHOT.jar
  • orientdb-tools-1.0rc2-SNAPSHOT.jar
  • persistence-api-1.0.jar

after several hours...


cluster: internal - 3
cluster: index - 882
cluster: default - 0
cluster: orole - 3
cluster: ouser - 3
cluster: artist - 43767
cluster: track - 155602
cluster: genre - 995
cluster: year - 114
cluster: disk - 11001



about 4GB of db...

Test Query:


first time:
query:select from artist name like 'Pink%' tot time:25692 ms
next:
query:select from artist name like 'Pink%' tot time:1646 ms

first time:
query:select from disk where artist.name like 'Pink%' tot time: 13388 ms
next:
query:select from disk where artist.name like 'Pink%' tot time: 4714 ms

first time:
query:select from disk where tracks contains ( artist.name like 'Pink%' ) tot time: 1628 ms
next:
query:select from disk where tracks contains ( artist.name like 'Pink%' ) tot time: 1481 ms

first/next time:
query:select from disk where year.data = '19780101' tot time: 906