use of org.apache.ignite.internal.util.future.GridFutureAdapter 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;
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class GridEventStorageManager method remoteEventsAsync.
/**
* @param p Grid event predicate.
* @param nodes Collection of nodes.
* @param timeout Maximum time to wait for result, if {@code 0}, then wait until result is received.
* @return Collection of events.
*/
public <T extends Event> IgniteInternalFuture<List<T>> remoteEventsAsync(final IgnitePredicate<T> p, final Collection<? extends ClusterNode> nodes, final long timeout) {
assert p != null;
assert nodes != null;
final GridFutureAdapter<List<T>> fut = new GridFutureAdapter<>();
ctx.closure().runLocalSafe(new GPR() {
@Override
public void run() {
try {
fut.onDone(query(p, nodes, timeout));
} catch (IgniteCheckedException e) {
fut.onDone(e);
}
}
}, true);
return fut;
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class IndexesRebuildTask method rebuild.
/**
* Start to rebuild.
*
* @param cctx Cache context.
* @param force Force rebuild indexes.
* @return A future of rebuilding cache indexes.
*/
@Nullable
public IgniteInternalFuture<?> rebuild(GridCacheContext<?, ?> cctx, boolean force, IndexRebuildCancelToken cancelTok) {
assert cctx != null;
if (!CU.affinityNode(cctx.localNode(), cctx.config().getNodeFilter()))
return null;
IgnitePageStoreManager pageStore = cctx.shared().pageStore();
SchemaIndexCacheVisitorClosure clo;
String cacheName = cctx.name();
if (pageStore == null || !pageStore.hasIndexStore(cctx.groupId())) {
boolean mvccEnabled = cctx.mvccEnabled();
// If there are no index store, rebuild all indexes.
clo = row -> cctx.queries().store(row, null, mvccEnabled);
} else {
Collection<InlineIndex> toRebuild = cctx.kernalContext().indexProcessor().treeIndexes(cctx, !force);
if (F.isEmpty(toRebuild))
return null;
clo = row -> cctx.kernalContext().indexProcessor().store(toRebuild, row, null, false);
}
// Closure prepared, do rebuild.
cctx.kernalContext().query().markAsRebuildNeeded(cctx, true);
GridFutureAdapter<Void> rebuildCacheIdxFut = new GridFutureAdapter<>();
// To avoid possible data race.
GridFutureAdapter<Void> outRebuildCacheIdxFut = new GridFutureAdapter<>();
IgniteLogger log = cctx.kernalContext().grid().log();
// An internal future for the ability to cancel index rebuilding.
SchemaIndexCacheFuture intRebFut = new SchemaIndexCacheFuture(cancelTok);
SchemaIndexCacheFuture prevIntRebFut = idxRebuildFuts.put(cctx.cacheId(), intRebFut);
// Check that the previous rebuild is completed.
assert prevIntRebFut == null;
cctx.kernalContext().query().onStartRebuildIndexes(cctx);
rebuildCacheIdxFut.listen(fut -> {
Throwable err = fut.error();
if (err == null) {
try {
cctx.kernalContext().query().markAsRebuildNeeded(cctx, false);
} catch (Throwable t) {
err = t;
}
}
if (err != null)
U.error(log, "Failed to rebuild indexes for cache: " + cacheName, err);
else
cctx.kernalContext().query().onFinishRebuildIndexes(cctx);
idxRebuildFuts.remove(cctx.cacheId(), intRebFut);
intRebFut.onDone(err);
outRebuildCacheIdxFut.onDone(err);
});
startRebuild(cctx, rebuildCacheIdxFut, clo, intRebFut.cancelToken());
return outRebuildCacheIdxFut;
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class WalStateManager method init.
/**
* Initiate WAL mode change operation.
*
* @param cacheNames Cache names.
* @param enabled Enabled flag.
* @return Future completed when operation finished.
*/
private IgniteInternalFuture<Boolean> init(Collection<String> cacheNames, boolean enabled) {
if (!enabled && prohibitDisabling)
return errorFuture("WAL disabling is prohibited.");
if (F.isEmpty(cacheNames))
return errorFuture("Cache names cannot be empty.");
synchronized (mux) {
if (disconnected)
return errorFuture("Failed to initiate WAL mode change because client node is disconnected.");
// Prepare cache and group infos.
Map<String, IgniteUuid> caches = new HashMap<>(cacheNames.size());
CacheGroupDescriptor grpDesc = null;
for (String cacheName : cacheNames) {
DynamicCacheDescriptor cacheDesc = cacheProcessor().cacheDescriptor(cacheName);
if (cacheDesc == null)
return errorFuture("Cache doesn't exist: " + cacheName);
caches.put(cacheName, cacheDesc.deploymentId());
CacheGroupDescriptor curGrpDesc = cacheDesc.groupDescriptor();
if (grpDesc == null)
grpDesc = curGrpDesc;
else if (!F.eq(grpDesc.deploymentId(), curGrpDesc.deploymentId())) {
return errorFuture("Cannot change WAL mode for caches from different cache groups [" + "cache1=" + cacheNames.iterator().next() + ", grp1=" + grpDesc.groupName() + ", cache2=" + cacheName + ", grp2=" + curGrpDesc.groupName() + ']');
}
}
assert grpDesc != null;
HashSet<String> grpCaches = new HashSet<>(grpDesc.caches().keySet());
grpCaches.removeAll(cacheNames);
if (!grpCaches.isEmpty()) {
return errorFuture("Cannot change WAL mode because not all cache names belonging to the group are " + "provided [group=" + grpDesc.groupName() + ", missingCaches=" + grpCaches + ']');
}
if (grpDesc.config().getCacheMode() == CacheMode.LOCAL)
return errorFuture("WAL mode cannot be changed for LOCAL cache(s): " + cacheNames);
// WAL mode change makes sense only for persistent groups.
if (!grpDesc.persistenceEnabled())
return errorFuture("Cannot change WAL mode because persistence is not enabled for cache(s) [" + "caches=" + cacheNames + ", dataRegion=" + grpDesc.config().getDataRegionName() + ']');
// Send request.
final UUID opId = UUID.randomUUID();
GridFutureAdapter<Boolean> fut = new GridFutureAdapter<>();
fut.listen(new IgniteInClosure<IgniteInternalFuture<Boolean>>() {
@Override
public void apply(IgniteInternalFuture<Boolean> fut) {
synchronized (mux) {
userFuts.remove(opId);
}
}
});
WalStateProposeMessage msg = new WalStateProposeMessage(opId, grpDesc.groupId(), grpDesc.deploymentId(), cctx.localNodeId(), caches, enabled);
userFuts.put(opId, fut);
try {
cctx.discovery().sendCustomEvent(msg);
if (log.isDebugEnabled())
log.debug("Initiated WAL state change operation: " + msg);
} catch (Exception e) {
IgniteCheckedException e0 = new IgniteCheckedException("Failed to initiate WAL mode change due to unexpected exception.", e);
fut.onDone(e0);
}
return fut;
}
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class IgniteSnapshotManager method checkSnapshot.
/**
* The check snapshot procedure performs compute operation over the whole cluster to verify the snapshot
* entirety and partitions consistency. The result future will be completed with an exception if this
* exception is not related to the check procedure, and will be completed normally with the {@code IdleVerifyResult}.
*
* @param name Snapshot name.
* @param grps Collection of cache group names to check.
* @param includeCustomHandlers {@code True} to invoke all user-defined {@link SnapshotHandlerType#RESTORE}
* handlers, otherwise only system consistency check will be performed.
* @return Future with the result of execution snapshot partitions verify task, which besides calculating partition
* hashes of {@link IdleVerifyResultV2} also contains the snapshot metadata distribution across the cluster.
*/
public IgniteInternalFuture<SnapshotPartitionsVerifyTaskResult> checkSnapshot(String name, @Nullable Collection<String> grps, boolean includeCustomHandlers) {
A.notNullOrEmpty(name, "Snapshot name cannot be null or empty.");
A.ensure(U.alphanumericUnderscore(name), "Snapshot name must satisfy the following name pattern: a-zA-Z0-9_");
A.ensure(grps == null || grps.stream().filter(Objects::isNull).collect(Collectors.toSet()).isEmpty(), "Collection of cache groups names cannot contain null elements.");
GridFutureAdapter<SnapshotPartitionsVerifyTaskResult> res = new GridFutureAdapter<>();
GridKernalContext kctx0 = cctx.kernalContext();
Collection<ClusterNode> bltNodes = F.view(cctx.discovery().serverNodes(AffinityTopologyVersion.NONE), (node) -> CU.baselineNode(node, kctx0.state().clusterState()));
kctx0.task().setThreadContext(TC_SKIP_AUTH, true);
kctx0.task().setThreadContext(TC_SUBGRID, bltNodes);
kctx0.task().execute(SnapshotMetadataCollectorTask.class, name).listen(f0 -> {
if (f0.error() == null) {
Map<ClusterNode, List<SnapshotMetadata>> metas = f0.result();
Map<Integer, String> grpIds = grps == null ? Collections.emptyMap() : grps.stream().collect(Collectors.toMap(CU::cacheId, v -> v));
for (List<SnapshotMetadata> nodeMetas : metas.values()) {
for (SnapshotMetadata meta : nodeMetas) grpIds.keySet().removeAll(meta.partitions().keySet());
}
if (!grpIds.isEmpty()) {
res.onDone(new SnapshotPartitionsVerifyTaskResult(metas, new IdleVerifyResultV2(Collections.singletonMap(cctx.localNode(), new IllegalArgumentException("Cache group(s) was not " + "found in the snapshot [groups=" + grpIds.values() + ", snapshot=" + name + ']')))));
return;
}
kctx0.task().setThreadContext(TC_SKIP_AUTH, true);
kctx0.task().setThreadContext(TC_SUBGRID, new ArrayList<>(metas.keySet()));
Class<? extends AbstractSnapshotVerificationTask> cls = includeCustomHandlers ? SnapshotHandlerRestoreTask.class : SnapshotPartitionsVerifyTask.class;
kctx0.task().execute(cls, new SnapshotPartitionsVerifyTaskArg(grps, metas)).listen(f1 -> {
if (f1.error() == null)
res.onDone(f1.result());
else if (f1.error() instanceof IgniteSnapshotVerifyException)
res.onDone(new SnapshotPartitionsVerifyTaskResult(metas, new IdleVerifyResultV2(((IgniteSnapshotVerifyException) f1.error()).exceptions())));
else
res.onDone(f1.error());
});
} else {
if (f0.error() instanceof IgniteSnapshotVerifyException)
res.onDone(new SnapshotPartitionsVerifyTaskResult(null, new IdleVerifyResultV2(((IgniteSnapshotVerifyException) f0.error()).exceptions())));
else
res.onDone(f0.error());
}
});
return res;
}
Aggregations