Search in sources :

Example 1 with Index

use of org.cojen.tupl.Index in project Tupl by cojen.

the class VerificationObserver method indexNodeFailed.

/**
 * Called after an index node fails verification. Implementation is free to
 * report incremental progress or throttle verification. Default
 * implementation prints a message to standard out and returns true.
 *
 * @param id ephemeral node identifier
 * @param level index node level; root node is level one
 * @param message failure message
 * @return false if verification should stop
 */
public boolean indexNodeFailed(long id, int level, String message) {
    var b = new StringBuilder("Verification failure: index=");
    Index index = this.index;
    if (index == null) {
        b.append("null");
    } else {
        b.append(index.id());
    }
    b.append(", node=").append(id).append(", level=").append(level).append(": ").append(message);
    reportFailure(b.toString());
    return true;
}
Also used : Index(org.cojen.tupl.Index)

Example 2 with Index

use of org.cojen.tupl.Index in project Tupl by cojen.

the class BasicRowUpdater method doUpdateAsDeleteInsert.

/**
 * Called when the primary key changed.
 *
 * @param c positioned at key to delete; position isn't changed
 * @param key key to insert
 * @param value value to insert
 * @throws UniqueConstraintException
 */
private void doUpdateAsDeleteInsert(R row, Cursor c, byte[] key, byte[] value) throws IOException {
    Index source = mTable.mSource;
    Transaction txn = ViewUtils.enterScope(source, c.link());
    try {
        Trigger<R> trigger = mTable.getTrigger();
        if (trigger != null)
            while (true) {
                trigger.acquireShared();
                try {
                    int mode = trigger.mode();
                    if (mode == Trigger.SKIP) {
                        break;
                    }
                    if (mode != Trigger.DISABLED) {
                        byte[] oldValue = c.value();
                        if (oldValue != null) {
                            // Don't pass the row because the key columns were modified.
                            trigger.delete(txn, c.key(), oldValue);
                        }
                        trigger.insertP(txn, row, key, value);
                        break;
                    }
                } finally {
                    trigger.releaseShared();
                }
                trigger = mTable.trigger();
            }
        boolean result;
        RowPredicateLock<R> lock = mTable.mIndexLock;
        if (lock == null) {
            result = source.insert(txn, key, value);
        } else {
            lock.redoPredicateMode(txn);
            try (RowPredicateLock.Closer closer = lock.openAcquireP(txn, row, key, value)) {
                result = source.insert(txn, key, value);
            }
        }
        if (!result) {
            throw new UniqueConstraintException("Primary key");
        }
        c.commit(null);
    } finally {
        txn.exit();
    }
    postStoreKeyValue(txn);
}
Also used : UniqueConstraintException(org.cojen.tupl.UniqueConstraintException) Transaction(org.cojen.tupl.Transaction) Index(org.cojen.tupl.Index) RowPredicateLock(org.cojen.tupl.core.RowPredicateLock)

Example 3 with Index

use of org.cojen.tupl.Index in project Tupl by cojen.

the class BaseTable method store.

/**
 * Called when no trigger is installed.
 */
protected final void store(Transaction txn, R row, byte[] key, byte[] value) throws IOException {
    Index source = mSource;
    // RowPredicateLock requires a non-null transaction.
    txn = ViewUtils.enterScope(source, txn);
    try {
        redoPredicateMode(txn);
        try (RowPredicateLock.Closer closer = mIndexLock.openAcquire(txn, row)) {
            source.store(txn, key, value);
        }
        txn.commit();
    } finally {
        txn.exit();
    }
}
Also used : Index(org.cojen.tupl.Index) RowPredicateLock(org.cojen.tupl.core.RowPredicateLock)

Example 4 with Index

use of org.cojen.tupl.Index in project Tupl by cojen.

the class BaseTable method insert.

/**
 * Called when no trigger is installed.
 */
protected final boolean insert(Transaction txn, R row, byte[] key, byte[] value) throws IOException {
    Index source = mSource;
    // RowPredicateLock requires a non-null transaction.
    txn = ViewUtils.enterScope(source, txn);
    boolean result;
    try {
        redoPredicateMode(txn);
        try (RowPredicateLock.Closer closer = mIndexLock.openAcquire(txn, row)) {
            result = source.insert(txn, key, value);
        }
        txn.commit();
    } finally {
        txn.exit();
    }
    return result;
}
Also used : Index(org.cojen.tupl.Index) RowPredicateLock(org.cojen.tupl.core.RowPredicateLock)

Example 5 with Index

use of org.cojen.tupl.Index in project Tupl by cojen.

the class IndexBackfill method inserted.

/**
 * Called by a trigger when an entry is inserted into the secondary index. It's expected
 * that the transaction holds a lock on the secondary key within the secondary index.
 *
 * @param txn not null
 */
public void inserted(Transaction txn, byte[] secondaryKey, byte[] secondaryValue) throws IOException {
    Index newIndex = mNewSecondaryIndex;
    Index deleted = mDeleted;
    if (newIndex == null || deleted == null) {
        // Backfill hasn't reached the finishing phase or is finished.
        return;
    }
    if (txn.isBogus()) {
        // Need a transaction that supports rollback.
        txn = mRowStore.mDatabase.newTransaction(DurabilityMode.NO_REDO);
        txn.lockTimeout(-1, null);
    } else {
        txn.enter();
    }
    try {
        // The other two indexes are used for tracking modifications which must be applied
        // into the new index, but because the insert supersedes them, delete the
        // corresponding entries. Note that the caller just inserted into mSecondaryIndex,
        // and the delete undoes it. It would be more efficient to not insert in the first
        // place, but this is simpler, and backfills are infrequent.
        // lock first to avoid deadlock
        mSecondaryIndex.delete(txn, secondaryKey);
        deleted.delete(txn, secondaryKey);
        // Insert into what will become the real secondary index.
        newIndex.store(txn, secondaryKey, secondaryValue);
        txn.commit();
    } catch (ClosedIndexException e) {
    // Assume that there was a race condition and the backfill now is closed. The
    // scoped transaction allows the mSecondaryIndex delete to be rolled back.
    } finally {
        txn.exit();
    }
}
Also used : Index(org.cojen.tupl.Index) ClosedIndexException(org.cojen.tupl.ClosedIndexException)

Aggregations

Index (org.cojen.tupl.Index)28 Transaction (org.cojen.tupl.Transaction)11 Database (org.cojen.tupl.Database)10 Cursor (org.cojen.tupl.Cursor)7 UnmodifiableReplicaException (org.cojen.tupl.UnmodifiableReplicaException)7 RowPredicateLock (org.cojen.tupl.core.RowPredicateLock)7 IOException (java.io.IOException)6 ClosedIndexException (org.cojen.tupl.ClosedIndexException)4 PrepareHandler (org.cojen.tupl.ext.PrepareHandler)4 RowUtils (org.cojen.tupl.rows.RowUtils)4 WeakReference (java.lang.ref.WeakReference)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 TreeMap (java.util.TreeMap)3 ConcurrentSkipListMap (java.util.concurrent.ConcurrentSkipListMap)3 LinkedBlockingQueue (java.util.concurrent.LinkedBlockingQueue)3 TimeUnit (java.util.concurrent.TimeUnit)3 CorruptDatabaseException (org.cojen.tupl.CorruptDatabaseException)3 View (org.cojen.tupl.View)3 Worker (org.cojen.tupl.util.Worker)3