// Copyright 2017 JanusGraph Authors // // Licensed 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.janusgraph.diskstorage.berkeleyje; import com.google.common.base.Preconditions; import com.sleepycat.je.Cursor; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.LockMode; import com.sleepycat.je.Transaction; import org.janusgraph.diskstorage.BackendException; import org.janusgraph.diskstorage.PermanentBackendException; import org.janusgraph.diskstorage.BaseTransactionConfig; import org.janusgraph.diskstorage.common.AbstractStoreTransaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; public class BerkeleyJETx extends AbstractStoreTransaction { private static final Logger log = LoggerFactory.getLogger(BerkeleyJETx.class); private volatile Transaction tx; private final List<Cursor> openCursors = new ArrayList<Cursor>(); private final LockMode lm; public BerkeleyJETx(Transaction t, LockMode lockMode, BaseTransactionConfig config) { super(config); tx = t; lm = lockMode; // tx may be null Preconditions.checkNotNull(lm); } public Transaction getTransaction() { return tx; } void registerCursor(Cursor cursor) { Preconditions.checkArgument(cursor != null); synchronized (openCursors) { //TODO: attempt to remove closed cursors if there are too many openCursors.add(cursor); } } private void closeOpenIterators() throws BackendException { for (Cursor cursor : openCursors) { cursor.close(); } } LockMode getLockMode() { return lm; } @Override public synchronized void rollback() throws BackendException { super.rollback(); if (tx == null) return; if (log.isTraceEnabled()) log.trace("{} rolled back", this.toString(), new TransactionClose(this.toString())); try { closeOpenIterators(); tx.abort(); tx = null; } catch (DatabaseException e) { throw new PermanentBackendException(e); } } @Override public synchronized void commit() throws BackendException { super.commit(); if (tx == null) return; if (log.isTraceEnabled()) log.trace("{} committed", this.toString(), new TransactionClose(this.toString())); try { closeOpenIterators(); tx.commit(); tx = null; } catch (DatabaseException e) { throw new PermanentBackendException(e); } } @Override public String toString() { return getClass().getSimpleName() + (null == tx ? "nulltx" : tx.toString()); } private static class TransactionClose extends Exception { private static final long serialVersionUID = 1L; private TransactionClose(String msg) { super(msg); } } }