use of org.apache.ignite.internal.processors.query.EnlistOperation in project ignite by apache.
the class GridDhtTxAbstractEnlistFuture method continueLoop.
/**
* Iterates over iterator, applies changes locally and sends it on backups.
*
* @param ignoreCntr {@code True} if need to ignore skip counter.
*/
private void continueLoop(boolean ignoreCntr) {
if (isDone() || (!ignoreCntr && (SKIP_UPD.getAndIncrement(this) != 0)))
return;
GridDhtCacheAdapter cache = cctx.dhtCache();
EnlistOperation op = it.operation();
AffinityTopologyVersion topVer = tx.topologyVersionSnapshot();
try {
while (true) {
int curPart = -1;
List<ClusterNode> backups = null;
while (hasNext0()) {
Object cur = next0();
KeyCacheObject key = toKey(op, cur);
if (curPart != key.partition())
backups = backupNodes(curPart = key.partition());
assert backups != null;
if (!ensureFreeSlot(key, backups)) {
// Can't advance further at the moment.
peek = cur;
it.beforeDetach();
break;
}
GridDhtCacheEntry entry = cache.entryExx(key);
if (log.isDebugEnabled())
log.debug("Adding entry: " + entry);
assert !entry.detached();
CacheObject val = op.isDeleteOrLock() || op.isInvoke() ? null : cctx.toCacheObject(((IgniteBiTuple) cur).getValue());
GridInvokeValue invokeVal = null;
EntryProcessor entryProc = null;
Object[] invokeArgs = null;
if (op.isInvoke()) {
assert needResult();
invokeVal = (GridInvokeValue) ((IgniteBiTuple) cur).getValue();
entryProc = invokeVal.entryProcessor();
invokeArgs = invokeVal.invokeArgs();
}
assert entryProc != null || !op.isInvoke();
boolean needOldVal = tx.txState().useMvccCaching(cctx.cacheId());
GridCacheUpdateTxResult res;
while (true) {
cctx.shared().database().checkpointReadLock();
try {
switch(op) {
case DELETE:
res = entry.mvccRemove(tx, cctx.localNodeId(), topVer, mvccSnapshot, isMoving(key.partition(), backups), needOldVal, filter, needResult());
break;
case INSERT:
case TRANSFORM:
case UPSERT:
case UPDATE:
res = entry.mvccSet(tx, cctx.localNodeId(), val, entryProc, invokeArgs, 0, topVer, mvccSnapshot, op.cacheOperation(), isMoving(key.partition(), backups), op.noCreate(), needOldVal, filter, needResult(), keepBinary);
break;
case LOCK:
res = entry.mvccLock(tx, mvccSnapshot);
break;
default:
throw new IgniteSQLException("Cannot acquire lock for operation [op= " + op + "]" + "Operation is unsupported at the moment ", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
break;
} catch (GridCacheEntryRemovedException ignored) {
entry = cache.entryExx(entry.key(), topVer);
} finally {
cctx.shared().database().checkpointReadUnlock();
}
}
IgniteInternalFuture<GridCacheUpdateTxResult> updateFut = res.updateFuture();
final Message val0 = invokeVal != null ? invokeVal : val;
if (updateFut != null) {
if (updateFut.isDone())
res = updateFut.get();
else {
GridDhtCacheEntry entry0 = entry;
List<ClusterNode> backups0 = backups;
it.beforeDetach();
updateFut.listen(new CI1<IgniteInternalFuture<GridCacheUpdateTxResult>>() {
@Override
public void apply(IgniteInternalFuture<GridCacheUpdateTxResult> fut) {
try {
tx.incrementLockCounter();
processEntry(entry0, op, fut.get(), val0, backups0);
continueLoop(true);
} catch (Throwable e) {
onDone(e);
}
}
});
// Can't move further. Exit loop without decrementing the counter.
return;
}
}
tx.incrementLockCounter();
processEntry(entry, op, res, val0, backups);
}
if (!hasNext0()) {
if (!F.isEmpty(batches)) {
// Flush incomplete batches.
// Need to skip batches for nodes where first request (contains tx info) is still in-flight.
// Otherwise, the regular enlist request (without tx info) may beat it to the primary node.
Iterator<Map.Entry<UUID, Batch>> it = batches.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<UUID, Batch> e = it.next();
ConcurrentMap<Integer, Batch> pending0 = pending == null ? null : pending.get(e.getKey());
if (pending0 == null || !pending0.containsKey(FIRST_BATCH_ID)) {
it.remove();
sendBatch(e.getValue());
}
}
}
if (noPendingRequests()) {
onDone(result0());
return;
}
}
if (SKIP_UPD.decrementAndGet(this) == 0)
break;
skipCntr = 1;
}
} catch (Throwable e) {
onDone(e);
if (e instanceof Error)
throw (Error) e;
}
}
use of org.apache.ignite.internal.processors.query.EnlistOperation in project ignite by apache.
the class GridNearTxLocal method mvccRemoveAllAsync0.
/**
* Internal method for remove operations in Mvcc mode.
*
* @param cacheCtx Cache context.
* @param keys Keys to remove.
* @param retval Flag indicating whether a value should be returned.
* @param filter Filter.
* @return Future for asynchronous remove.
*/
@SuppressWarnings("unchecked")
private <K, V> IgniteInternalFuture<GridCacheReturn> mvccRemoveAllAsync0(final GridCacheContext cacheCtx, @Nullable final Collection<? extends K> keys, final boolean retval, @Nullable final CacheEntryPredicate filter) {
try {
MvccUtils.requestSnapshot(this);
beforeRemove(cacheCtx, retval, true);
} catch (IgniteCheckedException e) {
return new GridFinishedFuture(e);
}
if (F.isEmpty(keys)) {
if (implicit()) {
try {
commit();
} catch (IgniteCheckedException e) {
return new GridFinishedFuture<>(e);
}
}
return new GridFinishedFuture<>(new GridCacheReturn(localResult(), true));
}
init();
Set<KeyCacheObject> enlisted = new HashSet<>(keys.size());
try {
for (Object key : keys) {
if (isRollbackOnly())
return new GridFinishedFuture<>(timedOut() ? timeoutException() : rollbackException());
if (key == null) {
rollback();
throw new NullPointerException("Null key.");
}
KeyCacheObject cacheKey = cacheCtx.toCacheKeyObject(key);
enlisted.add(cacheKey);
}
} catch (IgniteCheckedException e) {
return new GridFinishedFuture(e);
}
return updateAsync(cacheCtx, new UpdateSourceIterator<KeyCacheObject>() {
private final Iterator<KeyCacheObject> it = enlisted.iterator();
@Override
public EnlistOperation operation() {
return EnlistOperation.DELETE;
}
@Override
public boolean hasNextX() throws IgniteCheckedException {
return it.hasNext();
}
@Override
public KeyCacheObject nextX() throws IgniteCheckedException {
return it.next();
}
}, retval, filter, remainingTime(), true);
}
use of org.apache.ignite.internal.processors.query.EnlistOperation in project ignite by apache.
the class GridNearTxEnlistFuture method continueLoop.
/**
* Iterate data rows and form batches.
*
* @param nodeId Id of node acknowledged the last batch.
* @return Collection of newly completed batches.
* @throws IgniteCheckedException If failed.
*/
private Collection<Batch> continueLoop(@Nullable UUID nodeId) throws IgniteCheckedException {
if (nodeId != null)
batches.remove(nodeId);
// Let only one thread do the looping.
if (isDone() || SKIP_UPD.getAndIncrement(this) != 0)
return null;
ArrayList<Batch> res = null;
Batch batch = null;
boolean flush = false;
EnlistOperation op = it.operation();
while (true) {
while (hasNext0()) {
checkCompleted();
Object cur = next0();
KeyCacheObject key = cctx.toCacheKeyObject(op.isDeleteOrLock() ? cur : ((IgniteBiTuple) cur).getKey());
ClusterNode node = cctx.affinity().primaryByKey(key, topVer);
if (node == null)
throw new ClusterTopologyServerNotFoundException("Failed to get primary node " + "[topVer=" + topVer + ", key=" + key + ']');
if (!sequential)
batch = batches.get(node.id());
else if (batch != null && !batch.node().equals(node))
res = markReady(res, batch);
if (batch == null)
batches.put(node.id(), batch = new Batch(node));
if (batch.ready()) {
// Can't advance further at the moment.
batch = null;
peek = cur;
it.beforeDetach();
flush = true;
break;
}
batch.add(op.isDeleteOrLock() ? key : cur, !node.isLocal() && isLocalBackup(op, key));
if (batch.size() == batchSize)
res = markReady(res, batch);
}
if (SKIP_UPD.decrementAndGet(this) == 0)
break;
skipCntr = 1;
}
if (flush)
return res;
// No data left - flush incomplete batches.
for (Batch batch0 : batches.values()) {
if (!batch0.ready()) {
if (res == null)
res = new ArrayList<>();
batch0.ready(true);
res.add(batch0);
}
}
if (batches.isEmpty())
onDone(this.res);
return res;
}
use of org.apache.ignite.internal.processors.query.EnlistOperation in project ignite by apache.
the class GridNearTxQueryResultsEnlistFuture method continueLoop.
/**
* Iterate data rows and form batches.
*
* @param nodeId Id of node acknowledged the last batch.
* @return Collection of newly completed batches.
* @throws IgniteCheckedException If failed.
*/
private Collection<Batch> continueLoop(@Nullable UUID nodeId) throws IgniteCheckedException {
if (nodeId != null)
batches.remove(nodeId);
// Let only one thread do the looping.
if (isDone() || SKIP_UPD.getAndIncrement(this) != 0)
return null;
ArrayList<Batch> res = null;
Batch batch = null;
boolean flush = false;
EnlistOperation op = it.operation();
while (true) {
while (hasNext0()) {
checkCompleted();
Object cur = next0();
KeyCacheObject key = cctx.toCacheKeyObject(op.isDeleteOrLock() ? cur : ((IgniteBiTuple) cur).getKey());
ClusterNode node = cctx.affinity().primaryByPartition(key.partition(), topVer);
if (node == null)
throw new ClusterTopologyServerNotFoundException("Failed to get primary node " + "[topVer=" + topVer + ", key=" + key + ']');
if (!sequential)
batch = batches.get(node.id());
else if (batch != null && !batch.node().equals(node))
res = markReady(res, batch);
if (batch == null)
batches.put(node.id(), batch = new Batch(node));
if (batch.ready()) {
// Can't advance further at the moment.
batch = null;
peek = cur;
it.beforeDetach();
flush = true;
break;
}
batch.add(op.isDeleteOrLock() ? key : cur, !node.isLocal() && isLocalBackup(op, key));
if (batch.size() == batchSize)
res = markReady(res, batch);
}
if (SKIP_UPD.decrementAndGet(this) == 0)
break;
skipCntr = 1;
}
if (flush)
return res;
// No data left - flush incomplete batches.
for (Batch batch0 : batches.values()) {
if (!batch0.ready()) {
if (res == null)
res = new ArrayList<>();
batch0.ready(true);
res.add(batch0);
}
}
if (batches.isEmpty())
onDone(this.res);
return res;
}
use of org.apache.ignite.internal.processors.query.EnlistOperation in project ignite by apache.
the class GridNearTxQueryResultsEnlistFuture method processBatchLocalBackupKeys.
/**
* @param primaryId Primary node id.
* @param rows Rows.
* @param dhtVer Dht version assigned at primary node.
* @param dhtFutId Dht future id assigned at primary node.
*/
private void processBatchLocalBackupKeys(UUID primaryId, List<Object> rows, GridCacheVersion dhtVer, IgniteUuid dhtFutId) {
assert dhtVer != null;
assert dhtFutId != null;
EnlistOperation op = it.operation();
assert op != EnlistOperation.LOCK;
boolean keysOnly = op.isDeleteOrLock();
final ArrayList<KeyCacheObject> keys = new ArrayList<>(rows.size());
final ArrayList<Message> vals = keysOnly ? null : new ArrayList<>(rows.size());
for (Object row : rows) {
if (keysOnly)
keys.add(cctx.toCacheKeyObject(row));
else {
keys.add(cctx.toCacheKeyObject(((IgniteBiTuple) row).getKey()));
vals.add(cctx.toCacheObject(((IgniteBiTuple) row).getValue()));
}
}
try {
GridDhtTxRemote dhtTx = cctx.tm().tx(dhtVer);
if (dhtTx == null) {
dhtTx = new GridDhtTxRemote(cctx.shared(), cctx.localNodeId(), dhtFutId, primaryId, lockVer, topVer, dhtVer, null, cctx.systemTx(), cctx.ioPolicy(), PESSIMISTIC, REPEATABLE_READ, false, tx.remainingTime(), -1, SecurityUtils.securitySubjectId(cctx), tx.taskNameHash(), false, tx.label());
dhtTx.mvccSnapshot(new MvccSnapshotWithoutTxs(mvccSnapshot.coordinatorVersion(), mvccSnapshot.counter(), MVCC_OP_COUNTER_NA, mvccSnapshot.cleanupVersion()));
dhtTx = cctx.tm().onCreated(null, dhtTx);
if (dhtTx == null || !cctx.tm().onStarted(dhtTx)) {
throw new IgniteTxRollbackCheckedException("Failed to update backup " + "(transaction has been completed): " + dhtVer);
}
}
cctx.tm().txHandler().mvccEnlistBatch(dhtTx, cctx, it.operation(), keys, vals, mvccSnapshot.withoutActiveTransactions(), null, -1);
} catch (IgniteCheckedException e) {
onDone(e);
return;
}
sendNextBatches(primaryId);
}
Aggregations