blob: 234d8cb57676fc5c74a894914dfbd6ed4c976d75 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jena.system;
import java.util.Objects;
import org.apache.jena.query.TxnType;
import org.apache.jena.sparql.JenaTransactionException;
import org.apache.jena.sparql.core.Transactional;
public class TxnOp {
/* Transaction compatibility:
* A TxnType is compatible with (can run inside) another TxType if:
* READ < PROMOTE (either) < WRITE
*
* So
* Inner is READ works with any outer.
* Outer is WRITE works with any inner.
*/
/**
* Check whether a {@link TxnType} is compatible with another.
* Typically the "inner" transaction is a requested new transaction
* and the outer one an existing transaction.
*
* Throw an exception if not compatible.
*
* @see #isTxnTypeCompatible
* @see #compatibleWithPromote
*
* @param innerTxnType
* @param outerTxnType
* @throws JenaTransactionException
*/
public static void txnTypeCompatibleEx(TxnType innerTxnType, TxnType outerTxnType) {
boolean b = isTxnTypeCompatible(innerTxnType, outerTxnType);
if ( ! b )
throw new JenaTransactionException("Already in a transaction of an incompatable type: "+"outer="+outerTxnType+" : inner="+innerTxnType);
}
/** Check whether a {@link TxnType} is compatible with another.
* Typically then "inner" transaction is a requested new transaction
* and the outer one an existing transaction.
*
* A TxnType is compatible with (can run inside) another TxnType (for an an existing or outer transaction) if:
* the outer one covers the needs of the inner one <br/>
* READ &lt; PROMOTE (either) &lt; WRITE &lt; no outer
*
* In particular:
* Inner is READ works with any outer.
* Outer is WRITE works with any inner.
*
* For promoting if necessary, see {@link #compatibleWithPromote}
*
* @param innerTxnType
* @param outerTxnType
*/
public static boolean isTxnTypeCompatible(TxnType innerTxnType, TxnType outerTxnType) {
if ( outerTxnType == null )
// Not in an outer transaction.
return true;
if ( Objects.equals(innerTxnType, outerTxnType) )
return true;
// Outer any, inner READ
if ( TxnType.READ.equals(innerTxnType) )
return true;
// Outer WRITE, inner any
if ( TxnType.WRITE.equals(outerTxnType) )
return true;
// Outer READ, inner WRITE or PROMOTE
if ( TxnType.READ.equals(outerTxnType) )
return false;
return false;
}
/**
* Check an existing {@link Transactional} for compatibility with a {@link TxnType} and
* promote the {@link Transactional} if necessary.
* The {@link Transactional} does not need to already be in a transaction.
* Throw a {@link JenaTransactionException} if not compatible (e.g. current READ, requesting a WRITE).
* @param requestedTxnType
* @param currentTxn
* @throws JenaTransactionException if not possible.
*/
public static void compatibleWithPromote(TxnType requestedTxnType, Transactional currentTxn) {
TxnType currentTxnType = currentTxn.transactionType();
if ( currentTxnType == null )
// Not in an outer transaction.
return;
// Outer any, inner READ
if ( TxnType.READ.equals(requestedTxnType) )
return;
// Outer WRITE, inner any
if ( TxnType.WRITE.equals(currentTxnType) )
return;
if ( TxnType.READ.equals(currentTxnType) )
throw new JenaTransactionException("Already in a READ transaction: outer="+currentTxnType+" : inner="+requestedTxnType);
// Outer PROMOTE (either kind), inner is not READ.
// Try to promote outer if inner is WRITE.
if ( requestedTxnType == TxnType.WRITE ) {
boolean x = currentTxn.promote();
if ( x )
return ;
throw new JenaTransactionException("Can't promote outer transaction: "+"outer="+currentTxnType+" : inner="+requestedTxnType);
}
if ( Objects.equals(requestedTxnType, currentTxnType) )
return;
throw new JenaTransactionException("Already in a transaction of an incompatable type: "+"outer="+currentTxnType+" : inner="+requestedTxnType);
}
}