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

org.jsimpledb.kv.mvcc.SnapshotKVTransaction Maven / Gradle / Ivy

There is a newer version: 3.6.1
Show newest version

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.kv.mvcc;

import com.google.common.base.Preconditions;
import com.google.common.util.concurrent.ListenableFuture;

import java.io.Closeable;
import java.util.concurrent.atomic.AtomicLong;

import org.jsimpledb.kv.CloseableKVStore;
import org.jsimpledb.kv.KVStore;
import org.jsimpledb.kv.KVTransaction;
import org.jsimpledb.kv.StaleTransactionException;
import org.jsimpledb.kv.TransactionTimeoutException;
import org.jsimpledb.kv.util.CloseableForwardingKVStore;
import org.jsimpledb.kv.util.ForwardingKVStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link SnapshotKVDatabase} transaction.
 */
public class SnapshotKVTransaction extends ForwardingKVStore implements KVTransaction, Closeable {

// Note: locking order: (1) SnapshotKVTransaction, (2) SnapshotKVDatabase

    private static final AtomicLong COUNTER = new AtomicLong();

    private final Logger log = LoggerFactory.getLogger(this.getClass());
    private final long uniqueId = COUNTER.incrementAndGet();
    private final long startTime;
    private final SnapshotKVDatabase kvdb;
    private final SnapshotVersion versionInfo;
    private final MutableView mutableView;

    private boolean closed;
    private long timeout;

    /**
     * Constructor.
     *
     * @param kvdb the associated database
     * @param versionInfo the associated MVCC version
     */
    protected SnapshotKVTransaction(SnapshotKVDatabase kvdb, SnapshotVersion versionInfo) {
        this.kvdb = kvdb;
        this.versionInfo = versionInfo;
        this.startTime = System.nanoTime();
        this.mutableView = new MutableView(versionInfo.getSnapshotRefs().getKVStore());
    }

// Accessors

    /**
     * Get the {@link MutableView} associated with this instance.
     *
     * @return associated access and mutation state
     */
    public MutableView getMutableView() {
        return this.mutableView;
    }

    /**
     * Get the MVCC version associated with this instance.
     *
     * @return associated MVCC version
     */
    public SnapshotVersion getSnapshotVersion() {
        return this.versionInfo;
    }

// ForwardingKVStore

    /**
     * Get the underlying {@link KVStore}.
     *
     * 

* The implementation in {@link SnapshotKVTransaction} returns the {@link MutableView} associated with this instance. * * @return the underlying {@link KVStore} */ @Override protected KVStore delegate() { this.checkState(); return this.mutableView; } // KVTransaction @Override public SnapshotKVDatabase getKVDatabase() { return this.kvdb; } /** * Set the transaction timeout. * *

* {@link SnapshotKVTransaction}s do not perform any locking while the transaction is open. Therefore, the configured * value is used instead as a timeout on the overall transaction duration. If the transaction is kept open for longer * than {@code timeout} milliseconds, a {@link TransactionTimeoutException} will be thrown. * * @param timeout transaction timeout in milliseconds, or zero for unlimited * @throws IllegalArgumentException if {@code timeout} is negative */ @Override public synchronized void setTimeout(long timeout) { Preconditions.checkArgument(timeout >= 0, "timeout < 0"); this.timeout = timeout; } @Override public ListenableFuture watchKey(byte[] key) { return this.kvdb.watchKey(key); } @Override public synchronized void commit() { this.checkState(); this.closed = true; this.kvdb.commit(this); } @Override public synchronized void rollback() { if (this.closed) return; this.closed = true; this.kvdb.rollback(this); } @Override public CloseableKVStore mutableSnapshot() { final SnapshotRefs snapshotRefs; synchronized (this) { this.checkState(); snapshotRefs = this.versionInfo.getSnapshotRefs(); snapshotRefs.ref(); } final Writes writes; synchronized (this.mutableView) { writes = this.mutableView.getWrites().clone(); } final MutableView snapshotView = new MutableView(snapshotRefs.getKVStore(), null, writes); return new CloseableForwardingKVStore(snapshotView, snapshotRefs.getUnrefCloseable()); } // Closeable /** * Close this instance. * *

* Equivalent to invoking {@link #rollback}. */ @Override public void close() { this.rollback(); } // Object @Override public String toString() { return this.getClass().getSimpleName() + "[id=" + this.uniqueId + ",vers=" + this.versionInfo.getVersion() + (this.closed ? ",closed" : "") + "]"; } @Override protected void finalize() throws Throwable { try { if (!this.closed) this.log.warn(this + " leaked without commit() or rollback()"); this.close(); } finally { super.finalize(); } } // Internal methods private void checkState() { if (this.closed) throw this.kvdb.logException(new StaleTransactionException(this)); if (this.timeout == 0) return; final long time = (System.nanoTime() - this.startTime) / 1000000L; if (time >= this.timeout) { throw this.kvdb.logException(new TransactionTimeoutException(this, "transaction has timed out after " + time + "ms > limit of " + this.timeout + "ms")); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy