
org.opendaylight.controller.cluster.databroker.AbstractDOMBrokerTransaction Maven / Gradle / Ivy
/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. 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
*/
package org.opendaylight.controller.cluster.databroker;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.mdsal.common.api.TransactionDatastoreMismatchException;
import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransaction;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionFactory;
public abstract class AbstractDOMBrokerTransaction implements DOMDataTreeTransaction {
private static final VarHandle BACKING_TX;
static {
try {
BACKING_TX = MethodHandles.lookup()
.findVarHandle(AbstractDOMBrokerTransaction.class, "backingTx", Entry.class);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
}
private final @NonNull Object identifier;
private final Map storeTxFactories;
private volatile Entry backingTx;
/**
* Creates new transaction.
*
* @param identifier Identifier of transaction.
*/
protected AbstractDOMBrokerTransaction(final Object identifier,
Map storeTxFactories) {
this.identifier = requireNonNull(identifier, "Identifier should not be null");
this.storeTxFactories = requireNonNull(storeTxFactories, "Store Transaction Factories should not be null");
checkArgument(!storeTxFactories.isEmpty(), "Store Transaction Factories should not be empty");
}
/**
* Returns sub-transaction associated with supplied key.
*
* @param datastoreType the data store type
* @return the sub-transaction
* @throws NullPointerException if datastoreType is null
* @throws IllegalArgumentException if no sub-transaction is associated with datastoreType.
* @throws TransactionDatastoreMismatchException if datastoreType mismatches the one used at first access
*/
protected final T getSubtransaction(final LogicalDatastoreType datastoreType) {
requireNonNull(datastoreType, "datastoreType must not be null.");
var entry = backingTx;
if (entry == null) {
if (!storeTxFactories.containsKey(datastoreType)) {
throw new IllegalArgumentException(datastoreType + " is not supported");
}
final var tx = createTransaction(datastoreType);
final var newEntry = Map.entry(datastoreType, tx);
final var witness = (Entry) BACKING_TX.compareAndExchange(this, null, newEntry);
if (witness != null) {
tx.close();
entry = witness;
} else {
entry = newEntry;
}
}
final var expected = entry.getKey();
if (expected != datastoreType) {
throw new TransactionDatastoreMismatchException(expected, datastoreType);
}
return entry.getValue();
}
/**
* Returns sub-transaction if initialized.
*/
protected T getSubtransaction() {
final Entry entry;
return (entry = backingTx) == null ? null : entry.getValue();
}
protected abstract T createTransaction(LogicalDatastoreType datastoreType);
@Override
public Object getIdentifier() {
return identifier;
}
@SuppressWarnings("checkstyle:IllegalCatch")
protected void closeSubtransaction() {
if (backingTx != null) {
try {
backingTx.getValue().close();
} catch (Exception e) {
throw new IllegalStateException("Uncaught exception occurred during closing transaction", e);
}
}
}
protected DOMStoreTransactionFactory getTxFactory(LogicalDatastoreType type) {
return storeTxFactories.get(type);
}
@Override
public final String toString() {
return addToStringAttributes(MoreObjects.toStringHelper(this).omitNullValues()).toString();
}
protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
return toStringHelper.add("identifier", identifier);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy