/*******************************************************************************
* Copyright (c) 2008 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source$
* Created by: Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
* Created on: Jan 17, 2008
* Revision: $Id$
*
* Contributors:
* Cambridge Semantics Incorporated - initial API and implementation
*******************************************************************************/
package org.openanzo.datasource.nodecentric.internal;
import java.io.StringWriter;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.datatype.XMLGregorianCalendar;
import org.openanzo.datasource.IServerQuadStore;
import org.openanzo.datasource.IStoredNamedGraph;
import org.openanzo.datasource.StoredNamedGraph;
import org.openanzo.datasource.nodecentric.sql.GlitterRdbWrapper;
import org.openanzo.datasource.nodecentric.sql.LastTransactionTime;
import org.openanzo.datasource.nodecentric.sql.NamedGraphRdbWrapper;
import org.openanzo.datasource.update.NamedGraphType;
import org.openanzo.datasource.update.ServerUpdateTransaction;
import org.openanzo.datasource.update.UpdateChanges;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.CompoundAnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.exceptions.LogUtils;
import org.openanzo.jdbc.container.sql.BaseSQL;
import org.openanzo.jdbc.utils.ClosableIterator;
import org.openanzo.jdbc.utils.RdbException;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.MemTypedLiteral;
import org.openanzo.rdf.RDFFormat;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.Constants.GRAPHS;
import org.openanzo.rdf.Constants.NAMESPACES;
import org.openanzo.rdf.datatype.TypeMaps;
import org.openanzo.rdf.utils.ReadWriteUtils;
import org.openanzo.rdf.utils.UriGenerator;
import org.openanzo.services.IUpdateResultListener;
import org.openanzo.services.IUpdates;
import org.openanzo.services.Privilege;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A QuadStore for the server that dispatches operations to different underlying stores, as well as storing changes within deltas
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com</a>)
*
*/
class DispatchingDeltaQuadStore implements IServerQuadStore {
protected static final Logger log = LoggerFactory.getLogger(DispatchingDeltaQuadStore.class);
private final URI instanceURI;
private final HashMap<URI, NamedGraphType> namedGraphToType = new HashMap<URI, NamedGraphType>();
private final Map<URI, IStoredNamedGraph> storedNamedGraphs = new HashMap<URI, IStoredNamedGraph>();
private final NodeCentricServerQuadStore revisionedQuadStore;
private final NodeCentricServerQuadStore nonRevisionedQuadStore;
private final NodeCentricOperationContext context;
private Long transactionId = null;
private Map<Value, Long> storedNodes = null;
private Map<URI, URI> resolvedUUIDS = null;
private Map<URI, Long> graphIds = null;
private Map<Long, URI> graphUris = null;
private final Collection<IUpdateResultListener> datasourceUpdateResultListeners;
private final Map<URI, URI> removedNamedGraphs = new HashMap<URI, URI>();
private static final String STMTS_TMP = "STMTS_TMP";
private static final String STMT_ID_TMP = "STMT_ID_TMP";
private static final String NAMEDGRAPH_IDS_TEMP = "NAMEDGRAPH_IDS_TEMP";
private boolean direct;
public DispatchingDeltaQuadStore(NodeCentricOperationContext context, URI instanceURI, Collection<IUpdateResultListener> datasourceUpdateResultListeners) {
this.instanceURI = instanceURI;
this.context = context;
try {
direct = (context.getAttribute("dispatchUpdate") != null) ? context.getAttribute("dispatchUpdate", Boolean.class) : false;
} catch (AnzoException ae) {
direct = false;
}
this.revisionedQuadStore = new NodeCentricServerQuadStore(context, true, direct);
this.nonRevisionedQuadStore = new NodeCentricServerQuadStore(context, false, direct);
this.datasourceUpdateResultListeners = datasourceUpdateResultListeners;
namedGraphToType.put(GRAPHS.GRAPHS_DATASET, NamedGraphType.REVISIONED);
namedGraphToType.put(GRAPHS.METADATA_GRAPHS_DATASET, NamedGraphType.REVISIONED);
}
public NodeCentricOperationContext getContext() {
return context;
}
public URI getInstanceURI() {
return instanceURI;
}
public void close() throws AnzoException {
revisionedQuadStore.close();
nonRevisionedQuadStore.close();
}
public void fireUpdatesToListeners(IUpdates updates) throws AnzoException {
for (IUpdateResultListener listener : datasourceUpdateResultListeners) {
listener.updateComplete(context, updates);
}
}
public void abort() throws AnzoException {
try {
if (context.getConnection().isClosed()) {
context.getDatasource().abort(context.getConnection(), false, true);
context.getDatasource().rebindWriteContext(context);
} else {
context.getDatasource().abort(context.getConnection(), false, true);
}
} catch (SQLException sqle) {
log.error(LogUtils.RDB_MARKER, "Error aborting connection", sqle);
//new AnzoException(ExceptionConstants.ERROR_TAGS.DATASOURCE_ERROR | ExceptionConstants.ERROR_TAGS.RDB_ERROR, ExceptionConstants.RDB.FAILED_ROLLBACK_RDB_TRANSACTION, sqle);
}
context.getDatasource().begin(context.getConnection(), false, true);
revisionedQuadStore.abort();
nonRevisionedQuadStore.abort();
context.getNodeLayout().abortReferencedIds(context.getConnection(), transactionId);
NamedGraphRdbWrapper.purgelockedNamedGraph(context.getStatementProvider(), context.getConnection(), transactionId);
LastTransactionTime.abortTransactions(context.getStatementProvider(), context.getConnection(), transactionId);
try {
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), STMTS_TMP);
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), STMT_ID_TMP);
} catch (RdbException sqle) {
log.error(LogUtils.RDB_MARKER, "Error truncating tables", sqle);
}
context.getDatasource().commit(context.getConnection(), false, true);
storedNamedGraphs.clear();
graphIds.clear();
graphUris.clear();
resolvedUUIDS = null;
}
public void prepareForUpdate() throws AnzoException {
context.getDatasource().begin(context.getConnection(), false, true);
for (URI uri : namedGraphToType.keySet().toArray(new URI[0])) {
IStoredNamedGraph graph = getStoredNamedGraph(uri);
if (graph == null && !removedNamedGraphs.containsKey(uri)) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.NOT_FOUND, uri.toString());
}
}
context.getDatasource().commit(context.getConnection(), false, true);
HashSet<Value> values = new HashSet<Value>();
if (context.getOperationPrincipal() != null && context.getOperationPrincipal().getUserURI() != null) {
values.add(context.getOperationPrincipal().getUserURI());
}
for (Statement statement : revisionedQuadStore.getAdditions()) {
values.add(statement.getNamedGraphUri());
values.add(statement.getSubject());
values.add(statement.getPredicate());
values.add(statement.getObject());
}
for (Statement statement : nonRevisionedQuadStore.getAdditions()) {
values.add(statement.getNamedGraphUri());
values.add(statement.getSubject());
values.add(statement.getPredicate());
values.add(statement.getObject());
}
if (values.size() > 0) {
storedNodes = new HashMap<Value, Long>();
Value valsArray[] = values.toArray(new Value[0]);
for (int i = 0; (i * NodeCentricDatasource.MAX_OPERATION_SIZE) <= valsArray.length; i++) {
int offset = (i * NodeCentricDatasource.MAX_OPERATION_SIZE);
Set<Value> subSet = null;
if (valsArray.length > NodeCentricDatasource.MAX_OPERATION_SIZE) {
subSet = new LinkedHashSet<Value>();
for (int k = offset; k < Math.min(offset + NodeCentricDatasource.MAX_OPERATION_SIZE, valsArray.length); k++) {
subSet.add(valsArray[k]);
}
} else {
subSet = values;
}
try {
context.getDatasource().begin(context.getConnection(), true, true);
storedNodes.putAll(context.getNodeLayout().resolveStoredNodes(subSet, true, context.getConnection(), transactionId));
context.getDatasource().commit(context.getConnection(), true, true);
} catch (AnzoException ae) {
context.getDatasource().abort(context.getConnection(), true, true);
throw ae;
}
}
}
}
public void commitTransaction(ServerUpdateTransaction currentTransactionUpdateResults, Collection<URI> namedGraphs) throws AnzoException {
try {
context.getDatasource().begin(context.getConnection(), true, true);
LastTransactionTime.insertLastTransactionTime(context.getStatementProvider(), context.getConnection(), currentTransactionUpdateResults.getTransactionTimestamp());
context.getDatasource().commit(context.getConnection(), true, true);
} catch (RdbException sqle) {
try {
abort();
} catch (AnzoException ae2) {
throw new CompoundAnzoException(sqle, ae2);
}
throw sqle;
}
try {
context.getDatasource().begin(context.getConnection(), true, true);
context.getNodeLayout().commitReferencedIds(context.getConnection(), transactionId);
context.getDatasource().commit(context.getConnection(), true, true);
revisionedQuadStore.commit(currentTransactionUpdateResults);
nonRevisionedQuadStore.commit(currentTransactionUpdateResults);
context.getDatasource().begin(context.getConnection(), false, true);
LastTransactionTime.updateTransaction(context.getStatementProvider(), context.getConnection(), currentTransactionUpdateResults.getTransactionTimestamp(), transactionId);
try {
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), STMTS_TMP);
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), STMT_ID_TMP);
} catch (RdbException sqle) {
log.warn(LogUtils.RDB_MARKER, "Error truncating tables", sqle);
}
context.getDatasource().commit(context.getConnection(), false, true);
storedNamedGraphs.clear();
unlockNamedGraphs(namedGraphs);
graphIds.clear();
graphUris.clear();
resolvedUUIDS = null;
} catch (AnzoException sqle) {
try {
abort();
} catch (AnzoException ae2) {
throw new CompoundAnzoException(sqle, ae2);
}
throw sqle;
}
}
private void unlockNamedGraphs(Collection<URI> namedGraphs) throws AnzoException {
NamedGraphRdbWrapper.BatchUnlockNamedGraph stmt = new NamedGraphRdbWrapper.BatchUnlockNamedGraph(context.getConnection(), context.getStatementProvider());
try {
for (URI ngURI : namedGraphs) {
Long id = graphIds.get(ngURI);
if (id == null) {
id = context.getNodeLayout().fetchId(ngURI, context.getConnection());
}
if (id != null) {
stmt.addEntry(id, transactionId);
}
}
context.getDatasource().begin(context.getConnection(), false, true);
stmt.executeStatement();
context.getDatasource().commit(context.getConnection(), false, true);
} catch (RdbException sqle) {
context.getDatasource().abort(context.getConnection(), false, true);
throw new AnzoException(ExceptionConstants.DATASOURCE.FAILED_EXECUTE_BATCH, sqle);
} finally {
try {
stmt.close();
} catch (RdbException sqle) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Error closing statement", sqle);
}
}
}
}
public void addNewNamedGraph(URI namedGraphUri, URI metadataGraphUri, URI uuid, NamedGraphType type) throws AnzoException {
namedGraphToType.put(namedGraphUri, type);
namedGraphToType.put(metadataGraphUri, type);
IStoredNamedGraph graph = new StoredNamedGraph(true, type, namedGraphUri, metadataGraphUri, uuid, Long.valueOf(0), null, null);
storedNamedGraphs.put(namedGraphUri, graph);
storedNamedGraphs.put(metadataGraphUri, graph);
switch (type) {
case REVISIONED:
revisionedQuadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.revisionedProperty, MemTypedLiteral.create(Boolean.valueOf(true)), metadataGraphUri));
revisionedQuadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.persistedProperty, MemTypedLiteral.create(Boolean.valueOf(true)), metadataGraphUri));
break;
case NON_REVISIONED_PERSISTED:
nonRevisionedQuadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.revisionedProperty, MemTypedLiteral.create(Boolean.valueOf(false)), metadataGraphUri));
nonRevisionedQuadStore.add(Constants.valueFactory.createStatement(namedGraphUri, org.openanzo.ontologies.openanzo.NamedGraph.persistedProperty, MemTypedLiteral.create(Boolean.valueOf(true)), metadataGraphUri));
break;
}
}
private void updateNamedGraphRevision(IStoredNamedGraph storedGraph, URI lastModifiedBy, long transactionStart) throws AnzoException {
if (!storedGraph.isNewGraph()) {
remove(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.revisionProperty, Constants.valueFactory.createTypedLiteral(storedGraph.getRevision()), storedGraph.getMetaURI()));
}
if (!storedGraph.isNewGraph()) {
if (storedGraph.getLastModifiedBy() != null && !lastModifiedBy.equals(storedGraph.getLastModifiedBy())) {
if (storedGraph.getLastModifiedBy() != null) {
remove(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.lastModifiedByUserProperty, storedGraph.getLastModifiedBy(), storedGraph.getMetaURI()));
}
}
if (storedGraph.getLastModifiedTime() != null && transactionStart != storedGraph.getLastModifiedTime()) {
if (storedGraph.getLastModifiedTime() != null) {
XMLGregorianCalendar cal = TypeMaps.getXMLCaledar(storedGraph.getLastModifiedTime());
remove(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.modifiedProperty, Constants.valueFactory.createTypedLiteral(cal), storedGraph.getMetaURI()));
}
}
}
add(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.revisionProperty, Constants.valueFactory.createTypedLiteral(storedGraph.getNewRevision()), storedGraph.getMetaURI()));
add(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.lastModifiedByUserProperty, lastModifiedBy, storedGraph.getMetaURI()));
storedGraph.setLastModifiedBy(lastModifiedBy);
XMLGregorianCalendar cal = TypeMaps.getXMLCaledar(transactionStart);
add(Constants.valueFactory.createStatement(storedGraph.getURI(), org.openanzo.ontologies.openanzo.NamedGraph.modifiedProperty, Constants.valueFactory.createTypedLiteral(cal), storedGraph.getMetaURI()));
storedGraph.setLastModifiedTime(transactionStart);
NamedGraphType type = storedGraph.getNamedGraphType();
if (type == null) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.NOT_FOUND, storedGraph.getURI().toString());
}
switch (type) {
case REVISIONED:
revisionedQuadStore.updateNamedGraphRevision(storedGraph);
break;
case NON_REVISIONED_PERSISTED:
nonRevisionedQuadStore.updateNamedGraphRevision(storedGraph);
break;
}
}
public void removeNamedGraph(URI namedGraphUri, URI uuid, long transactionStart) throws AnzoException {
NamedGraphType type = getNamedGraphType(namedGraphUri);
if (type == null) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.NOT_FOUND, namedGraphUri.toString());
}
IStoredNamedGraph graph = getStoredNamedGraph(namedGraphUri);
switch (type) {
case REVISIONED:
revisionedQuadStore.removeNamedGraph(namedGraphUri, transactionStart, graph.getRevision());
break;
case NON_REVISIONED_PERSISTED:
nonRevisionedQuadStore.removeNamedGraph(namedGraphUri, transactionStart, graph.getRevision());
break;
}
removedNamedGraphs.put(namedGraphUri, uuid);
}
public void insertUpdates(UpdateChanges updateResults, long transactionStart, URI userURI) throws AnzoException {
prepareForUpdate();
//context.getDatasource().begin(context.getConnection(), false, true);
HashSet<IStoredNamedGraph> modifiedGraphs = new HashSet<IStoredNamedGraph>();
try {
UpdateChanges revUpdates = revisionedQuadStore.update(storedNamedGraphs, storedNodes);
UpdateChanges nonrevUpdates = nonRevisionedQuadStore.update(storedNamedGraphs, storedNodes);
updateResults.addedStatements.addAll(revUpdates.addedStatements);
updateResults.addedStatements.addAll(nonrevUpdates.addedStatements);
updateResults.namedGraphs.addAll(nonrevUpdates.namedGraphs);
updateResults.namedGraphs.addAll(revUpdates.namedGraphs);
modifiedGraphs.addAll(revUpdates.namedGraphs);
modifiedGraphs.addAll(nonrevUpdates.namedGraphs);
updateResults.removedStatements.addAll(revUpdates.removedStatements);
updateResults.removedStatements.addAll(nonrevUpdates.removedStatements);
// context.getDatasource().commit(context.getConnection(), false, true);
} catch (AnzoException ae) {
//context.getDatasource().abort(context.getConnection(), false, true);
throw ae;
}
revisionedQuadStore.precommit();
nonRevisionedQuadStore.precommit();
for (IStoredNamedGraph storedGraph : modifiedGraphs) {
updateNamedGraphRevision(storedGraph, userURI, transactionStart);
}
prepareForUpdate();
//context.getDatasource().begin(context.getConnection(), false, true);
revisionedQuadStore.executeNamedGraphsUpdates();
nonRevisionedQuadStore.executeNamedGraphsUpdates();
try {
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), NodeCentricServerQuadStore.REMOVE_GRAPHS_TMP);
} catch (RdbException sqle) {
log.warn(LogUtils.RDB_MARKER, "Error truncating tables", sqle);
}
try {
UpdateChanges revUpdates = revisionedQuadStore.update(storedNamedGraphs, storedNodes);
UpdateChanges nonrevUpdates = nonRevisionedQuadStore.update(storedNamedGraphs, storedNodes);
updateResults.addedStatements.addAll(revUpdates.addedStatements);
updateResults.addedStatements.addAll(nonrevUpdates.addedStatements);
updateResults.namedGraphs.addAll(nonrevUpdates.namedGraphs);
updateResults.namedGraphs.addAll(revUpdates.namedGraphs);
modifiedGraphs.addAll(revUpdates.namedGraphs);
modifiedGraphs.addAll(nonrevUpdates.namedGraphs);
updateResults.removedStatements.addAll(revUpdates.removedStatements);
updateResults.removedStatements.addAll(nonrevUpdates.removedStatements);
// context.getDatasource().commit(context.getConnection(), false, true);
} catch (AnzoException ae) {
// context.getDatasource().abort(context.getConnection(), false, true);
throw ae;
}
for (IStoredNamedGraph storedGraph : modifiedGraphs) {
storedGraph.commitNewRevision();
}
updateResults.removedNamedGraphs.putAll(removedNamedGraphs);
}
public void add(Statement... statements) throws AnzoException {
for (Statement stmt : statements) {
NamedGraphType type = getNamedGraphType(stmt.getNamedGraphUri());
if (type == null) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.NOT_FOUND, stmt.getNamedGraphUri().toString());
}
switch (type) {
case REVISIONED:
revisionedQuadStore.add(stmt);
break;
case NON_REVISIONED_PERSISTED:
nonRevisionedQuadStore.add(stmt);
break;
}
}
}
public void remove(Statement... statements) throws AnzoException {
for (Statement stmt : statements) {
NamedGraphType type = getNamedGraphType(stmt.getNamedGraphUri());
if (type == null) {
throw new AnzoException(ExceptionConstants.DATASOURCE.NAMEDGRAPH.NOT_FOUND, stmt.getNamedGraphUri().toString());
}
switch (type) {
case REVISIONED:
revisionedQuadStore.remove(stmt);
break;
case NON_REVISIONED_PERSISTED:
nonRevisionedQuadStore.remove(stmt);
break;
}
}
}
private NamedGraphType getNamedGraphType(URI namedGraphUri) throws AnzoException {
NamedGraphType type = namedGraphToType.get(namedGraphUri);
if (type == null) {
if (revisionedQuadStore.containsNamedGraph(namedGraphUri)) {
namedGraphToType.put(namedGraphUri, NamedGraphType.REVISIONED);
type = NamedGraphType.REVISIONED;
return type;
} else if (nonRevisionedQuadStore.containsNamedGraph(namedGraphUri)) {
namedGraphToType.put(namedGraphUri, NamedGraphType.NON_REVISIONED_PERSISTED);
type = NamedGraphType.NON_REVISIONED_PERSISTED;
return type;
}
}
return type;
}
public boolean containsNamedGraph(URI namedGraphURI) throws AnzoException {
if (UriGenerator.isMetadataGraphUri(namedGraphURI)) {
namedGraphURI = UriGenerator.stripEncapsulatedURI(NAMESPACES.METADATAGRAPH_PREFIX, namedGraphURI);
}
if (resolvedUUIDS != null && resolvedUUIDS.containsKey(namedGraphURI)) {
return true;
}
NamedGraphType type = getNamedGraphType(namedGraphURI);
if (type == null) {
return false;
} else {
return true;
}
}
public URI getNamedGraphUUID(URI namedGraphURI) throws AnzoException {
if (UriGenerator.isMetadataGraphUri(namedGraphURI)) {
namedGraphURI = UriGenerator.stripEncapsulatedURI(NAMESPACES.METADATAGRAPH_PREFIX, namedGraphURI);
}
if (resolvedUUIDS != null && resolvedUUIDS.containsKey(namedGraphURI)) {
return resolvedUUIDS.get(namedGraphURI);
}
NamedGraphType type = getNamedGraphType(namedGraphURI);
if (type == null)
return null;
switch (type) {
case REVISIONED:
return revisionedQuadStore.getNamedGraphUUID(namedGraphURI);
case NON_REVISIONED_PERSISTED:
return nonRevisionedQuadStore.getNamedGraphUUID(namedGraphURI);
}
return null;
}
public void beginTransaction(Long transactionId, URI transactionURI, Collection<URI> namedGraphs, Collection<Statement> transactionContext) throws AnzoException {
// SelectCurrentTimestampResult timestampResult = LastTransactionTime.selectCurrentTimestamp(context.getStatementProvider(), context.getConnection());
this.transactionId = transactionId;
Long tid = context.getNodeLayout().store(transactionURI, context.getConnection(), transactionId);
String cntx = null;
if (transactionContext != null && transactionContext.size() > 0) {
StringWriter tc = new StringWriter();
ReadWriteUtils.writeStatements(transactionContext, tc, RDFFormat.JSON);
cntx = tc.toString();
}
LastTransactionTime.insertTransaction(context.getStatementProvider(), context.getConnection(), transactionId, context.getDatasource().getInstanceId(), tid, cntx);
revisionedQuadStore.beginTransaction(this.transactionId);
nonRevisionedQuadStore.beginTransaction(this.transactionId);
graphIds = new HashMap<URI, Long>();
graphUris = new HashMap<Long, URI>();
resolvedUUIDS = new HashMap<URI, URI>();
boolean ok = lockNamedgraphs(namedGraphs);
int retryCount = 600;
while (!ok && retryCount-- > 0) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Could not lock the necessary namedGraphs");
}
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
throw new AnzoException(ExceptionConstants.CORE.INTERRUPTED);
}
ok = lockNamedgraphs(namedGraphs);
}
if (!ok) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "Could not get a lock on the NamedGraphs. Aborting");
}
throw new AnzoException(ExceptionConstants.DATASOURCE.NO_LOCK_NAMEDGRAPHS, Arrays.toString(namedGraphs.toArray(new URI[0])));
}
if (graphIds.size() > 25) {
for (Map.Entry<URI, Long> entry : graphIds.entrySet()) {
graphUris.put(entry.getValue(), entry.getKey());
}
GlitterRdbWrapper.BatchInsertGraphSysAdmin batch = null;
try {
context.getDatasource().begin(context.getConnection(), false, true);
batch = new GlitterRdbWrapper.BatchInsertGraphSysAdmin(context.getConnection(), context.getStatementProvider(), context.getConfiguration().getSessionPrefix(), NAMEDGRAPH_IDS_TEMP);
for (Long id : graphIds.values()) {
batch.addEntry(id);
}
batch.executeStatement();
Set<Long> ids = new HashSet<Long>();
HashMap<Long, Long> uuids = new HashMap<Long, Long>();
ClosableIterator<NamedGraphRdbWrapper.SelectNamedGraphRevisionedBatchResult> iterator = NamedGraphRdbWrapper.selectNamedGraphRevisionedBatch(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), NAMEDGRAPH_IDS_TEMP);
ArrayList<NamedGraphRdbWrapper.SelectNamedGraphRevisionedBatchResult> revisionedResults = new ArrayList<NamedGraphRdbWrapper.SelectNamedGraphRevisionedBatchResult>();
for (NamedGraphRdbWrapper.SelectNamedGraphRevisionedBatchResult result : iterator) {
revisionedResults.add(result);
uuids.put(result.getUuid(), result.getId());
ids.add(result.getUuid());
ids.add(result.getId());
ids.add(result.getMetaId());
ids.add(result.getLastModifiedBy());
}
iterator.close();
ClosableIterator<NamedGraphRdbWrapper.SelectNamedGraphNonRevisionedBatchResult> iterator2 = NamedGraphRdbWrapper.selectNamedGraphNonRevisionedBatch(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), NAMEDGRAPH_IDS_TEMP);
ArrayList<NamedGraphRdbWrapper.SelectNamedGraphNonRevisionedBatchResult> nonrevisionedResults = new ArrayList<NamedGraphRdbWrapper.SelectNamedGraphNonRevisionedBatchResult>();
for (NamedGraphRdbWrapper.SelectNamedGraphNonRevisionedBatchResult result : iterator2) {
nonrevisionedResults.add(result);
uuids.put(result.getUuid(), result.getId());
ids.add(result.getUuid());
ids.add(result.getId());
ids.add(result.getMetaId());
ids.add(result.getLastModifiedBy());
}
iterator2.close();
Map<Long, URI> resolved = context.getNodeLayout().getNodeURILayout().resolveStoredIds(ids, context.getConnection());
for (Map.Entry<Long, Long> entry : uuids.entrySet()) {
URI graphUri = graphUris.get(entry.getKey());
resolvedUUIDS.put(graphUri, resolved.get(entry.getValue()));
}
for (NamedGraphRdbWrapper.SelectNamedGraphRevisionedBatchResult result : revisionedResults) {
URI namedGraphUri = resolved.get(result.getId());
URI metaUri = resolved.get(result.getMetaId());
URI uuidURI = resolved.get(result.getUuid());
Long revision = result.getRevision();
Long hStart = result.getHstart();
URI userURI = resolved.get(result.getLastModifiedBy());
storedNamedGraphs.put(namedGraphUri, new StoredNamedGraph(false, NamedGraphType.REVISIONED, namedGraphUri, metaUri, uuidURI, revision, userURI, hStart));
}
for (NamedGraphRdbWrapper.SelectNamedGraphNonRevisionedBatchResult result : nonrevisionedResults) {
URI namedGraphUri = resolved.get(result.getId());
URI metaUri = resolved.get(result.getMetaId());
URI uuidURI = resolved.get(result.getUuid());
Long revision = result.getRevision();
Long hStart = result.getHstart();
URI userURI = resolved.get(result.getLastModifiedBy());
storedNamedGraphs.put(namedGraphUri, new StoredNamedGraph(false, NamedGraphType.NON_REVISIONED_PERSISTED, namedGraphUri, metaUri, uuidURI, revision, userURI, hStart));
}
context.getDatasource().commit(context.getConnection(), false, true);
} catch (RdbException sqle) {
context.getDatasource().abort(context.getConnection(), false, true);
} finally {
try {
if (batch != null) {
batch.close();
}
} catch (RdbException sqle) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "error closing batch statement", sqle);
}
}
try {
BaseSQL.truncateTableWithSessionMayCommit(context.getStatementProvider(), context.getConnection(), context.getConfiguration().getSessionPrefix(), STMTS_TMP);
} catch (RdbException sqle) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "error truncating table", sqle);
}
}
}
}
}
private boolean lockNamedgraphs(Collection<URI> namedGraphs) throws AnzoException {
NamedGraphRdbWrapper.BatchLockNamedGraph stmt = new NamedGraphRdbWrapper.BatchLockNamedGraph(context.getConnection(), context.getStatementProvider());
try {
context.getDatasource().begin(context.getConnection(), true, true);
if (namedGraphs.size() > 100) {
graphIds.putAll(context.getNodeLayout().getNodeURILayout().resolveStoredNodes(namedGraphs, true, context.getConnection(), transactionId));
} else {
for (URI uri : namedGraphs) {
graphIds.put(uri, context.getNodeLayout().store(uri, context.getConnection(), transactionId));
}
}
for (Long id : graphIds.values()) {
stmt.addEntry(id, transactionId);
}
stmt.executeStatement();
context.getDatasource().commit(context.getConnection(), true, true);
return true;
} catch (RdbException sqle) {
context.getDatasource().abort(context.getConnection(), true, true);
return false;
} finally {
try {
stmt.close();
} catch (RdbException sqle) {
if (log.isDebugEnabled()) {
log.debug(LogUtils.RDB_MARKER, "error closing statement", sqle);
}
}
}
}
private IStoredNamedGraph getStoredNamedGraph(URI namedGraphUri) throws AnzoException {
IStoredNamedGraph graph = storedNamedGraphs.get(namedGraphUri);
if (graph == null) {
if (UriGenerator.isMetadataGraphUri(namedGraphUri)) {
namedGraphUri = UriGenerator.stripEncapsulatedURI(NAMESPACES.METADATAGRAPH_PREFIX, namedGraphUri);
}
NamedGraphType type = getNamedGraphType(namedGraphUri);
if (type == null)
return null;
switch (type) {
case REVISIONED:
graph = revisionedQuadStore.getStoredNamedGraph(namedGraphUri);
break;
case NON_REVISIONED_PERSISTED:
graph = nonRevisionedQuadStore.getStoredNamedGraph(namedGraphUri);
break;
}
if (graph != null) {
storedNamedGraphs.put(namedGraphUri, graph);
storedNamedGraphs.put(graph.getMetaURI(), graph);
}
}
return graph;
}
public void addAcl(URI namedGraphUri, URI Role, org.openanzo.services.Privilege privilege) throws AnzoException {
}
public void removeAcl(URI namedGraphUri, URI Role, Privilege privilege) throws AnzoException {
}
}