public T openForRead() {
        Transaction me = Transaction.getLocal();
        switch (me.getStatus()) {
        case ACTIVE:
            Locator locator = this.locator.get();
            if (me == locator.owner) {
                return locator.current;
            }
            Locator newLocator = new Locator(me);
            while (!Thread.currentThread().isInterrupted()) {
                Locator oldLocator = this.locator.get();
                Transaction currentOwner = oldLocator.owner;
                switch (currentOwner.getStatus()) {
                case COMMITTED:
                    newLocator.current = oldLocator.current;
                    break;
                case ABORTED:
                    newLocator.current = oldLocator.backup;
                    break;
                case ACTIVE:
                    ContentionResolver.getLocal().resolve(me, currentOwner);
                    continue;
                }
                if (this.locator.compareAndSet(oldLocator, newLocator)) {
                    return newLocator.current;
                }
            }
            throw new AbortedException();
        case COMMITTED:
            return openOutsideTransaction();
        case ABORTED:
            throw new AbortedException();
        default:
            throw new TransactionFailedException();
        }
    }