Search in sources :

Example 1 with IgniteTxDuplicateKeyCheckedException

use of org.apache.ignite.internal.transactions.IgniteTxDuplicateKeyCheckedException in project ignite by apache.

the class GridCacheMapEntry method mvccSet.

/**
 * {@inheritDoc}
 */
@Override
public final GridCacheUpdateTxResult mvccSet(IgniteInternalTx tx, UUID affNodeId, CacheObject val, EntryProcessor entryProc, Object[] invokeArgs, long ttl0, AffinityTopologyVersion topVer, MvccSnapshot mvccVer, GridCacheOperation op, boolean needHistory, boolean noCreate, boolean needOldVal, CacheEntryPredicate filter, boolean retVal, boolean keepBinary) throws IgniteCheckedException, GridCacheEntryRemovedException {
    assert tx != null;
    final boolean valid = valid(tx.topologyVersion());
    final boolean invoke = entryProc != null;
    final GridCacheVersion newVer;
    WALPointer logPtr = null;
    ensureFreeSpace();
    lockEntry();
    MvccUpdateResult res;
    try {
        checkObsolete();
        newVer = tx.writeVersion();
        assert newVer != null : "Failed to get write version for tx: " + tx;
        // Determine new ttl and expire time.
        long expireTime, ttl = ttl0;
        if (ttl == -1L) {
            ttl = ttlExtras();
            expireTime = expireTimeExtras();
        } else
            expireTime = CU.toExpireTime(ttl);
        assert ttl >= 0 : ttl;
        assert expireTime >= 0 : expireTime;
        // Detach value before index update.
        val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
        assert val != null || invoke;
        res = cctx.offheap().mvccUpdate(this, val, newVer, expireTime, mvccVer, tx.local(), needHistory, noCreate, needOldVal, filter, retVal, keepBinary, entryProc, invokeArgs);
        assert res != null;
        // updating the key which just has been rebalanced.
        assert res.resultType() != ResultType.VERSION_FOUND || op == CREATE && tx.local() || !tx.local();
        // PREV_NOT_NULL on CREATE is possible only on primary.
        assert res.resultType() != ResultType.PREV_NOT_NULL || op != CREATE || tx.local();
        if (res.resultType() == ResultType.VERSION_MISMATCH)
            throw serializationError();
        else if (res.resultType() == ResultType.FILTERED) {
            GridCacheUpdateTxResult updRes = new GridCacheUpdateTxResult(invoke);
            assert !invoke || res.invokeResult() != null;
            if (// No-op invoke happened.
            invoke)
                updRes.invokeResult(res.invokeResult());
            updRes.filtered(true);
            if (retVal)
                updRes.prevValue(res.oldValue());
            return updRes;
        } else if (noCreate && !invoke && res.resultType() == ResultType.PREV_NULL)
            return new GridCacheUpdateTxResult(false);
        else if (res.resultType() == ResultType.LOCKED) {
            unlockEntry();
            MvccVersion lockVer = res.resultVersion();
            GridFutureAdapter<GridCacheUpdateTxResult> resFut = new GridFutureAdapter<>();
            IgniteInternalFuture<?> lockFut = cctx.kernalContext().coordinators().waitForLock(cctx, mvccVer, lockVer);
            lockFut.listen(new MvccUpdateLockListener(tx, this, affNodeId, topVer, val, ttl0, mvccVer, op, needHistory, noCreate, resFut, needOldVal, filter, retVal, keepBinary, entryProc, invokeArgs));
            return new GridCacheUpdateTxResult(false, resFut);
        } else if (op == CREATE && tx.local() && (res.resultType() == ResultType.PREV_NOT_NULL || res.resultType() == ResultType.VERSION_FOUND))
            throw new IgniteTxDuplicateKeyCheckedException("Duplicate key during INSERT [key=" + key + ']');
        if (cctx.deferredDelete() && deletedUnlocked() && !detached())
            deletedUnlocked(false);
        if (res.resultType() == ResultType.PREV_NULL) {
            TxCounters counters = tx.txCounters(true);
            if (compareIgnoreOpCounter(res.resultVersion(), mvccVer) == 0) {
                if (res.isKeyAbsentBefore())
                    counters.incrementUpdateCounter(cctx.cacheId(), partition());
            } else
                counters.incrementUpdateCounter(cctx.cacheId(), partition());
            counters.accumulateSizeDelta(cctx.cacheId(), partition(), 1);
        } else if (res.resultType() == ResultType.PREV_NOT_NULL && compareIgnoreOpCounter(res.resultVersion(), mvccVer) != 0) {
            TxCounters counters = tx.txCounters(true);
            counters.incrementUpdateCounter(cctx.cacheId(), partition());
        } else if (res.resultType() == ResultType.REMOVED_NOT_NULL) {
            TxCounters counters = tx.txCounters(true);
            if (compareIgnoreOpCounter(res.resultVersion(), mvccVer) == 0) {
                if (// Do not count own update removal.
                res.isKeyAbsentBefore())
                    counters.decrementUpdateCounter(cctx.cacheId(), partition());
            } else
                counters.incrementUpdateCounter(cctx.cacheId(), partition());
            counters.accumulateSizeDelta(cctx.cacheId(), partition(), -1);
        }
        if (cctx.group().persistenceEnabled() && cctx.group().walEnabled()) {
            logPtr = cctx.shared().wal().log(new MvccDataRecord(new MvccDataEntry(cctx.cacheId(), key, val, res.resultType() == ResultType.PREV_NULL ? CREATE : (res.resultType() == ResultType.REMOVED_NOT_NULL) ? DELETE : UPDATE, tx.nearXidVersion(), newVer, expireTime, key.partition(), 0L, mvccVer)));
        }
        update(val, expireTime, ttl, newVer, true);
        recordNodeId(affNodeId, topVer);
    } finally {
        if (lockedByCurrentThread()) {
            unlockEntry();
            cctx.evicts().touch(this);
        }
    }
    onUpdateFinished(0L);
    GridCacheUpdateTxResult updRes = valid ? new GridCacheUpdateTxResult(true, 0L, logPtr) : new GridCacheUpdateTxResult(false, logPtr);
    if (retVal && (res.resultType() == ResultType.PREV_NOT_NULL || res.resultType() == ResultType.VERSION_FOUND))
        updRes.prevValue(res.oldValue());
    if (needOldVal && compareIgnoreOpCounter(res.resultVersion(), mvccVer) != 0 && (res.resultType() == ResultType.PREV_NOT_NULL || res.resultType() == ResultType.REMOVED_NOT_NULL))
        updRes.oldValue(res.oldValue());
    updRes.newValue(res.newValue());
    if (invoke && res.resultType() != ResultType.VERSION_FOUND) {
        assert res.invokeResult() != null;
        updRes.invokeResult(res.invokeResult());
    }
    updRes.mvccHistory(res.history());
    return updRes;
}
Also used : TxCounters(org.apache.ignite.internal.processors.cache.transactions.TxCounters) MvccUpdateResult(org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccUpdateResult) MvccDataEntry(org.apache.ignite.internal.pagemem.wal.record.MvccDataEntry) IgniteInternalFuture(org.apache.ignite.internal.IgniteInternalFuture) IgniteTxDuplicateKeyCheckedException(org.apache.ignite.internal.transactions.IgniteTxDuplicateKeyCheckedException) GridCacheVersion(org.apache.ignite.internal.processors.cache.version.GridCacheVersion) MvccVersion(org.apache.ignite.internal.processors.cache.mvcc.MvccVersion) GridFutureAdapter(org.apache.ignite.internal.util.future.GridFutureAdapter) MvccDataRecord(org.apache.ignite.internal.pagemem.wal.record.MvccDataRecord) WALPointer(org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)

Aggregations

IgniteInternalFuture (org.apache.ignite.internal.IgniteInternalFuture)1 MvccDataEntry (org.apache.ignite.internal.pagemem.wal.record.MvccDataEntry)1 MvccDataRecord (org.apache.ignite.internal.pagemem.wal.record.MvccDataRecord)1 MvccVersion (org.apache.ignite.internal.processors.cache.mvcc.MvccVersion)1 WALPointer (org.apache.ignite.internal.processors.cache.persistence.wal.WALPointer)1 TxCounters (org.apache.ignite.internal.processors.cache.transactions.TxCounters)1 MvccUpdateResult (org.apache.ignite.internal.processors.cache.tree.mvcc.data.MvccUpdateResult)1 GridCacheVersion (org.apache.ignite.internal.processors.cache.version.GridCacheVersion)1 IgniteTxDuplicateKeyCheckedException (org.apache.ignite.internal.transactions.IgniteTxDuplicateKeyCheckedException)1 GridFutureAdapter (org.apache.ignite.internal.util.future.GridFutureAdapter)1