/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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; version 2 of the License. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Jan 3, 2007 */ package com.bigdata.rdf.store; import java.nio.ByteBuffer; import java.util.Enumeration; import java.util.Properties; import java.util.UUID; import org.apache.log4j.Logger; import com.bigdata.io.DirectBufferPool; import com.bigdata.journal.BufferMode; import com.bigdata.journal.IIndexManager; import com.bigdata.journal.IIndexStore; import com.bigdata.journal.ITx; import com.bigdata.journal.Journal; import com.bigdata.journal.TemporaryStore; import com.bigdata.rdf.inf.TruthMaintenance; import com.bigdata.rdf.sail.BigdataSail; import com.bigdata.rdf.spo.SPORelation; import com.bigdata.relation.locator.DefaultResourceLocator; import com.bigdata.service.IBigdataFederation; import com.bigdata.util.PropertyUtil; /** * A temporary triple store based on the <em>bigdata</em> architecture. Data * is buffered in memory but will overflow to disk for large stores. The backing * store is a {@link TemporaryStore}. * <p> * Note: the {@link TempTripleStore} declares indices that do NOT support * isolation. This offers a significant performance boost when you do not need * transactions or the ability to purge historical data versions from the store * as they age. * <p> * Note: Users of the {@link TempTripleStore} may find it worthwhile to turn off * a variety of options in order to minimize the time and space burden of the * temporary store depending on the use which will be made of it, including * {@link Options#LEXICON} and {@link Options#ONE_ACCESS_PATH}. * <p> * Note: Multiple KBs MAY be created in the backing {@link TemporaryStore} but * all MUST be assigned the {@link TemporaryStore#getUUID()} as their prefix in * order to avoid possible conflicts within a global namespace. This is * especially important when the relations in the {@link TemporaryStore} are * resolvable by an {@link IBigdataFederation} or {@link Journal}. * <p> * Note: This class is often used to support inference. When so used, the * statement indices are populated with the term identifiers from the main * database and the {@link SPORelation} in the {@link TempTripleStore} is * disabled using {@link Options#LEXICON}. * <p> * Note: If you want an in-memory {@link ITripleStore} that supports commit and * abort then use a {@link LocalTripleStore} and specify * {@link com.bigdata.journal.Options#BUFFER_MODE} as * {@link BufferMode#Temporary} or as {@link BufferMode#Transient} if you want * the triple store to begin in memory and overflow to disk if necessary. Both * of these configurations provide full concurrency control and group commit. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TempTripleStore extends AbstractLocalTripleStore { final static private Logger log = Logger.getLogger(TempTripleStore.class); private final TemporaryStore store; public TemporaryStore getIndexManager() { return store; } /** * NOP. * <p> * Note: since multiple {@link TempTripleStore}s may be created on the same * backing {@link TemporaryStore} it is NOT safe to perform a * {@link TemporaryStore#checkpoint()}. There is no coordination of write * access to the indices so the checkpoint can not be atomic. Therefore this * method is a NOP and {@link #abort()} will throw an exception. */ final public long commit() { // final long begin = System.currentTimeMillis(); return super.commit(); // final long checkpointAddr = getIndexManager().checkpoint(); // // final long elapsed = System.currentTimeMillis() - begin; // // if (log.isInfoEnabled()) // log.info("latency=" + elapsed + "ms, checkpointAddr=" // + checkpointAddr); } /** * Not supported. * * @throws UnsupportedOperationException */ final public void abort() { throw new UnsupportedOperationException(); // super.abort(); // // // discard the write sets. // getIndexManager().restoreLastCheckpoint(); } final public boolean isStable() { return store.isStable(); } /** * Causes the {@link TempTripleStore} to be {@link #destroy()}ed, but does * not reclaim space in the backing {@link TemporaryStore} and does not * close the backing {@link TemporaryStore}. */ final public void close() { // store.close(); destroy(); super.close(); } // /** // * Deletes the backing {@link TemporaryStore}, thereby destroying all // * {@link TempTripleStore}s on that {@link TemporaryStore}. After calling // * this method you will see an {@link IllegalStateException} if you attempt // * further operations on {@link TempTripleStore}s that were backed by the // * backing {@link TemporaryStore}. // */ // final public void __tearDownUnitTest() { // // store.destroy(); // // super.__tearDownUnitTest(); // // } /** * * @todo define options for {@link TemporaryStore} and then extend them * here. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> */ public static interface Options extends AbstractTripleStore.Options { //, TemporaryStore.Options { } /** * Create a transient {@link ITripleStore} backed by a new * {@link TemporaryStore}. * * @param properties * See {@link Options}. * * @deprecated by * {@link TempTripleStore#TempTripleStore(TemporaryStore, Properties, AbstractTripleStore)} * which permits you to reuse the same backing * {@link TemporaryStore} instance until it becomes full. */ public TempTripleStore(final Properties properties) { this(properties, null); } /** * Create a transient {@link ITripleStore} backed by a new * {@link TemporaryStore}. The {@link ITripleStore} will default its * properties based on those specified for the optional <i>db</i> and then * override those defaults using the given <i>properties</i>. * <p> * Note: This variant is especially useful when the {@link TempTripleStore} * will have its own lexicon and you need it to be compatible with the * lexicon for the <i>db</i>. * <p> * Note: When <i>db</i> is non-<code>null</code>, the relations on the * {@link TempTripleStore} will be locatable by the specified <i>db</i>. * * @param properties * Overrides for the database's properties. * @param db * The optional database (a) will establish the defaults for the * {@link TempTripleStore}; and (b) will be able to locate * relations declared on the backing {@link TemporaryStore}. * * @deprecated Use * {@link #TempTripleStore(TemporaryStore, Properties, AbstractTripleStore)} * instead and provide the {@link TemporaryStore} reference * returned by {@link IIndexStore#getTempStore()}. This has the * advantage of reusing a single shared {@link TemporaryStore} * instance until it becomes "large" and then allocating a new * instance (note that each instance will consume a direct * {@link ByteBuffer} from the {@link DirectBufferPool}). This * is especially important for operations like * {@link TruthMaintenance} which have to create a lot of * temporary stores. */ public TempTripleStore(final Properties properties, final AbstractTripleStore db) { this(new TemporaryStore(), properties, db); } /** * Variant for creating a(nother) {@link TempTripleStore} on the same * {@link TemporaryStore}. The {@link TempTripleStore} will have its own * namespace. * * @param store * The {@link TemporaryStore}. * @param properties * Overrides for the database's properties. * @param db * The optional database (a) will establish the defaults for the * {@link TempTripleStore}; and (b) will be able to locate * relations declared on the backing {@link TemporaryStore}. */ public TempTripleStore(final TemporaryStore store, final Properties properties, final AbstractTripleStore db) { this(store, db == null ? properties : stackProperties(properties, store, db)); if (log.isInfoEnabled()) { log.info("new temporary store: " + store.getFile() + ", namespace=" + getNamespace()); } if (db != null) { ((DefaultResourceLocator<?>) db.getIndexManager() .getResourceLocator()).add(store); } /* * Create the KB for this ctor variant! */ create(); } /** * Note: This is here just to make it easy to have the reference to the * [store] and its [uuid] when we create one in the calling ctor. */ private TempTripleStore(final TemporaryStore store, final Properties properties) { this(store, UUID.randomUUID() + "kb", ITx.UNISOLATED, properties); } /** * Ctor specified by {@link DefaultResourceLocator}. * * @param indexManager * @param namespace * @param timestamp * @param properties */ public TempTripleStore(final IIndexManager indexManager, final String namespace, final Long timestamp, final Properties properties) { super(indexManager, namespace, timestamp, properties); store = (TemporaryStore) indexManager; if(log.isInfoEnabled()) { log.info("view on existing temporary store: "+store.getUUID()); } } /** * Stacks the <i>properties</i> on top of the <i>db</i>'s properties so that * the databases properties will be treated as defaults and anything in * <i>properties</i> will override anything in database's properties. * <p> * Note: This also ensures that the {@link TempTripleStore} has a unique * namespace name based on the namespace of the main triple store instance * plus the {@link UUID} of the {@link TemporaryStore}. This addresses a * problem where the {@link TempTripleStore} could otherwise be located by * the DefaultResourceLocator after an abort() had cleared the * DefaultResourceLocator cache of the unisolated view of the main triple * store. See BLZG-2023, BLZG-2041. * * @param properties * The properties for the {@link TempTripleStore}. * @param db * The database from which we will obtain default properties. * * @return The stacked properties. */ private static Properties stackProperties(final Properties properties, final TemporaryStore tempStore, final AbstractTripleStore db) { final Properties out = new Properties(); final Properties in = PropertyUtil.flatCopy(properties); final Enumeration<Object> e = in.keys(); while (e.hasMoreElements()) { final Object ekey = e.nextElement(); if (!(ekey instanceof String)) { continue; } final String key = (String) ekey; final String val = in.getProperty(key); // FIXME BLZG-2023, BLZG-2041 if (BigdataSail.Options.NAMESPACE.equals(key)) { // Ensure that the TempTripleStore has a unique namespace. out.setProperty(key, val + "_temporaryStore=" + tempStore.getUUID()); } else { out.setProperty(key, val); } } return out; } /** * This store is NOT safe for concurrent operations on an * {@link ITx#UNISOLATED} index. However, it does support concurrent readers * on the {@link ITx#READ_COMMITTED} view of an index. */ public boolean isConcurrent() { return false; } }