summaryrefslogtreecommitdiff
path: root/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java')
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java99
1 files changed, 43 insertions, 56 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
index 26f18bce..541d59fc 100644
--- a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2013
+ Copyright (C) 2014
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,11 +29,11 @@ import java.util.Collection;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.DBIDView;
@@ -50,15 +50,13 @@ import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
- * Provides a mapping for associations based on a Hashtable and functions to get
- * the next usable ID for insertion, making IDs reusable after deletion of the
- * entry.
+ * Database storing data using hashtable storage, and thus allowing additional
+ * and removal of objects.
*
* @author Arthur Zimek
* @author Erich Schubert
@@ -67,7 +65,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @apiviz.composedOf HashSetModifiableDBIDs
*/
@Description("Database using an in-memory hashtable and at least providing linear scans.")
-public class HashmapDatabase extends AbstractDatabase implements UpdatableDatabase, Parameterizable {
+public class HashmapDatabase extends AbstractDatabase implements UpdatableDatabase {
/**
* Our logger
*/
@@ -103,7 +101,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
this.addChildResult(idrep);
// Add indexes.
- if (indexFactories != null) {
+ if(indexFactories != null) {
this.indexFactories.addAll(indexFactories);
}
}
@@ -121,7 +119,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
*/
@Override
public void initialize() {
- if (databaseConnection != null) {
+ if(databaseConnection != null) {
this.insert(databaseConnection.loadData());
// Run at most once.
databaseConnection = null;
@@ -130,50 +128,37 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
@Override
public DBIDs insert(ObjectBundle objpackages) {
- if (objpackages.dataLength() == 0) {
+ if(objpackages.dataLength() == 0) {
return DBIDUtil.EMPTYDBIDS;
}
// insert into db
ArrayModifiableDBIDs newids = DBIDUtil.newArray(objpackages.dataLength());
Relation<?>[] targets = alignColumns(objpackages);
- int idrepnr = -1;
- for (int i = 0; i < targets.length; i++) {
- if (targets[i] == idrep) {
- idrepnr = i;
- break;
- }
- }
-
- for (int j = 0; j < objpackages.dataLength(); j++) {
+ DBIDVar var = DBIDUtil.newVar();
+ for(int j = 0; j < objpackages.dataLength(); j++) {
// insert object
- final DBID newid;
- if (idrepnr < 0) {
- newid = DBIDUtil.generateSingleDBID();
- } else {
- newid = (DBID) objpackages.data(j, idrepnr);
+ if(!objpackages.assignDBID(j, var)) {
+ var.set(DBIDUtil.generateSingleDBID());
}
- if (ids.contains(newid)) {
+ if(ids.contains(var)) {
throw new AbortException("Duplicate DBID conflict.");
}
- ids.add(newid);
- for (int i = 0; i < targets.length; i++) {
- // DBIDs were handled above.
- if (i == idrepnr) {
- continue;
- }
+ ids.add(var);
+ for(int i = 0; i < targets.length; i++) {
@SuppressWarnings("unchecked")
final Relation<Object> relation = (Relation<Object>) targets[i];
- relation.set(newid, objpackages.data(j, i));
+ relation.set(var, objpackages.data(j, i));
}
- newids.add(newid);
+ newids.add(var);
}
// Notify indexes of insertions
- for (Index index : indexes) {
- if (index instanceof DynamicIndex) {
+ for(Index index : indexes) {
+ if(index instanceof DynamicIndex) {
((DynamicIndex) index).insertAll(newids);
- } else {
+ }
+ else {
LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
}
}
@@ -195,19 +180,19 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
Relation<?>[] targets = new Relation<?>[pack.metaLength()];
{
BitSet used = new BitSet(relations.size());
- for (int i = 0; i < targets.length; i++) {
+ for(int i = 0; i < targets.length; i++) {
SimpleTypeInformation<?> meta = pack.meta(i);
// TODO: aggressively try to match exact metas first?
// Try to match unused representations only
- for (int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) {
+ for(int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) {
Relation<?> relation = relations.get(j);
- if (relation.getDataTypeInformation().isAssignableFromType(meta)) {
+ if(relation.getDataTypeInformation().isAssignableFromType(meta)) {
targets[i] = relation;
used.set(j);
break;
}
}
- if (targets[i] == null) {
+ if(targets[i] == null) {
targets[i] = addNewRelation(meta);
used.set(relations.size() - 1);
}
@@ -229,8 +214,8 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
relations.add(relation);
getHierarchy().add(this, relation);
// Try to add indexes where appropriate
- for (IndexFactory<?, ?> factory : indexFactories) {
- if (factory.getInputTypeRestriction().isAssignableFromType(meta)) {
+ for(IndexFactory<?, ?> factory : indexFactories) {
+ if(factory.getInputTypeRestriction().isAssignableFromType(meta)) {
@SuppressWarnings("unchecked")
final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory;
@SuppressWarnings("unchecked")
@@ -254,22 +239,23 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
public MultipleObjectsBundle delete(DBIDs ids) {
// Prepare bundle to return
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
- for (Relation<?> relation : relations) {
+ for(Relation<?> relation : relations) {
ArrayList<Object> data = new ArrayList<>(ids.size());
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
data.add(relation.get(iter));
}
bundle.appendColumn(relation.getDataTypeInformation(), data);
}
// remove from db
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
doDelete(iter);
}
// Remove from indexes
- for (Index index : indexes) {
- if (index instanceof DynamicIndex) {
+ for(Index index : indexes) {
+ if(index instanceof DynamicIndex) {
((DynamicIndex) index).deleteAll(ids);
- } else {
+ }
+ else {
LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
}
@@ -290,15 +276,16 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
public SingleObjectBundle delete(DBIDRef id) {
// Prepare bundle to return
SingleObjectBundle bundle = new SingleObjectBundle();
- for (Relation<?> relation : relations) {
+ for(Relation<?> relation : relations) {
bundle.append(relation.getDataTypeInformation(), relation.get(id));
}
doDelete(id);
// Remove from indexes
- for (Index index : indexes) {
- if (index instanceof DynamicIndex) {
+ for(Index index : indexes) {
+ if(index instanceof DynamicIndex) {
((DynamicIndex) index).delete(id);
- } else {
+ }
+ else {
LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
}
}
@@ -317,9 +304,9 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
// Remove id
ids.remove(id);
// Remove from all representations.
- for (Relation<?> relation : relations) {
+ for(Relation<?> relation : relations) {
// ID has already been removed, and this would loop...
- if (relation != idrep) {
+ if(relation != idrep) {
relation.delete(id);
}
}
@@ -354,12 +341,12 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
super.makeOptions(config);
// Get database connection.
final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class);
- if (config.grab(dbcP)) {
+ if(config.grab(dbcP)) {
databaseConnection = dbcP.instantiateClass(config);
}
// Get indexes.
final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<>(INDEX_ID, IndexFactory.class, true);
- if (config.grab(indexFactoryP)) {
+ if(config.grab(indexFactoryP)) {
indexFactories = indexFactoryP.instantiateClasses(config);
}
}