From 05f34a3fa7436e262166e23fe20db23c9f9060f4 Mon Sep 17 00:00:00 2001 From: orbiter Date: Tue, 22 Nov 2011 12:31:07 +0000 Subject: [PATCH] added a full, complete, database insert, update and delete API for the tables. Please see this example: list all database tables: http://localhost:8090/api/table_p.xml now create a new table and insert some values into 'mytable' http://localhost:8090/api/table_p.xml?table=mytable&pk=&commitrow=&col_termin=Release%20Machen&col_datum=24.11.2011&col_status=ongoing list the table content: http://localhost:8090/api/table_p.xml?table=mytable&pk= update the table and change a single value inside. You must refer to the row using a primary key 'pk' http://localhost:8090/api/table_p.xml?table=mytable&pk=000000000001&commitrow=&col_datum=29.11.2011 you can also select rows using a search operator http://localhost:8090/api/table_p.xml?table=mytable&pk=&count=10&search= now lets delete the row: http://localhost:8090/api/table_p.xml?table=mytable&pk=&deleterows=pk_000000000001 and we can also delete the complete table: http://localhost:8090/api/table_p.xml?table=mytable&deletetable= You can use this to administrate the robots, bookmarks and API steering using an outside application! git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@8071 6c8d7289-2bf4-0310-a012-ef5d649a1542 --- htroot/Table_YMark_p.java | 2 +- htroot/Tables_p.html | 2 +- htroot/Tables_p.java | 21 +- htroot/api/table_p.java | 95 +++++-- htroot/api/table_p.xml | 38 +-- .../net/yacy/kelondro/blob/BEncodedHeap.java | 239 +++++++++--------- source/net/yacy/kelondro/blob/Tables.java | 37 ++- 7 files changed, 260 insertions(+), 174 deletions(-) diff --git a/htroot/Table_YMark_p.java b/htroot/Table_YMark_p.java index 399fba42e..ebf9611ad 100644 --- a/htroot/Table_YMark_p.java +++ b/htroot/Table_YMark_p.java @@ -40,7 +40,7 @@ public class Table_YMark_p { // show table selection int count = 0; - final Iterator ti = sb.tables.tables(); + final Iterator ti = sb.tables.iterator(); String tablename; prop.put("showselection", 1); while (ti.hasNext()) { diff --git a/htroot/Tables_p.html b/htroot/Tables_p.html index 437ea099b..4c07e8615 100644 --- a/htroot/Tables_p.html +++ b/htroot/Tables_p.html @@ -84,7 +84,7 @@ document.write("
\ #{list}# - + #[pk]# #{columns}# #[cell]# diff --git a/htroot/Tables_p.java b/htroot/Tables_p.java index ba51178f0..3ecfe3a52 100644 --- a/htroot/Tables_p.java +++ b/htroot/Tables_p.java @@ -49,7 +49,7 @@ public class Tables_p { // show table selection int count = 0; - final Iterator ti = sb.tables.tables(); + final Iterator ti = sb.tables.iterator(); String tablename; prop.put("showselection", 1); while (ti.hasNext()) { @@ -69,21 +69,13 @@ public class Tables_p { final Pattern matcher = (pattern.length() == 0 || pattern.equals(".*")) ? null : Pattern.compile(".*" + pattern + ".*"); prop.put("pattern", pattern); - List columns = null; - if (table != null) try { - columns = sb.tables.columns(table); - } catch (final IOException e) { - Log.logException(e); - columns = new ArrayList(); - } - // apply deletion requests if (post.get("deletetable", "").length() > 0) sb.tables.clear(table); if (post.get("deleterows", "").length() > 0) { for (final Map.Entry entry: post.entrySet()) { - if (entry.getValue().startsWith("mark_")) try { + if (entry.getValue().startsWith("pk_")) try { sb.tables.delete(table, entry.getValue().substring(5).getBytes()); } catch (final IOException e) { Log.logException(e); @@ -110,8 +102,17 @@ public class Tables_p { prop.put("showtable", 0); prop.put("showedit", 0); + if (table != null) { + List columns = null; + try { + columns = sb.tables.columns(table); + } catch (final IOException e) { + Log.logException(e); + columns = new ArrayList(); + } + if (post.containsKey("editrow")) { // check if we can find a key String pk = null; diff --git a/htroot/api/table_p.java b/htroot/api/table_p.java index 9f9f41127..0fa36909a 100644 --- a/htroot/api/table_p.java +++ b/htroot/api/table_p.java @@ -19,11 +19,15 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.Iterator; +import java.util.Map; +import java.util.regex.Pattern; import net.yacy.cora.document.UTF8; import net.yacy.cora.protocol.RequestHeader; import net.yacy.kelondro.blob.Tables; +import net.yacy.kelondro.index.RowSpaceExceededException; import net.yacy.kelondro.logging.Log; import net.yacy.search.Switchboard; import de.anomic.server.serverObjects; @@ -39,17 +43,85 @@ public class table_p { final boolean html = EXT.equals("html"); final boolean xml = EXT.equals("xml"); - String table = (post == null) ? null : post.get("table", null); - if (table != null && !sb.tables.hasHeap(table)) table = null; + String table = (post == null) ? null : post.get("table"); + if (post == null || (!post.containsKey("commitrow") && table != null && !sb.tables.hasHeap(table))) table = null; prop.put("showtable", 0); + prop.put("tablecount", sb.tables.size()); - if (table == null) return prop; + // apply deletion requests + if (table != null && post != null && post.containsKey("deletetable")) { + sb.tables.clear(table); + table = null; + } + + if (table == null) { + // list all tables that we know + int c = 0; + for (final String name: sb.tables) { + try { + if (html) { + prop.putHTML("showtable_tables_" + c + "_table", name); + } + if (xml) { + prop.putXML("showtable_tables_" + c + "_table", name); + } + prop.put("showtable_tables_" + c + "_num", sb.tables.size(name)); + c++; + } catch (final IOException e) { + } + } + prop.put("showtable_tables", c); + prop.put("tablecount", c); + return prop; + } final boolean showpk = post.containsKey("pk"); final String selectKey = post.containsKey("selectKey") ? post.get("selectKey") : null; final String selectValue = (selectKey != null && post.containsKey("selectValue")) ? post.get("selectValue") : null; + final String counts = post.get("count", null); + int maxcount = (counts == null || counts.equals("all")) ? Integer.MAX_VALUE : post.getInt("count", 10); + final String pattern = post.get("search", ""); + final Pattern matcher = (pattern.length() == 0 || pattern.equals(".*")) ? null : Pattern.compile(".*" + pattern + ".*"); + + + if (post.containsKey("deleterows")) { + for (final Map.Entry entry: post.entrySet()) { + if (entry.getValue().startsWith("pk_")) try { + sb.tables.delete(table, entry.getValue().substring(3).getBytes()); + } catch (final IOException e) { + Log.logException(e); + } + } + } + + if (post.containsKey("commitrow")) { + final String pk = post.get("pk"); + final Map map = new HashMap(); + for (final Map.Entry entry: post.entrySet()) { + if (entry.getKey().startsWith("col_")) { + map.put(entry.getKey().substring(4), entry.getValue().getBytes()); + } + } + try { + if (pk == null || pk.length() == 0) { + sb.tables.insert(table, map); + } else { + sb.tables.update(table, pk.getBytes(), map); + } + } catch (final IOException e) { + Log.logException(e); + } catch (final RowSpaceExceededException e) { + Log.logException(e); + } + } + + // generate table + prop.put("showtable", 1); + prop.put("showtable_table", table); + + // insert the columns ArrayList columns = null; try { columns = sb.tables.columns(table); @@ -67,12 +139,6 @@ public class table_p { if (i < columns.size()) columns.add(i, row[i]); } } - - // generate table - prop.put("showtable", 1); - prop.put("showtable_table", table); - - // insert the columns prop.put("showtable_showpk", showpk ? 1 : 0); for (int i = 0; i < columns.size(); i++) { prop.putHTML("showtable_columns_" + i + "_header", columns.get(i)); @@ -80,21 +146,20 @@ public class table_p { prop.put("showtable_columns", columns.size()); // insert all rows - int maxCount; try { - maxCount = Math.min(1000, sb.tables.size(table)); + maxcount = Math.min(maxcount, sb.tables.size(table)); } catch (final IOException e) { Log.logException(e); - maxCount = 0; + maxcount = 0; } int count = 0; try { - final Iterator plainIterator = sb.tables.iterator(table); - final Iterator mapIterator = sb.tables.orderByPK(plainIterator, maxCount).iterator(); + final Iterator plainIterator = sb.tables.iterator(table, matcher); + final Iterator mapIterator = sb.tables.orderByPK(plainIterator, maxcount).iterator(); Tables.Row trow; boolean dark = true; String cellName, cellValue; - rowloop: while ((mapIterator.hasNext()) && (count < maxCount)) { + rowloop: while ((mapIterator.hasNext()) && (count < maxcount)) { trow = mapIterator.next(); if (row == null) continue; prop.put("showtable_list_" + count + "_dark", ((dark) ? 1 : 0) ); dark=!dark; diff --git a/htroot/api/table_p.xml b/htroot/api/table_p.xml index d465d8891..2d447b287 100644 --- a/htroot/api/table_p.xml +++ b/htroot/api/table_p.xml @@ -1,18 +1,24 @@ -#(showtable)#:: - - - #{columns}# - - #{/columns}# - - - #{list}# - + +#(showtable)# + #{tables}# +
+ #{/tables}# +:: +
+ #{columns}# - #[cell]# + #{/columns}# - - #{/list}# - -
-#(/showtable)# \ No newline at end of file + + + #{list}# + + #{columns}# + #[cell]# + #{/columns}# + + #{/list}# + + +#(/showtable)# + \ No newline at end of file diff --git a/source/net/yacy/kelondro/blob/BEncodedHeap.java b/source/net/yacy/kelondro/blob/BEncodedHeap.java index af28b4b08..2be6f34e2 100644 --- a/source/net/yacy/kelondro/blob/BEncodedHeap.java +++ b/source/net/yacy/kelondro/blob/BEncodedHeap.java @@ -7,7 +7,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 @@ -45,9 +45,9 @@ import net.yacy.kelondro.order.ByteOrder; import net.yacy.kelondro.order.Digest; import net.yacy.kelondro.order.NaturalOrder; import net.yacy.kelondro.util.BDecoder; +import net.yacy.kelondro.util.BDecoder.BObject; import net.yacy.kelondro.util.BEncoder; import net.yacy.kelondro.util.FileUtils; -import net.yacy.kelondro.util.BDecoder.BObject; /** * store a table of properties (instead of fixed-field entries) @@ -56,8 +56,8 @@ import net.yacy.kelondro.util.BDecoder.BObject; public class BEncodedHeap implements Map>, Iterable>> { private Heap table; - private LinkedHashSet columnames; - + private final LinkedHashSet columnames; + /** * produce or open a properties table * @param location the file @@ -70,11 +70,11 @@ public class BEncodedHeap implements Map>, Iterable< final File location, final int keylength, final ByteOrder ordering, - int buffermax) throws IOException { + final int buffermax) throws IOException { this.table = new Heap(location, keylength, ordering, buffermax); this.columnames = new LinkedHashSet(); } - + /** * convenience method to open a properies table * @param location the file @@ -86,72 +86,72 @@ public class BEncodedHeap implements Map>, Iterable< this.table = new Heap(location, keylength, NaturalOrder.naturalOrder, 100); this.columnames = new LinkedHashSet(); } - - public byte[] encodedKey(String key) { + + public byte[] encodedKey(final String key) { return Base64Order.enhancedCoder.encodeSubstring(Digest.encodeMD5Raw(key), this.table.keylength); } - + private static class EntryIter implements Iterator>> { HeapReader.entries iter; - public EntryIter(File location, int keylen) throws IOException { - iter = new HeapReader.entries(location, keylen); + public EntryIter(final File location, final int keylen) throws IOException { + this.iter = new HeapReader.entries(location, keylen); } - + public boolean hasNext() { - return iter.hasNext(); + return this.iter.hasNext(); } public Entry> next() { - Map.Entry entry = iter.next(); - Map map = b2m(entry.getValue()); + final Map.Entry entry = this.iter.next(); + final Map map = b2m(entry.getValue()); return new b2mEntry(entry.getKey(), map); } public void remove() { throw new UnsupportedOperationException(); } - + } - + public static class b2mEntry implements Map.Entry> { private final byte[] s; private Map b; - + public b2mEntry(final byte[] s, final Map b) { this.s = s; this.b = b; } - + public byte[] getKey() { - return s; + return this.s; } public Map getValue() { - return b; + return this.b; } - public Map setValue(Map value) { - Map b1 = b; - b = value; + public Map setValue(final Map value) { + final Map b1 = this.b; + this.b = value; return b1; } } - - private static Map b2m(byte[] b) { + + private static Map b2m(final byte[] b) { if (b == null) return null; //System.out.println("b = " + UTF8.String(b)); - BDecoder decoder = new BDecoder(b); - BObject bobj = decoder.parse(); + final BDecoder decoder = new BDecoder(b); + final BObject bobj = decoder.parse(); if (bobj.getType() != BDecoder.BType.dictionary) return null; - Map map = bobj.getMap(); - Map m = new HashMap(); + final Map map = bobj.getMap(); + final Map m = new HashMap(); for (final Map.Entry entry: map.entrySet()) { if (entry.getValue().getType() != BDecoder.BType.string) continue; m.put(entry.getKey(), entry.getValue().getString()); } return m; } - + /** * the map is stored inside a file; this method may return the file * @return the file where the map is stored @@ -167,76 +167,76 @@ public class BEncodedHeap implements Map>, Iterable< public int size() { return this.table.size(); } - + /** * return true if the table is empty */ public boolean isEmpty() { return this.table.size() == 0; } - + /** * check if a row with given key exists in the table * @param name * @return true if the row exists */ - public boolean containsKey(byte[] pk) { + public boolean containsKey(final byte[] pk) { return this.table.containsKey(pk); } - + /** * check if a row with given key exists in the table * This method is here to implement the Map interface * @param name * @return true if the row exists */ - public boolean containsKey(Object key) { + public boolean containsKey(final Object key) { if (key instanceof byte[]) return containsKey((byte[]) key); return false; } - + /** * the containsValue method cannot be used in this method * and is only here to implement the Map interface */ - public boolean containsValue(Object value) { + public boolean containsValue(final Object value) { // this method shall not be used because it is not appropriate for this kind of data throw new UnsupportedOperationException(); } - + /** * get a map from the table * @param name * @return the map if one found or NULL if no entry exists or the entry is corrupt - * @throws RowSpaceExceededException + * @throws RowSpaceExceededException * @throws IOException */ - public Map get(byte[] pk) throws IOException, RowSpaceExceededException { - byte[] b = this.table.get(pk); + public Map get(final byte[] pk) throws IOException, RowSpaceExceededException { + final byte[] b = this.table.get(pk); if (b == null) return null; return b2m(b); } - + /** * get a map from the table * this method is here to implement the Map interface * @param name * @return the map if one found or NULL if no entry exists or the entry is corrupt */ - public Map get(Object key) { + public Map get(final Object key) { if (key instanceof byte[]) try { return get((byte[]) key); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); return null; - } catch (RowSpaceExceededException e) { + } catch (final RowSpaceExceededException e) { Log.logException(e); return null; } return null; } - + /** * convenience method to get a value from a map * @param pk @@ -245,10 +245,10 @@ public class BEncodedHeap implements Map>, Iterable< * @throws IOException * @throws RowSpaceExceededException */ - public byte[] getProp(byte[] pk, String key) throws IOException, RowSpaceExceededException { - byte[] b = this.table.get(pk); + public byte[] getProp(final byte[] pk, final String key) throws IOException, RowSpaceExceededException { + final byte[] b = this.table.get(pk); if (b == null) return null; - Map map = b2m(b); + final Map map = b2m(b); return map.get(key); } @@ -259,12 +259,12 @@ public class BEncodedHeap implements Map>, Iterable< * @param columnMatcher the matcher for the elements of the column * @return a set of primary keys where the matcher matched */ - public Set select(String columnName, Pattern columnMatcher) { - Iterator>> i = iterator(); + public Set select(final String columnName, final Pattern columnMatcher) { + final Iterator>> i = iterator(); Map.Entry> row; Map prop; byte[] val; - Set pks = new TreeSet(this.table.ordering); + final Set pks = new TreeSet(this.table.ordering); while (i.hasNext()) { row = i.next(); prop = row.getValue(); @@ -283,8 +283,8 @@ public class BEncodedHeap implements Map>, Iterable< * @param columnMatcher the matcher for the elements of the column * @return the row where the matcher matched the given column */ - public Map.Entry> selectOne(String columnName, Pattern columnMatcher) { - Iterator>> i = iterator(); + public Map.Entry> selectOne(final String columnName, final Pattern columnMatcher) { + final Iterator>> i = iterator(); Map.Entry> row; Map prop; byte[] val; @@ -298,7 +298,7 @@ public class BEncodedHeap implements Map>, Iterable< } return null; } - + /** * insert a map into the table * this method shall be used in exchange of the get method if the @@ -308,20 +308,20 @@ public class BEncodedHeap implements Map>, Iterable< * @throws RowSpaceExceededException * @throws IOException */ - public void insert(byte[] pk, Map map) throws RowSpaceExceededException, IOException { - byte[] b = BEncoder.encode(BEncoder.transcode(map)); + public void insert(final byte[] pk, final Map map) throws RowSpaceExceededException, IOException { + final byte[] b = BEncoder.encode(BEncoder.transcode(map)); this.table.insert(pk, b); this.columnames.addAll(map.keySet()); } - - public void insert(byte[] pk, String key, byte[] value) throws IOException { - byte[] b = BEncoder.encodeMap(key, value); + + public void insert(final byte[] pk, final String key, final byte[] value) throws IOException { + final byte[] b = BEncoder.encodeMap(key, value); this.table.insert(pk, b); this.columnames.add(key); } - - public void update(byte[] pk, Map map) throws RowSpaceExceededException, IOException { - Map entry = this.get(pk); + + public void update(final byte[] pk, final Map map) throws RowSpaceExceededException, IOException { + final Map entry = this.get(pk); if (entry == null) { insert(pk, map); } else { @@ -329,8 +329,8 @@ public class BEncodedHeap implements Map>, Iterable< insert(pk, entry); } } - - public void update(byte[] pk, String key, byte[] value) throws RowSpaceExceededException, IOException { + + public void update(final byte[] pk, final String key, final byte[] value) throws RowSpaceExceededException, IOException { Map entry = this.get(pk); if (entry == null) { entry = new HashMap(); @@ -347,74 +347,74 @@ public class BEncodedHeap implements Map>, Iterable< * @param name * @param map */ - public Map put(byte[] pk, Map map) { + public Map put(final byte[] pk, final Map map) { try { - Map entry = this.get(pk); - byte[] b = BEncoder.encode(BEncoder.transcode(map)); + final Map entry = this.get(pk); + final byte[] b = BEncoder.encode(BEncoder.transcode(map)); this.table.insert(pk, b); this.columnames.addAll(map.keySet()); return entry; - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); return null; - } catch (RowSpaceExceededException e) { + } catch (final RowSpaceExceededException e) { Log.logException(e); return null; } } - + /** * delete a map from the table * @param name * @throws IOException */ - public void delete(byte[] pk) throws IOException { + public void delete(final byte[] pk) throws IOException { this.table.delete(pk); } - + /** * delete a map from the table * @param name - * @throws RowSpaceExceededException + * @throws RowSpaceExceededException * @throws IOException */ - public Map remove(byte[] key) throws IOException, RowSpaceExceededException { - Map value = get(key); - this.delete(key); + public Map remove(final byte[] key) throws IOException, RowSpaceExceededException { + final Map value = get(key); + delete(key); return value; } - public Map remove(Object key) { + public Map remove(final Object key) { if (key instanceof byte[]) try { return remove((byte[]) key); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); return null; - } catch (RowSpaceExceededException e) { + } catch (final RowSpaceExceededException e) { Log.logException(e); return null; } return null; } - + /** * Copy all the mappings from the specified map to this map. * * @param m mappings to be stored in this map */ - public void putAll(Map> map) { + public void putAll(final Map> map) { for (final Map.Entry> me: map.entrySet()) { try { this.insert(me.getKey(), me.getValue()); - } catch (RowSpaceExceededException e) { + } catch (final RowSpaceExceededException e) { Log.logException(e); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); } } } - + /** * remove all entries from the map; * possibly removes the backend-file @@ -422,11 +422,12 @@ public class BEncodedHeap implements Map>, Iterable< public void clear() { try { this.table.clear(); - } catch (IOException e) { + this.columnames.clear(); + } catch (final IOException e) { Log.logException(e); } } - + /** * close the backen-file. * Should be called explicitely to ensure that all data @@ -435,20 +436,20 @@ public class BEncodedHeap implements Map>, Iterable< public void close() { this.table.close(); } - + /** * Return a Set of the keys contained in this map. * This may not be a useful method, if possible use the keys() * method instead to iterate all keys from the backend-file - * + * * @return a set view of the keys contained in this map */ public Set keySet() { - TreeSet set = new TreeSet(this.table.ordering); + final TreeSet set = new TreeSet(this.table.ordering); try { - Iterator i = this.table.keys(true, false); + final Iterator i = this.table.keys(true, false); while (i.hasNext()) set.add(i.next()); - } catch (IOException e) {} + } catch (final IOException e) {} return set; } @@ -473,7 +474,7 @@ public class BEncodedHeap implements Map>, Iterable< // this method shall not be used because it is not appropriate for this kind of data throw new UnsupportedOperationException(); } - + /** * The abstract method entrySet() from AbstractMap must be implemented, * but never used because that is not useful for this file-based storage class. @@ -482,14 +483,14 @@ public class BEncodedHeap implements Map>, Iterable< * methods must be overriden in this class. These methods are: * size, containsValue, containsKey, get, remove, putAll, clear, * 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 */ public Set>> entrySet() { throw new UnsupportedOperationException(); } - + /** * iterate all rows of the table. * This method implements the @@ -497,20 +498,20 @@ public class BEncodedHeap implements Map>, Iterable< * interface */ public Iterator>> iterator() { - File location = this.table.location(); - int keylen = this.table.keylength(); + final File location = this.table.location(); + final int keylen = this.table.keylength(); try { this.table.flushBuffer(); return new EntryIter(location, keylen); - } catch (IOException e1) { - ByteOrder order = this.table.ordering(); - int buffermax = this.table.getBuffermax(); + } catch (final IOException e1) { + final ByteOrder order = this.table.ordering(); + final int buffermax = this.table.getBuffermax(); this.table.close(); try { - Iterator>> iter = new EntryIter(location, keylen); + final Iterator>> iter = new EntryIter(location, keylen); this.table = new Heap(location, keylen, order, buffermax); return iter; - } catch (IOException e) { + } catch (final IOException e) { Log.logSevere("PropertiesTable", e.getMessage(), e); return null; } @@ -525,11 +526,11 @@ public class BEncodedHeap implements Map>, Iterable< * @return * @throws IOException */ - public static Iterator>> iterator(File location, int keylen) throws IOException { + public static Iterator>> iterator(final File location, final int keylen) throws IOException { return new EntryIter(location, keylen); } - - + + /** * a hashcode for the object */ @@ -552,51 +553,51 @@ public class BEncodedHeap implements Map>, Iterable< this.columnames.addAll(row.getValue().keySet()); } } - ArrayList l = new ArrayList(); + final ArrayList l = new ArrayList(); l.addAll(this.columnames); return l; } - - public static void main(String[] args) { + + public static void main(final String[] args) { if (args.length == 0) { // 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()); if (f.exists()) FileUtils.deletedelete(f); try { - BEncodedHeap map = new BEncodedHeap(f, 4); + final BEncodedHeap map = new BEncodedHeap(f, 4); // put some values into the map - Map m = new HashMap(); + final Map m = new HashMap(); m.put("k", "000".getBytes()); map.insert("123".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 Map.Entry> entry; - Iterator>> i = map.iterator(); + final Iterator>> i = map.iterator(); while (i.hasNext()) { entry = i.next(); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); } // clean up map.close(); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); - } catch (RowSpaceExceededException e) { + } catch (final RowSpaceExceededException e) { Log.logException(e); } } else { - File f = new File(args[0]); + final File f = new File(args[0]); try { Map.Entry> entry; - BEncodedHeap map = new BEncodedHeap(f, 12); - Iterator>> i = map.iterator(); + final BEncodedHeap map = new BEncodedHeap(f, 12); + final Iterator>> i = map.iterator(); while (i.hasNext()) { entry = i.next(); System.out.println(ASCII.String(entry.getKey()) + ": " + entry.getValue()); } map.close(); - } catch (IOException e) { + } catch (final IOException e) { Log.logException(e); } } diff --git a/source/net/yacy/kelondro/blob/Tables.java b/source/net/yacy/kelondro/blob/Tables.java index 30d9827ef..32db61977 100644 --- a/source/net/yacy/kelondro/blob/Tables.java +++ b/source/net/yacy/kelondro/blob/Tables.java @@ -51,7 +51,7 @@ import net.yacy.kelondro.util.FileUtils; import net.yacy.kelondro.util.LookAheadIterator; -public class Tables { +public class Tables implements Iterable { private static final String suffix = ".bheap"; private static final String system_table_pkcounter = "pkcounter"; @@ -88,7 +88,8 @@ public class Tables { } } - public Iterator tables() { + @Override + public Iterator iterator() { return this.tables.keySet().iterator(); } @@ -104,17 +105,20 @@ public class Tables { } public void clear(final String tablename) { - BEncodedHeap heap = null; try { - heap = getHeap(tablename); - if (heap != null) heap.clear(); - heap.close(); + BEncodedHeap heap = getHeap(tablename); + if (heap != null) { + final File f = heap.getFile(); + heap.clear(); + heap.close(); + FileUtils.deletedelete(f); + heap = null; + } } catch (final IOException e) { + Log.logException(e); + } finally { + this.tables.remove(tablename); } - heap = null; - final File f = new File(this.location, tablename + suffix); - this.tables.remove(tablename); - FileUtils.deletedelete(f); } public boolean hasHeap(final String tablename) { @@ -137,6 +141,14 @@ public class Tables { return heap; } + /** + * get the total number of known tables + * @return + */ + public int size() { + return this.tables.size(); + } + public int size(final String table) throws IOException { final BEncodedHeap heap = getHeap(table); return heap.size(); @@ -344,7 +356,7 @@ public class Tables { public RowIterator(final String table, final String whereColumn, final Pattern wherePattern) throws IOException { this.whereColumn = whereColumn; this.whereValue = null; - this.wherePattern = wherePattern; + this.wherePattern = wherePattern == null || wherePattern.toString().length() == 0 ? null : wherePattern; final BEncodedHeap heap = getHeap(table); this.i = heap.iterator(); } @@ -359,7 +371,7 @@ public class Tables { public RowIterator(final String table, final Pattern pattern) throws IOException { this.whereColumn = null; this.whereValue = null; - this.wherePattern = pattern; + this.wherePattern = pattern == null || pattern.toString().length() == 0 ? null : pattern; final BEncodedHeap heap = getHeap(table); this.i = heap.iterator(); } @@ -541,4 +553,5 @@ public class Tables { Log.logException(e); } } + }