diff options
author | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:41 +0000 |
---|---|---|
committer | Andrej Shadura <andrewsh@debian.org> | 2019-03-09 22:30:41 +0000 |
commit | 38212b3127e90751fb39cda34250bc11be62b76c (patch) | |
tree | dc1397346030e9695bd763dddc93b3be527cd643 /elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java | |
parent | 337087b668d3a54f3afee3a9adb597a32e9f7e94 (diff) |
Import Upstream version 0.7.0
Diffstat (limited to 'elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java')
-rw-r--r-- | elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java b/elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java new file mode 100644 index 00000000..da13c5fa --- /dev/null +++ b/elki/src/main/java/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java @@ -0,0 +1,224 @@ +package de.lmu.ifi.dbs.elki.database; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2015 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Collection; + +import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; +import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; +import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; +import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; +import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.relation.DBIDView; +import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.datasource.DatabaseConnection; +import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection; +import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; +import de.lmu.ifi.dbs.elki.index.Index; +import de.lmu.ifi.dbs.elki.index.IndexFactory; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.logging.statistics.Duration; +import de.lmu.ifi.dbs.elki.utilities.documentation.Description; +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; + +/** + * This database class uses array-based storage and thus does not allow for + * dynamic insert, delete and update operations. However, array access is + * expected to be faster and use less memory. + * + * @author Arthur Zimek + * @author Erich Schubert + * + * @apiviz.landmark + * @apiviz.composedOf ArrayStaticDBIDs + * @apiviz.uses DatabaseConnection + */ +@Description("Database using an in-memory hashtable and at least providing linear scans.") +public class StaticArrayDatabase extends AbstractDatabase { + /** + * Our logger + */ + private static final Logging LOG = Logging.getLogger(StaticArrayDatabase.class); + + /** + * IDs of this database + */ + private ArrayStaticDBIDs ids; + + /** + * The DBID representation we use + */ + private DBIDView idrep; + + /** + * The data source we get the initial data from. + */ + protected DatabaseConnection databaseConnection; + + /** + * Constructor. + * + * @param databaseConnection Database connection to get the initial data from. + * @param indexFactories Indexes to add + */ + public StaticArrayDatabase(DatabaseConnection databaseConnection, Collection<IndexFactory<?, ?>> indexFactories) { + super(); + this.databaseConnection = databaseConnection; + this.ids = null; + this.idrep = null; + + // Add indexes. + if(indexFactories != null) { + this.indexFactories.addAll(indexFactories); + } + } + + /** + * Constructor with no indexes. + */ + public StaticArrayDatabase() { + this(null, null); + } + + /** + * Initialize the database by getting the initial data from the database + * connection. + */ + @Override + public void initialize() { + if(databaseConnection != null) { + if(LOG.isDebugging()) { + LOG.debugFine("Loading data from database connection."); + } + MultipleObjectsBundle bundle = databaseConnection.loadData(); + // Run at most once. + databaseConnection = null; + + // Find DBIDs for bundle + { + DBIDs bids = bundle.getDBIDs(); + if(bids instanceof ArrayStaticDBIDs) { + this.ids = (ArrayStaticDBIDs) bids; + } + else if(bids == null) { + this.ids = DBIDUtil.generateStaticDBIDRange(bundle.dataLength()); + } + else { + this.ids = (ArrayStaticDBIDs) DBIDUtil.makeUnmodifiable(bids); + } + } + // Replace id representation (it would be nicer if we would not need + // DBIDView at all) + this.idrep = new DBIDView(this.ids); + relations.add(this.idrep); + getHierarchy().add(this, idrep); + + DBIDArrayIter it = this.ids.iter(); + + int numrel = bundle.metaLength(); + for(int i = 0; i < numrel; i++) { + SimpleTypeInformation<?> meta = bundle.meta(i); + @SuppressWarnings("unchecked") + SimpleTypeInformation<Object> ometa = (SimpleTypeInformation<Object>) meta; + WritableDataStore<Object> store = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_DB, ometa.getRestrictionClass()); + for(it.seek(0); it.valid(); it.advance()) { + store.put(it, bundle.data(it.getOffset(), i)); + } + Relation<?> relation = new MaterializedRelation<>(ometa, ids, null, store); + relations.add(relation); + getHierarchy().add(this, relation); + + // Try to add indexes where appropriate + for(IndexFactory<?, ?> factory : indexFactories) { + if(factory.getInputTypeRestriction().isAssignableFromType(ometa)) { + @SuppressWarnings("unchecked") + final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory; + @SuppressWarnings("unchecked") + final Relation<Object> orep = (Relation<Object>) relation; + final Index index = ofact.instantiate(orep); + Duration duration = LOG.isStatistics() ? LOG.newDuration(index.getClass().getName() + ".construction").begin() : null; + index.initialize(); + if(duration != null) { + LOG.statistics(duration.end()); + } + getHierarchy().add(relation, index); + } + } + } + + // fire insertion event + eventManager.fireObjectsInserted(ids); + } + } + + @Override + protected Logging getLogger() { + return LOG; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer extends AbstractDatabase.Parameterizer { + /** + * Holds the database connection to get the initial data from. + */ + protected DatabaseConnection databaseConnection = null; + + /** + * Indexes to add. + */ + private Collection<IndexFactory<?, ?>> indexFactories; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + // Get database connection. + final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class); + 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)) { + indexFactories = indexFactoryP.instantiateClasses(config); + } + } + + @Override + protected StaticArrayDatabase makeInstance() { + return new StaticArrayDatabase(databaseConnection, indexFactories); + } + } +} |