/**
* IndexTable
* Copyright 2014 by Michael Peter Christen
* First released 11.11.2014 at http://yacy.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.kelondro.table;
import java.io.File;
import java.io.IOException;
import net.yacy.cora.order.NaturalOrder;
import net.yacy.cora.util.SpaceExceededException;
import net.yacy.kelondro.index.Row;
import net.yacy.kelondro.util.kelondroException;
/**
* this is a stored index for primary keys. Each key is associated to a single long value
*/
public class IndexTable {
private final Table table;
/**
* create an index with given (fixed) key and value length
* @param location
* @param keysize
* @param payloadsize
* @param useTailCache
* @param exceed134217727
* @throws IOException
*/
public IndexTable(
final File location, int keysize, int payloadsize,
final boolean useTailCache,
final boolean exceed134217727) throws IOException {
final Row row = new Row(
"byte[] key-" + keysize + ", " +
"long num-" + payloadsize + " {b256}",
NaturalOrder.naturalOrder);
Table t;
try {
t = new Table(location, row, 1024*1024, 0, useTailCache, exceed134217727, true);
} catch (final SpaceExceededException e) {
try {
t = new Table(location, row, 0, 0, false, exceed134217727, true);
} catch (kelondroException | SpaceExceededException e1) {
throw new IOException(e);
}
}
this.table = t;
}
/**
* Write an index entry. All written values are persistent.
* @param key
* @param value
* @return
* @throws IOException
*/
public Long put(final byte[] key, final long value) throws IOException {
final Row.Entry entry = table.row().newEntry();
entry.setCol(0, key);
entry.setCol(1, value);
Row.Entry oldentry;
try {
oldentry = table.replace(entry);
if (oldentry == null) return null;
return oldentry.getColLong(1);
} catch (SpaceExceededException e) {
throw new IOException(e);
}
}
/**
* get a value from the index
* @param key
* @return the value of the relation or -1 if that does not exist
* @throws IOException
*/
public long get(final byte[] key) throws IOException {
final Row.Entry entry = table.get(key, false);
if (entry == null) return -1;
Long l = entry.getColLong(1);
return l == null ? -1 : l.longValue();
}
/**
* check if a given value exists in the index. The check is very efficient because all operations are done in the RAM.
* @param key
* @return true if the key already existed, false otherwise
*/
public boolean has(final byte[] key) {
return table.has(key);
}
/**
* remove a given key from the index
* @param key
* @return the previous value of the relation
* @throws IOException
*/
public Long remove(final byte[] key) throws IOException {
final Row.Entry entry = table.remove(key);
if (entry == null) return null;
return entry.getColLong(1);
}
/**
* clear the index
* @throws IOException
*/
public void clear() throws IOException {
this.table.clear();
}
/**
* close the index. must be called to finally write all data to disc
*/
public void close() {
this.table.close();
}
}