All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.rdf.sail.CreateKBTask Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

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 Apr 13, 2011
 */
package com.bigdata.rdf.sail;

import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.log4j.Logger;

import com.bigdata.ha.HAGlue;
import com.bigdata.ha.QuorumService;
import com.bigdata.journal.IIndexManager;
import com.bigdata.journal.IJournal;
import com.bigdata.journal.ITransactionService;
import com.bigdata.journal.ITx;
import com.bigdata.journal.Journal;
import com.bigdata.quorum.AsynchronousQuorumCloseException;
import com.bigdata.quorum.Quorum;
import com.bigdata.rdf.store.AbstractTripleStore;
import com.bigdata.rdf.store.LocalTripleStore;
import com.bigdata.rdf.store.ScaleOutTripleStore;
import com.bigdata.rdf.task.AbstractApiTask;
import com.bigdata.util.InnerCause;

/**
 * Task creates a KB for the given namespace iff no such KB exists. The correct
 * use of this class is as follows:
 * 
 * 
 * AbstractApiTask.submitApiTask(indexManager, new CreateKBTask(namespace, properties)).get();
 * 
* * @see DestroyKBTask * @author Bryan Thompson */ public class CreateKBTask extends AbstractApiTask { private static final transient Logger log = Logger .getLogger(CreateKBTask.class); // private final IIndexManager indexManager; /** * The effective properties that will be used to create the namespace. */ private final Properties properties; /** * Return the effective properties that will be used to create the namespace. */ protected Properties getProperties() { return properties; } public CreateKBTask(final String namespace, final Properties properties) { super(namespace, ITx.UNISOLATED, true/* isGRSRequired */); if (properties == null) throw new IllegalArgumentException(); // Use the caller's properties as the default. this.properties = new Properties(properties); // override the namespace. this.properties.setProperty(BigdataSail.Options.NAMESPACE, namespace); } @Override final public boolean isReadOnly() { return false; } @Override public Void call() throws Exception { try { doRun(); } catch (Throwable t) { if (InnerCause.isInnerCause(t, AsynchronousQuorumCloseException.class)) { /* * The quorum is closed, so we stopped trying. * * Note: This can also happen if the quorum has not been started * yet. The HAJournalServer explicitly invokes the CreateKBTask * when entering "RunMet" in order to handle this case. */ log.warn(t); } else { log.error(t, t); } throw new Exception(t); } return null; } /** * Note: This process is not robust if the leader is elected and becomes * HAReady and then fails over before the KB is created. The task should be * re-submitted by the new leader once that leader is elected. */ private void doRun() { final IIndexManager indexManager = getIndexManager(); if (indexManager instanceof IJournal) { /* * Create a local triple store. * * Note: This hands over the logic to some custom code located * on the BigdataSail. */ final IJournal jnl = (IJournal) indexManager; final Quorum> quorum = jnl .getQuorum(); boolean isSoloOrLeader; if (quorum == null) { isSoloOrLeader = true; } else { /* * Wait for a quorum meet. */ final long token; try { long tmp = quorum.token(); if (tmp == Quorum.NO_QUORUM) { // Only log if we are going to wait. log.warn("Awaiting quorum."); tmp = quorum.awaitQuorum(); } token = tmp; assert token != Quorum.NO_QUORUM; } catch (AsynchronousQuorumCloseException e1) { throw new RuntimeException(e1); } catch (InterruptedException e1) { throw new RuntimeException(e1); } /* * Now wait until the service is HAReady. */ try { jnl.awaitHAReady(Long.MAX_VALUE, TimeUnit.NANOSECONDS); } catch (AsynchronousQuorumCloseException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } catch (TimeoutException e) { throw new RuntimeException(e); } if (quorum.getMember().isLeader(token)) { isSoloOrLeader = true; } else { isSoloOrLeader = false; } final IJournal journal = jnl; if (journal.isGroupCommit() && journal.getRootBlockView().getCommitCounter() == 0L) { /* * Force the GRS to be materialized. This is necessary for the * initial KB create when using group commit and HA. (For HA the * initial KB create is single threaded within the context of the * leader election. However, this is not true for a standalone * Journal.) * * Note: This logic will fail if AbstractTask uses a * DefaultResourceLocator that is based on the HAJournal and not * on an IsolatedActionJournal because that will allow the * GlobalRowStoreHelper.getGlobalRowStore() method to registerr * the GSR index on the unisolated Name2Addr rather than the n2a * class inside of the AbstractTask. */ journal.getGlobalRowStore(); journal.commit(); } } if (isSoloOrLeader) { // Attempt to resolve the namespace. if (indexManager.getResourceLocator().locate(namespace, ITx.UNISOLATED) == null) { if(log.isInfoEnabled()) log.info("Creating KB instance: namespace=" + namespace); // create the appropriate as configured triple/quad store. createLTS(jnl, getProperties()); if(log.isInfoEnabled()) log.info("Created tripleStore: " + namespace); } // if( tripleStore == null ) } } else { // Attempt to resolve the namespace. if (indexManager.getResourceLocator() .locate(namespace, ITx.UNISOLATED) == null) { /* * Register triple store for scale-out. */ if (log.isInfoEnabled()) log.info("Creating KB instance: namespace=" + namespace); final ScaleOutTripleStore lts = new ScaleOutTripleStore( indexManager, namespace, ITx.UNISOLATED, getProperties()); lts.create(); if (log.isInfoEnabled()) log.info("Created tripleStore: " + namespace); } // if( tripleStore == null ) } } /** * Create an {@link AbstractTripleStore} instance against a local database. *

* Note: For group commit, the caller will be holding the resource lock for * the namespace. * * @param indexManager * @param properties * @return */ private AbstractTripleStore createLTS(final IJournal indexManager, final Properties properties) { final ITransactionService txService = indexManager .getLocalTransactionManager().getTransactionService(); final String namespace = properties.getProperty( BigdataSail.Options.NAMESPACE, BigdataSail.Options.DEFAULT_NAMESPACE); // throws an exception if there are inconsistent properties BigdataSail.checkProperties(properties); /** * Note: Unless group commit is enabled, we need to make this operation * mutually exclusive with KB level writers in order to avoid the * possibility of a triggering a commit during the middle of a * BigdataSailConnection level operation (or visa versa). * * Note: When group commit is not enabled, the indexManager will be a * Journal class. When it is enabled, it will merely implement the * IJournal interface. * * @see #1143 (Isolation broken in NSS when groupCommit disabled) */ final boolean isGroupCommit = indexManager.isGroupCommit(); boolean acquiredConnection = false; try { if (!isGroupCommit) { try { // acquire the unisolated connection permit. ((Journal) indexManager).acquireUnisolatedConnection(); acquiredConnection = true; } catch (InterruptedException e) { throw new RuntimeException(e); } } // Check for pre-existing instance. { final LocalTripleStore lts = (LocalTripleStore) indexManager .getResourceLocator().locate(namespace, ITx.UNISOLATED); if (lts != null) { return lts; } } // Create a new instance. { if (Boolean.parseBoolean(properties.getProperty( BigdataSail.Options.ISOLATABLE_INDICES, BigdataSail.Options.DEFAULT_ISOLATABLE_INDICES))) { /* * Isolatable indices: requires the use of a tx to create the KB * instance. */ final long txCreate = txService.newTx(ITx.UNISOLATED); boolean ok = false; try { final AbstractTripleStore txCreateView = new LocalTripleStore( indexManager, namespace, Long.valueOf(txCreate), properties); // create the kb instance within the tx. txCreateView.create(); // commit the tx. txService.commit(txCreate); ok = true; } finally { if (!ok) txService.abort(txCreate); } } else { /* * Create KB without isolatable indices. */ final LocalTripleStore lts = new LocalTripleStore(indexManager, namespace, ITx.UNISOLATED, properties); lts.create(); } } /* * Now that we have created the instance, either using a tx or the * unisolated connection, locate the triple store resource and return * it. */ { final LocalTripleStore lts = (LocalTripleStore) indexManager .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 (IOException ex) { throw new RuntimeException(ex); } finally { if (!isGroupCommit && acquiredConnection) { /** * When group commit is not enabled, we need to release the * unisolated connection. * * @see #1143 (Isolation broken in NSS when groupCommit disabled) */ ((Journal) indexManager).releaseUnisolatedConnection(); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy