@ -9,7 +9,7 @@
// $LastChangedBy$
//
// LICENSE
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
@ -52,13 +52,13 @@ import net.yacy.kelondro.util.LookAheadIterator;
public class Tables {
private static final String suffix = ".bheap" ;
private static final String system_table_pkcounter = "pkcounter" ;
private static final String system_table_pkcounter_counterName = "pk" ;
private File location ;
private ConcurrentHashMap < String , BEncodedHeap > tables ;
private final File location ;
private final ConcurrentHashMap < String , BEncodedHeap > tables ;
int keymaxlen ;
// use our own formatter to prevent concurrency locks with other processes
@ -69,7 +69,7 @@ public class Tables {
if ( ! this . location . exists ( ) ) this . location . mkdirs ( ) ;
this . keymaxlen = keymaxlen ;
this . tables = new ConcurrentHashMap < String , BEncodedHeap > ( ) ;
String [ ] files = this . location . list ( ) ;
final String [ ] files = this . location . list ( ) ;
String tablename ;
File file ;
for ( final String f : files ) {
@ -82,16 +82,16 @@ public class Tables {
tablename = f . substring ( 0 , f . length ( ) - suffix . length ( ) ) ;
try {
getHeap ( tablename ) ;
} catch ( IOException e ) {
} catch ( final IOException e ) {
}
}
}
}
public Iterator < String > tables ( ) {
return this . tables . keySet ( ) . iterator ( ) ;
}
public void close ( final String tablename ) {
final BEncodedHeap heap = this . tables . remove ( tablename ) ;
if ( heap = = null ) return ;
@ -103,30 +103,33 @@ public class Tables {
this . tables . clear ( ) ;
}
public void clear ( final String tablename ) throws IOException {
BEncodedHeap heap = getHeap ( tablename ) ;
if ( heap = = null ) return ;
heap . clear ( ) ;
File f = heap . getFile ( ) ;
heap . close ( ) ;
public void clear ( final String tablename ) {
BEncodedHeap heap = null ;
try {
heap = getHeap ( tablename ) ;
if ( heap ! = null ) heap . clear ( ) ;
heap . close ( ) ;
} catch ( final IOException e ) {
}
heap = null ;
final File f = new File ( this . location , tablename + suffix ) ;
this . tables . remove ( tablename ) ;
FileUtils . deletedelete ( f ) ;
}
public boolean hasHeap ( final String tablename ) {
try {
return getHeap ( tablename ) ! = null ;
} catch ( IOException e ) {
} catch ( final IOException e ) {
return false ;
}
}
public BEncodedHeap getHeap ( final String tablename ) throws IOException {
final String table = tablename + suffix ;
BEncodedHeap heap = this . tables . get ( tablename ) ;
if ( heap ! = null ) return heap ;
// open a new heap and register it in the tables
final File heapf = new File ( this . location , table ) ;
heap = new BEncodedHeap ( heapf , this . keymaxlen ) ;
@ -134,12 +137,12 @@ public class Tables {
return heap ;
}
public int size ( String table ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public int size ( final String table ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
return heap . size ( ) ;
}
private byte [ ] ukey ( String tablename ) throws IOException , RowSpaceExceededException {
private byte [ ] ukey ( final String tablename ) throws IOException , RowSpaceExceededException {
Row row = select ( system_table_pkcounter , UTF8 . getBytes ( tablename ) ) ;
if ( row = = null ) {
// table counter entry in pkcounter table does not exist: make a new table entry
@ -160,110 +163,110 @@ public class Tables {
}
return pk ;
}
private String int2key ( int i ) {
StringBuilder sb = new StringBuilder ( this . keymaxlen ) ;
String is = Integer . toString ( i ) ;
private String int2key ( final int i ) {
final StringBuilder sb = new StringBuilder ( this . keymaxlen ) ;
final String is = Integer . toString ( i ) ;
for ( int j = 0 ; j < this . keymaxlen - is . length ( ) ; j + + ) sb . append ( '0' ) ;
sb . append ( is ) ;
return sb . toString ( ) ;
}
/ * *
* insert a map into a table using a new unique key
* @param tablename
* @param map
* @throws RowSpaceExceededException
* @throws IOException
* @throws RowSpaceExceededException
* @throws RowSpaceExceededException
* /
public byte [ ] insert ( final String tablename , Map < String , byte [ ] > map ) throws IOException , RowSpaceExceededException {
byte [ ] uk = ukey ( tablename ) ;
public byte [ ] insert ( final String tablename , final Map < String , byte [ ] > map ) throws IOException , RowSpaceExceededException {
final byte [ ] uk = ukey ( tablename ) ;
update ( tablename , uk , map ) ;
BEncodedHeap heap = getHeap ( system_table_pkcounter ) ;
final BEncodedHeap heap = getHeap ( system_table_pkcounter ) ;
heap . insert ( UTF8 . getBytes ( tablename ) , system_table_pkcounter_counterName , uk ) ;
return uk ;
}
public void insert ( final String table , byte [ ] pk , Map < String , byte [ ] > map ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public void insert ( final String table , final byte [ ] pk , final Map < String , byte [ ] > map ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
try {
heap . insert ( pk , map ) ;
} catch ( RowSpaceExceededException e ) {
} catch ( final RowSpaceExceededException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
}
public void insert ( final String table , Row row ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public void insert ( final String table , final Row row ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
try {
heap . insert ( row . pk , row ) ;
} catch ( RowSpaceExceededException e ) {
} catch ( final RowSpaceExceededException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
}
public void update ( final String table , byte [ ] pk , Map < String , byte [ ] > map ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public void update ( final String table , final byte [ ] pk , final Map < String , byte [ ] > map ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
try {
heap . update ( pk , map ) ;
} catch ( RowSpaceExceededException e ) {
} catch ( final RowSpaceExceededException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
}
public void update ( final String table , Row row ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public void update ( final String table , final Row row ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
try {
heap . update ( row . pk , row ) ;
} catch ( RowSpaceExceededException e ) {
} catch ( final RowSpaceExceededException e ) {
throw new IOException ( e . getMessage ( ) ) ;
}
}
public byte [ ] createRow ( String table ) throws IOException , RowSpaceExceededException {
public byte [ ] createRow ( final String table ) throws IOException , RowSpaceExceededException {
return this . insert ( table , new ConcurrentHashMap < String , byte [ ] > ( ) ) ;
}
public Row select ( final String table , byte [ ] pk ) throws IOException , RowSpaceExceededException {
BEncodedHeap heap = getHeap ( table ) ;
public Row select ( final String table , final byte [ ] pk ) throws IOException , RowSpaceExceededException {
final BEncodedHeap heap = getHeap ( table ) ;
if ( heap . containsKey ( pk ) ) return new Row ( pk , heap . get ( pk ) ) ;
return null ;
}
public void delete ( final String table , byte [ ] pk ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public void delete ( final String table , final byte [ ] pk ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
heap . delete ( pk ) ;
}
public boolean has ( String table , byte [ ] key ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public boolean has ( final String table , final byte [ ] key ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
return heap . containsKey ( key ) ;
}
public Iterator < byte [ ] > keys ( String table ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public Iterator < byte [ ] > keys ( final String table ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
return heap . keys ( ) ;
}
public Iterator < Row > iterator ( String table ) throws IOException {
public Iterator < Row > iterator ( final String table ) throws IOException {
return new RowIterator ( table ) ;
}
public Iterator < Row > iterator ( String table , String whereColumn , byte [ ] whereValue ) throws IOException {
public Iterator < Row > iterator ( final String table , final String whereColumn , final byte [ ] whereValue ) throws IOException {
return new RowIterator ( table , whereColumn , whereValue ) ;
}
public Iterator < Row > iterator ( String table , String whereColumn , Pattern wherePattern ) throws IOException {
public Iterator < Row > iterator ( final String table , final String whereColumn , final Pattern wherePattern ) throws IOException {
return new RowIterator ( table , whereColumn , wherePattern ) ;
}
public Iterator < Row > iterator ( String table , Pattern wherePattern ) throws IOException {
public Iterator < Row > iterator ( final String table , final Pattern wherePattern ) throws IOException {
return new RowIterator ( table , wherePattern ) ;
}
public Collection < Row > orderByPK ( Iterator < Row > rowIterator , int maxcount ) {
TreeMap < String , Row > sortTree = new TreeMap < String , Row > ( ) ;
public Collection < Row > orderByPK ( final Iterator < Row > rowIterator , int maxcount ) {
final TreeMap < String , Row > sortTree = new TreeMap < String , Row > ( ) ;
Row row ;
while ( ( maxcount < 0 | | maxcount - - > 0 ) & & rowIterator . hasNext ( ) ) {
row = rowIterator . next ( ) ;
@ -271,9 +274,9 @@ public class Tables {
}
return sortTree . values ( ) ;
}
public Collection < Row > orderBy ( Iterator < Row > rowIterator , int maxcount , String sortColumn ) {
TreeMap < String , Row > sortTree = new TreeMap < String , Row > ( ) ;
public Collection < Row > orderBy ( final Iterator < Row > rowIterator , int maxcount , final String sortColumn ) {
final TreeMap < String , Row > sortTree = new TreeMap < String , Row > ( ) ;
Row row ;
byte [ ] r ;
while ( ( maxcount < 0 | | maxcount - - > 0 ) & & rowIterator . hasNext ( ) ) {
@ -287,9 +290,9 @@ public class Tables {
}
return sortTree . values ( ) ;
}
public ArrayList < String > columns ( String table ) throws IOException {
BEncodedHeap heap = getHeap ( table ) ;
public ArrayList < String > columns ( final String table ) throws IOException {
final BEncodedHeap heap = getHeap ( table ) ;
return heap . columns ( ) ;
}
@ -299,20 +302,20 @@ public class Tables {
private final byte [ ] whereValue ;
private final Pattern wherePattern ;
private final Iterator < Map . Entry < byte [ ] , Map < String , byte [ ] > > > i ;
/ * *
* iterator that iterates all elements in the given table
* @param table
* @throws IOException
* /
public RowIterator ( String table ) throws IOException {
public RowIterator ( final String table ) throws IOException {
this . whereColumn = null ;
this . whereValue = null ;
this . wherePattern = null ;
BEncodedHeap heap = getHeap ( table ) ;
i = heap . iterator ( ) ;
final BEncodedHeap heap = getHeap ( table ) ;
this . i = heap . iterator ( ) ;
}
/ * *
* iterator that iterates all elements in the given table
* where a given column is equal to a given value
@ -321,15 +324,15 @@ public class Tables {
* @param whereValue
* @throws IOException
* /
public RowIterator ( String table , String whereColumn , byte [ ] whereValue ) throws IOException {
public RowIterator ( final String table , final String whereColumn , final byte [ ] whereValue ) throws IOException {
assert whereColumn ! = null | | whereValue = = null ;
this . whereColumn = whereColumn ;
this . whereValue = whereValue ;
this . wherePattern = null ;
BEncodedHeap heap = getHeap ( table ) ;
i = heap . iterator ( ) ;
final BEncodedHeap heap = getHeap ( table ) ;
this . i = heap . iterator ( ) ;
}
/ * *
* iterator that iterates all elements in the given table
* where a given column matches with a given value
@ -338,14 +341,14 @@ public class Tables {
* @param wherePattern
* @throws IOException
* /
public RowIterator ( String table , String whereColumn , Pattern wherePattern ) throws IOException {
public RowIterator ( final String table , final String whereColumn , final Pattern wherePattern ) throws IOException {
this . whereColumn = whereColumn ;
this . whereValue = null ;
this . wherePattern = wherePattern ;
BEncodedHeap heap = getHeap ( table ) ;
i = heap . iterator ( ) ;
final BEncodedHeap heap = getHeap ( table ) ;
this . i = heap . iterator ( ) ;
}
/ * *
* iterator that iterates all elements in the given table
* where any column matches with a given value
@ -353,18 +356,18 @@ public class Tables {
* @param pattern
* @throws IOException
* /
public RowIterator ( String table , Pattern pattern ) throws IOException {
public RowIterator ( final String table , final Pattern pattern ) throws IOException {
this . whereColumn = null ;
this . whereValue = null ;
this . wherePattern = pattern ;
BEncodedHeap heap = getHeap ( table ) ;
i = heap . iterator ( ) ;
final BEncodedHeap heap = getHeap ( table ) ;
this . i = heap . iterator ( ) ;
}
protected Row next0 ( ) {
Row r ;
while ( i. hasNext ( ) ) {
r = new Row ( i. next ( ) ) ;
while ( this . i. hasNext ( ) ) {
r = new Row ( this . i. next ( ) ) ;
if ( this . whereValue ! = null ) {
if ( ByteBuffer . equals ( r . get ( this . whereColumn ) , this . whereValue ) ) return r ;
} else if ( this . wherePattern ! = null ) {
@ -379,90 +382,90 @@ public class Tables {
}
} else {
return r ;
}
}
}
return null ;
}
}
public static class Data extends LinkedHashMap < String , byte [ ] > {
private static final long serialVersionUID = 978426054043749337L ;
public Data ( ) {
super ( ) ;
}
private Data ( final Map < String , byte [ ] > map ) {
super ( ) ;
assert map ! = null ;
this . putAll( map ) ;
putAll( map ) ;
}
public void put ( String colname , String value ) {
public void put ( final String colname , final String value ) {
super . put ( colname , UTF8 . getBytes ( value ) ) ;
}
public void put ( String colname , int value ) {
public void put ( final String colname , final int value ) {
super . put ( colname , UTF8 . getBytes ( Integer . toString ( value ) ) ) ;
}
public void put ( String colname , long value ) {
public void put ( final String colname , final long value ) {
super . put ( colname , UTF8 . getBytes ( Long . toString ( value ) ) ) ;
}
public void put ( String colname , Date value ) {
public void put ( final String colname , final Date value ) {
super . put ( colname , UTF8 . getBytes ( my_SHORT_MILSEC_FORMATTER . format ( value ) ) ) ;
}
public byte [ ] get ( String colname , byte [ ] dflt ) {
byte [ ] r = this . get ( colname ) ;
public byte [ ] get ( final String colname , final byte [ ] dflt ) {
final byte [ ] r = this . get ( colname ) ;
if ( r = = null ) return dflt ;
return r ;
}
public String get ( String colname , String dflt ) {
byte [ ] r = this . get ( colname ) ;
public String get ( final String colname , final String dflt ) {
final byte [ ] r = this . get ( colname ) ;
if ( r = = null ) return dflt ;
return UTF8 . String ( r ) ;
}
public int get ( String colname , int dflt ) {
byte [ ] r = this . get ( colname ) ;
public int get ( final String colname , final int dflt ) {
final byte [ ] r = this . get ( colname ) ;
if ( r = = null ) return dflt ;
try {
return ( int ) ByteArray . parseDecimal ( r ) ;
} catch ( NumberFormatException e ) {
} catch ( final NumberFormatException e ) {
return dflt ;
}
}
public long get ( String colname , long dflt ) {
byte [ ] r = this . get ( colname ) ;
public long get ( final String colname , final long dflt ) {
final byte [ ] r = this . get ( colname ) ;
if ( r = = null ) return dflt ;
try {
return ByteArray . parseDecimal ( r ) ;
} catch ( NumberFormatException e ) {
} catch ( final NumberFormatException e ) {
return dflt ;
}
}
public Date get ( String colname , Date dflt ) {
byte [ ] r = this . get ( colname ) ;
public Date get ( final String colname , final Date dflt ) {
final byte [ ] r = this . get ( colname ) ;
if ( r = = null ) return dflt ;
try {
return my_SHORT_MILSEC_FORMATTER . parse ( UTF8 . String ( r ) ) ;
} catch ( ParseException e ) {
} catch ( final ParseException e ) {
return dflt ;
}
}
@Override
public String toString ( ) {
StringBuilder sb = new StringBuilder ( this . size ( ) * 40 ) ;
final StringBuilder sb = new StringBuilder ( this . size ( ) * 40 ) ;
sb . append ( '{' ) ;
for ( final Map . Entry < String , byte [ ] > entry : this . entrySet( ) ) {
for ( final Map . Entry < String , byte [ ] > entry : entrySet( ) ) {
sb . append ( entry . getKey ( ) ) . append ( '=' ) . append ( UTF8 . String ( entry . getValue ( ) ) ) . append ( ", " ) ;
}
if ( sb . length ( ) > 1 ) sb . setLength ( sb . length ( ) - 2 ) ;
@ -470,13 +473,13 @@ public class Tables {
return sb . toString ( ) ;
}
}
public class Row extends Data {
private static final long serialVersionUID = 978426054043749338L ;
private final byte [ ] pk ;
private Row ( final Map . Entry < byte [ ] , Map < String , byte [ ] > > entry ) {
super ( entry . getValue ( ) ) ;
assert entry ! = null ;
@ -484,43 +487,43 @@ public class Tables {
assert entry . getValue ( ) ! = null ;
this . pk = entry . getKey ( ) ;
}
private Row ( final byte [ ] pk , final Map < String , byte [ ] > map ) {
super ( map ) ;
assert pk ! = null ;
assert map ! = null ;
this . pk = pk ;
}
private Row ( final byte [ ] pk , String k0 , byte [ ] v0 ) {
private Row ( final byte [ ] pk , final String k0 , final byte [ ] v0 ) {
super ( ) ;
assert k0 ! = null ;
assert v0 ! = null ;
this . put ( k0 , v0 ) ;
this . pk = pk ;
}
public byte [ ] getPK ( ) {
return this . pk ;
}
@Override
public String toString ( ) {
StringBuilder sb = new StringBuilder ( keymaxlen + 20 * this . size ( ) ) ;
sb . append ( UTF8 . String ( pk) ) . append ( ":" ) . append ( super . toString ( ) ) ;
final StringBuilder sb = new StringBuilder ( Tables. this . keymaxlen + 20 * this . size ( ) ) ;
sb . append ( UTF8 . String ( this . pk) ) . append ( ":" ) . append ( super . toString ( ) ) ;
return sb . toString ( ) ;
}
}
public static void main ( String [ ] args ) {
public static void main ( final String [ ] args ) {
// test the class
File f = new File ( new File ( "maptest" ) . getAbsolutePath ( ) ) ;
final File f = new File ( new File ( "maptest" ) . getAbsolutePath ( ) ) ;
// System.out.println(f.getAbsolutePath());
// System.out.println(f.getParent());
try {
Tables map = new Tables ( f . getParentFile ( ) , 4 ) ;
final Tables map = new Tables ( f . getParentFile ( ) , 4 ) ;
// put some values into the map
Map < String , byte [ ] > m = new HashMap < String , byte [ ] > ( ) ;
final Map < String , byte [ ] > m = new HashMap < String , byte [ ] > ( ) ;
m . put ( "k" , "000" . getBytes ( ) ) ;
map . update ( "testdao" , "123" . getBytes ( ) , m ) ;
m . put ( "k" , "111" . getBytes ( ) ) ;
@ -528,13 +531,13 @@ public class Tables {
m . put ( "k" , "222" . getBytes ( ) ) ;
map . update ( "testdao" , "789" . getBytes ( ) , m ) ;
// iterate over keys
Iterator < Row > i = map . iterator ( "testdao" ) ;
final Iterator < Row > i = map . iterator ( "testdao" ) ;
while ( i . hasNext ( ) ) {
System . out . println ( i . next ( ) . toString ( ) ) ;
}
// clean up
map . close ( ) ;
} catch ( IOException e ) {
} catch ( final IOException e ) {
Log . logException ( e ) ;
}
}