removed npe

pull/1/head
Michael Christen 13 years ago
parent e7e429705a
commit d35bdc2df6

@ -50,16 +50,19 @@ import net.yacy.kelondro.util.BEncoder;
import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.FileUtils;
/** /**
* store a table of properties (instead of fixed-field entries) * store a table of properties (instead of fixed-field entries) this is realized using blobs and BEncoded
* this is realized using blobs and BEncoded property lists * property lists
*/ */
public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<Map.Entry<byte[], Map<String, byte[]>>> { public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>,
Iterable<Map.Entry<byte[], Map<String, byte[]>>>
{
private Heap table; private Heap table;
private final LinkedHashSet<String> columnames; private final LinkedHashSet<String> columnames;
/** /**
* produce or open a properties table * produce or open a properties table
*
* @param location the file * @param location the file
* @param keylength length of access keys * @param keylength length of access keys
* @param ordering ordering on the keys * @param ordering ordering on the keys
@ -77,12 +80,11 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* convenience method to open a properies table * convenience method to open a properies table
*
* @param location the file * @param location the file
* @param keylength length of access keys * @param keylength length of access keys
*/ */
public BEncodedHeap( public BEncodedHeap(final File location, final int keylength) throws IOException {
final File location,
final int keylength) throws IOException {
this.table = new Heap(location, keylength, NaturalOrder.naturalOrder, 100); this.table = new Heap(location, keylength, NaturalOrder.naturalOrder, 100);
this.columnames = new LinkedHashSet<String>(); this.columnames = new LinkedHashSet<String>();
} }
@ -91,45 +93,54 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
return Base64Order.enhancedCoder.encodeSubstring(Digest.encodeMD5Raw(key), this.table.keylength); return Base64Order.enhancedCoder.encodeSubstring(Digest.encodeMD5Raw(key), this.table.keylength);
} }
private static class EntryIter implements Iterator<Map.Entry<byte[], Map<String, byte[]>>> { private static class EntryIter implements Iterator<Map.Entry<byte[], Map<String, byte[]>>>
{
HeapReader.entries iter; HeapReader.entries iter;
public EntryIter(final File location, final int keylen) throws IOException { public EntryIter(final File location, final int keylen) throws IOException {
this.iter = new HeapReader.entries(location, keylen); this.iter = new HeapReader.entries(location, keylen);
} }
@Override
public boolean hasNext() { public boolean hasNext() {
return this.iter.hasNext(); return this.iter.hasNext();
} }
@Override
public Entry<byte[], Map<String, byte[]>> next() { public Entry<byte[], Map<String, byte[]>> next() {
final Map.Entry<byte[], byte[]> entry = this.iter.next(); final Map.Entry<byte[], byte[]> entry = this.iter.next();
final Map<String, byte[]> map = b2m(entry.getValue()); final Map<String, byte[]> map = b2m(entry.getValue());
return new b2mEntry(entry.getKey(), map); return new b2mEntry(entry.getKey(), map);
} }
@Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
public static class b2mEntry implements Map.Entry<byte[], Map<String, byte[]>> { public static class b2mEntry implements Map.Entry<byte[], Map<String, byte[]>>
{
private final byte[] s; private final byte[] s;
private Map<String,byte[]> b; private Map<String, byte[]> b;
public b2mEntry(final byte[] s, final Map<String, byte[]> b) { public b2mEntry(final byte[] s, final Map<String, byte[]> b) {
this.s = s; this.s = s;
this.b = b; this.b = b;
} }
@Override
public byte[] getKey() { public byte[] getKey() {
return this.s; return this.s;
} }
@Override
public Map<String, byte[]> getValue() { public Map<String, byte[]> getValue() {
return this.b; return this.b;
} }
@Override
public Map<String, byte[]> setValue(final Map<String, byte[]> value) { public Map<String, byte[]> setValue(final Map<String, byte[]> value) {
final Map<String, byte[]> b1 = this.b; final Map<String, byte[]> b1 = this.b;
this.b = value; this.b = value;
@ -138,15 +149,21 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
private static Map<String, byte[]> b2m(final byte[] b) { private static Map<String, byte[]> b2m(final byte[] b) {
if (b == null) return null; if ( b == null ) {
return null;
}
//System.out.println("b = " + UTF8.String(b)); //System.out.println("b = " + UTF8.String(b));
final BDecoder decoder = new BDecoder(b); final BDecoder decoder = new BDecoder(b);
final BObject bobj = decoder.parse(); final BObject bobj = decoder.parse();
if (bobj.getType() != BDecoder.BType.dictionary) return null; if ( bobj == null || bobj.getType() != BDecoder.BType.dictionary ) {
return null;
}
final Map<String, BDecoder.BObject> map = bobj.getMap(); final Map<String, BDecoder.BObject> map = bobj.getMap();
final Map<String, byte[]> m = new HashMap<String, byte[]>(); final Map<String, byte[]> m = new HashMap<String, byte[]>();
for (final Map.Entry<String, BDecoder.BObject> entry: map.entrySet()) { for ( final Map.Entry<String, BDecoder.BObject> entry : map.entrySet() ) {
if (entry.getValue().getType() != BDecoder.BType.string) continue; if ( entry.getValue().getType() != BDecoder.BType.string ) {
continue;
}
m.put(entry.getKey(), entry.getValue().getString()); m.put(entry.getKey(), entry.getValue().getString());
} }
return m; return m;
@ -154,6 +171,7 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* the map is stored inside a file; this method may return the file * the map is stored inside a file; this method may return the file
*
* @return the file where the map is stored * @return the file where the map is stored
*/ */
public File getFile() { public File getFile() {
@ -162,8 +180,10 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* Retur the number of key-value mappings in this map. * Retur the number of key-value mappings in this map.
*
* @return the number of entries mappings in this map * @return the number of entries mappings in this map
*/ */
@Override
public int size() { public int size() {
return this.table.size(); return this.table.size();
} }
@ -171,12 +191,14 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* return true if the table is empty * return true if the table is empty
*/ */
@Override
public boolean isEmpty() { public boolean isEmpty() {
return this.table.size() == 0; return this.table.size() == 0;
} }
/** /**
* check if a row with given key exists in the table * check if a row with given key exists in the table
*
* @param name * @param name
* @return true if the row exists * @return true if the row exists
*/ */
@ -185,20 +207,23 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
/** /**
* check if a row with given key exists in the table * check if a row with given key exists in the table This method is here to implement the Map interface
* This method is here to implement the Map interface *
* @param name * @param name
* @return true if the row exists * @return true if the row exists
*/ */
@Override
public boolean containsKey(final Object key) { public boolean containsKey(final Object key) {
if (key instanceof byte[]) return containsKey((byte[]) key); if ( key instanceof byte[] ) {
return containsKey((byte[]) key);
}
return false; return false;
} }
/** /**
* the containsValue method cannot be used in this method * the containsValue method cannot be used in this method and is only here to implement the Map interface
* and is only here to implement the Map interface
*/ */
@Override
public boolean containsValue(final Object value) { public boolean containsValue(final Object value) {
// this method shall not be used because it is not appropriate for this kind of data // this method shall not be used because it is not appropriate for this kind of data
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -206,6 +231,7 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* get a map from the table * get a map from the table
*
* @param name * @param name
* @return the map if one found or NULL if no entry exists or the entry is corrupt * @return the map if one found or NULL if no entry exists or the entry is corrupt
* @throws RowSpaceExceededException * @throws RowSpaceExceededException
@ -213,32 +239,37 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
*/ */
public Map<String, byte[]> get(final byte[] pk) throws IOException, RowSpaceExceededException { public Map<String, byte[]> get(final byte[] pk) throws IOException, RowSpaceExceededException {
final byte[] b = this.table.get(pk); final byte[] b = this.table.get(pk);
if (b == null) return null; if ( b == null ) {
return null;
}
return b2m(b); return b2m(b);
} }
/** /**
* get a map from the table * get a map from the table this method is here to implement the Map interface
* this method is here to implement the Map interface *
* @param name * @param name
* @return the map if one found or NULL if no entry exists or the entry is corrupt * @return the map if one found or NULL if no entry exists or the entry is corrupt
*/ */
@Override
public Map<String, byte[]> get(final Object key) { public Map<String, byte[]> get(final Object key) {
if (key instanceof byte[]) if ( key instanceof byte[] ) {
try { try {
return get((byte[]) key); return get((byte[]) key);
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} catch (final RowSpaceExceededException e) { } catch ( final RowSpaceExceededException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} }
}
return null; return null;
} }
/** /**
* convenience method to get a value from a map * convenience method to get a value from a map
*
* @param pk * @param pk
* @param key * @param key
* @return the value * @return the value
@ -247,14 +278,17 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
*/ */
public byte[] getProp(final byte[] pk, final String key) throws IOException, RowSpaceExceededException { public byte[] getProp(final byte[] pk, final String key) throws IOException, RowSpaceExceededException {
final byte[] b = this.table.get(pk); final byte[] b = this.table.get(pk);
if (b == null) return null; if ( b == null ) {
return null;
}
final Map<String, byte[]> map = b2m(b); final Map<String, byte[]> map = b2m(b);
return map.get(key); return map.get(key);
} }
/** /**
* select all rows from a table where a given matcher matches with elements in a given row * select all rows from a table where a given matcher matches with elements in a given row this method
* this method makes a full-table scan of the whole table * makes a full-table scan of the whole table
*
* @param columnName the name of the column where the matcher shall match * @param columnName the name of the column where the matcher shall match
* @param columnMatcher the matcher for the elements of the column * @param columnMatcher the matcher for the elements of the column
* @return a set of primary keys where the matcher matched * @return a set of primary keys where the matcher matched
@ -265,50 +299,59 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
Map<String, byte[]> prop; Map<String, byte[]> prop;
byte[] val; byte[] val;
final Set<byte[]> pks = new TreeSet<byte[]>(this.table.ordering); final Set<byte[]> pks = new TreeSet<byte[]>(this.table.ordering);
while (i.hasNext()) { while ( i.hasNext() ) {
row = i.next(); row = i.next();
prop = row.getValue(); prop = row.getValue();
val = prop.get(columnName); val = prop.get(columnName);
if (val != null) { if ( val != null ) {
if (columnMatcher.matcher(UTF8.String(val)).matches()) pks.add(row.getKey()); if ( columnMatcher.matcher(UTF8.String(val)).matches() ) {
pks.add(row.getKey());
}
} }
} }
return pks; return pks;
} }
/** /**
* select one row from a table where a given matcher matches with elements in a given row * select one row from a table where a given matcher matches with elements in a given row this method
* this method stops the full-table scan as soon as a first matcher was found * stops the full-table scan as soon as a first matcher was found
*
* @param columnName the name of the column where the matcher shall match * @param columnName the name of the column where the matcher shall match
* @param columnMatcher the matcher for the elements of the column * @param columnMatcher the matcher for the elements of the column
* @return the row where the matcher matched the given column * @return the row where the matcher matched the given column
*/ */
public Map.Entry<byte[], Map<String, byte[]>> selectOne(final String columnName, final Pattern columnMatcher) { public Map.Entry<byte[], Map<String, byte[]>> selectOne(
final String columnName,
final Pattern columnMatcher) {
final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = iterator(); final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = iterator();
Map.Entry<byte[], Map<String, byte[]>> row; Map.Entry<byte[], Map<String, byte[]>> row;
Map<String, byte[]> prop; Map<String, byte[]> prop;
byte[] val; byte[] val;
while (i.hasNext()) { while ( i.hasNext() ) {
row = i.next(); row = i.next();
prop = row.getValue(); prop = row.getValue();
val = prop.get(columnName); val = prop.get(columnName);
if (val != null) { if ( val != null ) {
if (columnMatcher.matcher(UTF8.String(val)).matches()) return row; if ( columnMatcher.matcher(UTF8.String(val)).matches() ) {
return row;
}
} }
} }
return null; return null;
} }
/** /**
* insert a map into the table * insert a map into the table this method shall be used in exchange of the get method if the previous
* this method shall be used in exchange of the get method if the * entry value is not needed.
* previous entry value is not needed. *
* @param name * @param name
* @param map * @param map
* @throws RowSpaceExceededException * @throws RowSpaceExceededException
* @throws IOException * @throws IOException
*/ */
public void insert(final byte[] pk, final Map<String, byte[]> map) throws RowSpaceExceededException, IOException { public void insert(final byte[] pk, final Map<String, byte[]> map)
throws RowSpaceExceededException,
IOException {
final byte[] b = BEncoder.encode(BEncoder.transcode(map)); final byte[] b = BEncoder.encode(BEncoder.transcode(map));
this.table.insert(pk, b); this.table.insert(pk, b);
this.columnames.addAll(map.keySet()); this.columnames.addAll(map.keySet());
@ -320,9 +363,11 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
this.columnames.add(key); this.columnames.add(key);
} }
public void update(final byte[] pk, final Map<String, byte[]> map) throws RowSpaceExceededException, IOException { public void update(final byte[] pk, final Map<String, byte[]> map)
throws RowSpaceExceededException,
IOException {
final Map<String, byte[]> entry = this.get(pk); final Map<String, byte[]> entry = this.get(pk);
if (entry == null) { if ( entry == null ) {
insert(pk, map); insert(pk, map);
} else { } else {
entry.putAll(map); entry.putAll(map);
@ -330,9 +375,11 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
} }
public void update(final byte[] pk, final String key, final byte[] value) throws RowSpaceExceededException, IOException { public void update(final byte[] pk, final String key, final byte[] value)
throws RowSpaceExceededException,
IOException {
Map<String, byte[]> entry = this.get(pk); Map<String, byte[]> entry = this.get(pk);
if (entry == null) { if ( entry == null ) {
entry = new HashMap<String, byte[]>(); entry = new HashMap<String, byte[]>();
entry.put(key, value); entry.put(key, value);
insert(pk, entry); insert(pk, entry);
@ -344,9 +391,11 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* insert a map into the table * insert a map into the table
*
* @param name * @param name
* @param map * @param map
*/ */
@Override
public Map<String, byte[]> put(final byte[] pk, final Map<String, byte[]> map) { public Map<String, byte[]> put(final byte[] pk, final Map<String, byte[]> map) {
try { try {
final Map<String, byte[]> entry = this.get(pk); final Map<String, byte[]> entry = this.get(pk);
@ -354,10 +403,10 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
this.table.insert(pk, b); this.table.insert(pk, b);
this.columnames.addAll(map.keySet()); this.columnames.addAll(map.keySet());
return entry; return entry;
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} catch (final RowSpaceExceededException e) { } catch ( final RowSpaceExceededException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} }
@ -365,6 +414,7 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* delete a map from the table * delete a map from the table
*
* @param name * @param name
* @throws IOException * @throws IOException
*/ */
@ -374,6 +424,7 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
/** /**
* delete a map from the table * delete a map from the table
*
* @param name * @param name
* @throws RowSpaceExceededException * @throws RowSpaceExceededException
* @throws IOException * @throws IOException
@ -384,17 +435,19 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
return value; return value;
} }
@Override
public Map<String, byte[]> remove(final Object key) { public Map<String, byte[]> remove(final Object key) {
if (key instanceof byte[]) if ( key instanceof byte[] ) {
try { try {
return remove((byte[]) key); return remove((byte[]) key);
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} catch (final RowSpaceExceededException e) { } catch ( final RowSpaceExceededException e ) {
Log.logException(e); Log.logException(e);
return null; return null;
} }
}
return null; return null;
} }
@ -403,58 +456,62 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
* *
* @param m mappings to be stored in this map * @param m mappings to be stored in this map
*/ */
@Override
public void putAll(final Map<? extends byte[], ? extends Map<String, byte[]>> map) { public void putAll(final Map<? extends byte[], ? extends Map<String, byte[]>> map) {
for (final Map.Entry<? extends byte[], ? extends Map<String, byte[]>> me: map.entrySet()) { for ( final Map.Entry<? extends byte[], ? extends Map<String, byte[]>> me : map.entrySet() ) {
try { try {
this.insert(me.getKey(), me.getValue()); this.insert(me.getKey(), me.getValue());
} catch (final RowSpaceExceededException e) { } catch ( final RowSpaceExceededException e ) {
Log.logException(e); Log.logException(e);
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
} }
} }
} }
/** /**
* remove all entries from the map; * remove all entries from the map; possibly removes the backend-file
* possibly removes the backend-file
*/ */
@Override
public void clear() { public void clear() {
try { try {
this.table.clear(); this.table.clear();
this.columnames.clear(); this.columnames.clear();
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
} }
} }
/** /**
* close the backen-file. * close the backen-file. Should be called explicitely to ensure that all data waiting in IO write buffers
* Should be called explicitely to ensure that all data * are flushed
* waiting in IO write buffers are flushed
*/ */
public void close() { public void close() {
this.table.close(); this.table.close();
} }
/** /**
* Return a Set of the keys contained in this map. * Return a Set of the keys contained in this map. This may not be a useful method, if possible use the
* This may not be a useful method, if possible use the keys() * keys() method instead to iterate all keys from the backend-file
* method instead to iterate all keys from the backend-file
* *
* @return a set view of the keys contained in this map * @return a set view of the keys contained in this map
*/ */
@Override
public Set<byte[]> keySet() { public Set<byte[]> keySet() {
final TreeSet<byte[]> set = new TreeSet<byte[]>(this.table.ordering); final TreeSet<byte[]> set = new TreeSet<byte[]>(this.table.ordering);
try { try {
final Iterator<byte[]> i = this.table.keys(true, false); final Iterator<byte[]> i = this.table.keys(true, false);
while (i.hasNext()) set.add(i.next()); while ( i.hasNext() ) {
} catch (final IOException e) {} set.add(i.next());
}
} catch ( final IOException e ) {
}
return set; return set;
} }
/** /**
* iterate all keys of the table * iterate all keys of the table
*
* @return an iterator of byte[] * @return an iterator of byte[]
* @throws IOException * @throws IOException
*/ */
@ -463,47 +520,43 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
/** /**
* the values() method is not implemented in this class * the values() method is not implemented in this class because it does not make sense to use such a
* because it does not make sense to use such a method for * method for file-based data structures. To get a collection view of all the entries, just use a entry
* file-based data structures. To get a collection view of * iterator instead.
* all the entries, just use a entry iterator instead.
* *
* @return nothing. The method throws always a UnsupportedOperationException * @return nothing. The method throws always a UnsupportedOperationException
*/ */
@Override
public Collection<Map<String, byte[]>> values() { public Collection<Map<String, byte[]>> values() {
// this method shall not be used because it is not appropriate for this kind of data // this method shall not be used because it is not appropriate for this kind of data
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* The abstract method entrySet() from AbstractMap must be implemented, * The abstract method entrySet() from AbstractMap must be implemented, but never used because that is not
* but never used because that is not useful for this file-based storage class. * useful for this file-based storage class. To prevent the usage, a UnsupportedOperationException is
* To prevent the usage, a UnsupportedOperationException is thrown. * thrown. To prevent that the method is used by the methods from AbstractMap, all such methods must be
* To prevent that the method is used by the methods from AbstractMap, all such * overriden in this class. These methods are: size, containsValue, containsKey, get, remove, putAll,
* methods must be overriden in this class. These methods are: * clear, keySet, values, equals, hashCode and toString Instead of using this method, use the iterator()
* size, containsValue, containsKey, get, remove, putAll, clear, * method to iterate all elements in the back-end blob file
* keySet, values, equals, hashCode and toString
*
* Instead of using this method, use the iterator() method to iterate
* all elements in the back-end blob file
*/ */
@Override
public Set<Map.Entry<byte[], Map<String, byte[]>>> entrySet() { public Set<Map.Entry<byte[], Map<String, byte[]>>> entrySet() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
/** /**
* iterate all rows of the table. * iterate all rows of the table. This method implements the Iterable<Map.Entry<byte[], Map<String,
* This method implements the * byte[]>>> interface
* Iterable<Map.Entry<byte[], Map<String, byte[]>>>
* interface
*/ */
@Override
public Iterator<Map.Entry<byte[], Map<String, byte[]>>> iterator() { public Iterator<Map.Entry<byte[], Map<String, byte[]>>> iterator() {
final File location = this.table.location(); final File location = this.table.location();
final int keylen = this.table.keylength(); final int keylen = this.table.keylength();
try { try {
this.table.flushBuffer(); this.table.flushBuffer();
return new EntryIter(location, keylen); return new EntryIter(location, keylen);
} catch (final IOException e1) { } catch ( final IOException e1 ) {
final ByteOrder order = this.table.ordering(); final ByteOrder order = this.table.ordering();
final int buffermax = this.table.getBuffermax(); final int buffermax = this.table.getBuffermax();
this.table.close(); this.table.close();
@ -511,7 +564,7 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
final Iterator<Map.Entry<byte[], Map<String, byte[]>>> iter = new EntryIter(location, keylen); final Iterator<Map.Entry<byte[], Map<String, byte[]>>> iter = new EntryIter(location, keylen);
this.table = new Heap(location, keylen, order, buffermax); this.table = new Heap(location, keylen, order, buffermax);
return iter; return iter;
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logSevere("PropertiesTable", e.getMessage(), e); Log.logSevere("PropertiesTable", e.getMessage(), e);
return null; return null;
} }
@ -519,18 +572,20 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
/** /**
* iterate all rows of the table. this is a static method that expects that the given * iterate all rows of the table. this is a static method that expects that the given file is not opened
* file is not opened by any other application * by any other application
*
* @param location * @param location
* @param keylen * @param keylen
* @return * @return
* @throws IOException * @throws IOException
*/ */
public static Iterator<Map.Entry<byte[], Map<String, byte[]>>> iterator(final File location, final int keylen) throws IOException { public static Iterator<Map.Entry<byte[], Map<String, byte[]>>> iterator(
final File location,
final int keylen) throws IOException {
return new EntryIter(location, keylen); return new EntryIter(location, keylen);
} }
/** /**
* a hashcode for the object * a hashcode for the object
*/ */
@ -540,16 +595,15 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
/** /**
* Produce a list of column names from this table * Produce a list of column names from this table This method may be useful if the table shall be
* This method may be useful if the table shall be displayed * displayed as a table in GUIs. To show the first line of the table, the table header, a list of all
* as a table in GUIs. To show the first line of the table, the * column names is required. This can be generated with this method
* table header, a list of all column names is required. This can *
* be generated with this method
* @return a list of column names * @return a list of column names
*/ */
public ArrayList<String> columns() { public ArrayList<String> columns() {
if (this.columnames.size() == 0) { if ( this.columnames.size() == 0 ) {
for (final Map.Entry<byte[], Map<String, byte[]>> row: this) { for ( final Map.Entry<byte[], Map<String, byte[]>> row : this ) {
this.columnames.addAll(row.getValue().keySet()); this.columnames.addAll(row.getValue().keySet());
} }
} }
@ -559,31 +613,36 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
} }
public static void main(final String[] args) { public static void main(final String[] args) {
if (args.length == 0) { if ( args.length == 0 ) {
// test the class // test the class
final 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.getAbsolutePath());
//System.out.println(f.getParent()); //System.out.println(f.getParent());
if (f.exists()) FileUtils.deletedelete(f); if ( f.exists() ) {
FileUtils.deletedelete(f);
}
try { try {
final BEncodedHeap map = new BEncodedHeap(f, 4); final BEncodedHeap map = new BEncodedHeap(f, 4);
// put some values into the map // put some values into the map
final Map<String, byte[]> m = new HashMap<String, byte[]>(); final Map<String, byte[]> m = new HashMap<String, byte[]>();
m.put("k", "000".getBytes()); map.insert("123".getBytes(), m); m.put("k", "000".getBytes());
m.put("k", "111".getBytes()); map.insert("456".getBytes(), m); map.insert("123".getBytes(), m);
m.put("k", "222".getBytes()); map.insert("789".getBytes(), m); m.put("k", "111".getBytes());
map.insert("456".getBytes(), m);
m.put("k", "222".getBytes());
map.insert("789".getBytes(), m);
// iterate over keys // iterate over keys
Map.Entry<byte[], Map<String, byte[]>> entry; Map.Entry<byte[], Map<String, byte[]>> entry;
final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = map.iterator(); final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = map.iterator();
while (i.hasNext()) { while ( i.hasNext() ) {
entry = i.next(); entry = i.next();
System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue());
} }
// clean up // clean up
map.close(); map.close();
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
} catch (final RowSpaceExceededException e) { } catch ( final RowSpaceExceededException e ) {
Log.logException(e); Log.logException(e);
} }
} else { } else {
@ -592,12 +651,12 @@ public class BEncodedHeap implements Map<byte[], Map<String, byte[]>>, Iterable<
Map.Entry<byte[], Map<String, byte[]>> entry; Map.Entry<byte[], Map<String, byte[]>> entry;
final BEncodedHeap map = new BEncodedHeap(f, 12); final BEncodedHeap map = new BEncodedHeap(f, 12);
final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = map.iterator(); final Iterator<Map.Entry<byte[], Map<String, byte[]>>> i = map.iterator();
while (i.hasNext()) { while ( i.hasNext() ) {
entry = i.next(); entry = i.next();
System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue());
} }
map.close(); map.close();
} catch (final IOException e) { } catch ( final IOException e ) {
Log.logException(e); Log.logException(e);
} }
} }

Loading…
Cancel
Save