/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.transaction; import com.github.geophile.erdo.AbstractKey; import java.util.ArrayDeque; import java.util.Collection; import java.util.Deque; import java.util.Map; class LockConflict { // Object interface @Override public String toString() { return String.format("LockConflict(%s: owner: %s, waiting: %s)", key, lockOwner, waiting); } // LockConflict interface public AbstractKey key() { return key; } public Transaction lockOwner() { return lockOwner; } public boolean hasWaiters() { return !waiting.isEmpty(); } public boolean hasWaiter(Transaction transaction) { return waiting != null && waiting.contains(transaction); } public void addWaiter(Transaction transaction) { assert !waiting.contains(transaction) : String.format("%s, transaction %s", this, transaction); waiting.addLast(transaction); } public void removeWaiter(Transaction transaction) { waiting.remove(transaction); } public Transaction giveLockToFirstWaiter() { // waiting should not be empty. LockManager should discard a LockConflict object as soon // as the last waiter is removed. assert !waiting.isEmpty() : key; do { lockOwner = waiting.pollFirst(); } while (lockOwner != null && ignorable(lockOwner)); return lockOwner; } public void findDependencies(Map<Transaction, WaitsFor> dependencies) { for (Transaction lockWaiter : waiting) { if (!ignorable(lockWaiter)) { WaitsFor replaced = dependencies.put(lockWaiter, new WaitsFor(lockWaiter, lockOwner)); assert replaced == null : replaced; } } } public Collection<Transaction> waiters() { return waiting; } public LockConflict(AbstractKey key, Transaction lockOwner) { this.key = key; this.lockOwner = lockOwner; } // For use by this class private boolean ignorable(Transaction transaction) { return transaction.irrelevant() || transaction.hasAborted(); } // Object state private final AbstractKey key; private Transaction lockOwner; private Deque<Transaction> waiting = new ArrayDeque<Transaction>(); }