/**
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.util.Properties;
import org.apache.log4j.Logger;
import com.bigdata.btree.BTree;
import com.bigdata.journal.IIndexManager;
import com.bigdata.journal.IJournal;
import com.bigdata.journal.ITx;
import com.bigdata.journal.Journal;
import com.bigdata.journal.TimestampUtility;
import com.bigdata.relation.locator.DefaultResourceLocator;
/**
* A triple store based on the <em>bigdata</em> architecture. This class
* offers extremely low latency for index operations. All indices are local
* (in-process) objects and there are no concurrency controls, so point tests on
* the indices are extremely efficient. Significant parallelism is achieved by
* paying careful attention to the concurrency constraints imposed by the
* {@link BTree} class (writers are single threaded, reads may be concurrent,
* but not concurrent with a writer) and by using different views (unisolated vs
* read-historical) of the indices when computing entailments or performing
* high-level query.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
*/
public class LocalTripleStore extends AbstractLocalTripleStore {
final static private Logger log = Logger.getLogger(LocalTripleStore.class);
private final IJournal store;
/**
* The backing embedded database.
*/
@Override
public IJournal getIndexManager() {
return store;
}
/**
* Delegates the operation to the backing store.
*/
@Override
synchronized public long commit() {
final long begin = System.currentTimeMillis();
super.commit();
final IIndexManager indexManager = getIndexManager();
if (indexManager.isGroupCommit()) {
/*
* Note: GROUP_COMMIT (#566) requires that the WriteExecutorService
* controls when commit points are melded. If group commit is enabled
* and the index manager is directs the Journal to commit() then any
* partially executed tasks that have checkpointed indices will be
* immediately flushed to the backing store, breaking the ACID
* semantics of the commit.
*
* Note: The checkpoint of the indices for an unisolated AbstractTask
* occurs when the task is done with its work but is still holding any
* resource locks.
*/
return 0L;
}
final long commitTime = getIndexManager().commit();
final long elapsed = System.currentTimeMillis() - begin;
if (log.isInfoEnabled())
log.info("commit: commit latency=" + elapsed + "ms");
return commitTime;
}
@Override
synchronized public void abort() {
super.abort();
// discard the write sets.
getIndexManager().abort();
}
@Override
public boolean isStable() {
return store.isStable();
}
@Override
public boolean isReadOnly() {
return super.isReadOnly() || store.isReadOnly();
}
@Override
public void close() {
super.close();
if(!isReadOnly()) {
store.shutdown();
}
}
// public void __tearDownUnitTest() {
//
// super.__tearDownUnitTest();
//
// if(!isReadOnly()) {
//
// store.destroy();
//
// }
//
// }
/**
* Options understood by the {@link LocalTripleStore}.
*
* @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a>
*/
public static interface Options extends AbstractTripleStore.Options {
}
/**
* Ctor specified by {@link DefaultResourceLocator}.
*
* @param indexManager (must be an {@link IJournal}).
* @param namespace
* @param timestamp
* @param properties
*/
public LocalTripleStore(final IIndexManager indexManager,
final String namespace, final Long timestamp,
final Properties properties) {
super(indexManager, namespace, timestamp, properties);
if (indexManager instanceof IJournal) {
store = (IJournal) indexManager;
} else {
/*
* Hitting this code path may indicate that a TemporaryStore was
* added to the DefaultResourceLocator as a "seeAlso" store to be
* checked and a TempTripleStore was created on that TemporaryStore
* under the same namespace as the LocalTripleStore. If the
* LocalTripleStore is then destroyed or an abort() otherwise clears
* it from the DefaultResourceLocator cache, then the
* TempTripleStore having the same namespace can be discovered on
* the TemporaryStore. This will cause an attempt to instantiate the
* LocalTripleStore on the TemporaryStore, which will fail here.
*/
throw new UnsupportedOperationException("Not an IJournal: indexManager=" + indexManager + ", namespace="
+ namespace + ", timestamp=" + TimestampUtility.toString(timestamp) + ", properties=" + properties);
}
}
/**
* Create or re-open a triple store using a local embedded database.
* <p>
* Note: This is only used by the test suites.
*/
/* public */static LocalTripleStore getInstance(final Properties properties) {
final String namespace = "kb";
// create/re-open journal.
final Journal journal = new Journal(properties);
try {
// Check for pre-existing instance.
{
final LocalTripleStore lts = (LocalTripleStore) journal
.getResourceLocator().locate(namespace, ITx.UNISOLATED);
if (lts != null) {
return lts;
}
}
// Create a new instance.
{
final LocalTripleStore lts = new LocalTripleStore(
journal, namespace, ITx.UNISOLATED, properties);
// if (Boolean.parseBoolean(properties.getProperty(
// BigdataSail.Options.ISOLATABLE_INDICES,
// BigdataSail.Options.DEFAULT_ISOLATABLE_INDICES))) {
//
// final long txCreate = txService.newTx(ITx.UNISOLATED);
//
// final AbstractTripleStore txCreateView = new LocalTripleStore(
// journal, namespace, Long.valueOf(txCreate), properties);
//
// // create the kb instance within the tx.
// txCreateView.create();
//
// // commit the tx.
// txService.commit(txCreate);
//
// } else {
lts.create();
// }
}
/*
* Now that we have created the instance locate the triple store
* resource and return it.
*/
{
final LocalTripleStore lts = (LocalTripleStore) journal
.getResourceLocator().locate(namespace, ITx.UNISOLATED);
if (lts == null) {
/*
* This should only occur if there is a concurrent destroy,
* which is highly unlikely to say the least.
*/
throw new RuntimeException("Concurrent create/destroy: "
+ namespace);
}
return lts;
}
} catch (Throwable ex) {
journal.shutdownNow();
throw new RuntimeException(ex);
}
// /*
// * FIXME This should pass up the existing properties for the KB instance
// * when the KB instance is pre-existing. Really though, you should first
// * obtain the Journal and then attempt to locate the KB and create it if
// * it does not exist.
// */
// this(new Journal(properties), "kb"/* namespace */, ITx.UNISOLATED,
// properties);
//
// /*
// * FIXME Modify this to use a row scan for the contained relations.
// * There is one other place where the same test is being used. The
// * reason for this test is that getSPORelation() tries to _locate_ the
// * relation, but that will fail if it does not exist. By using the ctor
// * and exists() we can test for pre-existence. However, the best route
// * is to perform a row scan when the container is created and then we
// * can just materialize the existing relations and create them if they
// * are not found.
// */
// if (!new SPORelation(getIndexManager(), getNamespace() + "."
// + SPORelation.NAME_SPO_RELATION, getTimestamp(), getProperties()).exists()) {
//
// /*
// * If we could not find the SPO relation then presume that this is a
// * new KB and create it now.
// */
//
// create();
//
// } else {
//
// init();
//
// }
}
/**
* When using an {@link ITx#UNISOLATED} view, this store is NOT safe for
* write operations concurrent with either readers or writers. However, it
* does support concurrent readers for {@link ITx#READ_COMMITTED} and
* read-historical views.
*/
@Override
public boolean isConcurrent() {
return getTimestamp() == ITx.UNISOLATED;
}
}