use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.
the class GridDhtTxPrepareFuture method map.
/**
* @param entry Transaction entry.
*/
private void map(IgniteTxEntry entry) throws IgniteTxRollbackCheckedException {
if (entry.cached().isLocal())
return;
GridDhtCacheEntry cached = (GridDhtCacheEntry) entry.cached();
GridCacheContext cacheCtx = entry.context();
GridDhtCacheAdapter<?, ?> dht = cacheCtx.isNear() ? cacheCtx.near().dht() : cacheCtx.dht();
ExpiryPolicy expiry = cacheCtx.expiryForTxEntry(entry);
if (expiry != null && (entry.op() == READ || entry.op() == NOOP)) {
entry.op(NOOP);
entry.ttl(CU.toTtl(expiry.getExpiryForAccess()));
}
while (true) {
try {
List<ClusterNode> dhtNodes = dht.topology().nodes(cached.partition(), tx.topologyVersion());
GridDhtPartitionTopology top = cacheCtx.topology();
GridDhtLocalPartition part = top.localPartition(cached.partition());
if (part != null && !part.primary(top.readyTopologyVersion())) {
log.warning("Failed to map a transaction on outdated topology, rolling back " + "[tx=" + CU.txString(tx) + ", readyTopVer=" + top.readyTopologyVersion() + ", lostParts=" + top.lostPartitions() + ", part=" + part.toString() + ']');
throw new IgniteTxRollbackCheckedException("Failed to map a transaction on outdated " + "topology, please try again [timeout=" + tx.timeout() + ", tx=" + CU.txString(tx) + ']');
}
assert !dhtNodes.isEmpty() && dhtNodes.get(0).id().equals(cctx.localNodeId()) : "cacheId=" + cacheCtx.cacheId() + ", localNode = " + cctx.localNodeId() + ", dhtNodes = " + dhtNodes;
if (log.isDebugEnabled())
log.debug("Mapping entry to DHT nodes [nodes=" + U.toShortString(dhtNodes) + ", entry=" + entry + ']');
for (int i = 1; i < dhtNodes.size(); i++) {
ClusterNode node = dhtNodes.get(i);
addMapping(entry, node, dhtMap);
}
Collection<UUID> readers = cached.readers();
if (!F.isEmpty(readers)) {
for (UUID readerId : readers) {
if (readerId.equals(tx.nearNodeId()))
continue;
ClusterNode readerNode = cctx.discovery().node(readerId);
if (readerNode == null || canSkipNearReader(dht, readerNode, dhtNodes))
continue;
if (log.isDebugEnabled())
log.debug("Mapping entry to near node [node=" + readerNode + ", entry=" + entry + ']');
addMapping(entry, readerNode, nearMap);
}
} else if (log.isDebugEnabled())
log.debug("Entry has no near readers: " + entry);
break;
} catch (GridCacheEntryRemovedException ignore) {
cached = dht.entryExx(entry.key(), tx.topologyVersion());
entry.cached(cached);
}
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.
the class GridDhtTransactionalCacheAdapter method startRemoteTx.
/**
* @param nodeId Primary node ID.
* @param req Request.
* @param res Response.
* @return Remote transaction.
* @throws IgniteCheckedException If failed.
* @throws GridDistributedLockCancelledException If lock has been cancelled.
*/
@Nullable
private GridDhtTxRemote startRemoteTx(UUID nodeId, GridDhtLockRequest req, GridDhtLockResponse res) throws IgniteCheckedException, GridDistributedLockCancelledException {
List<KeyCacheObject> keys = req.keys();
GridDhtTxRemote tx = null;
int size = F.size(keys);
for (int i = 0; i < size; i++) {
KeyCacheObject key = keys.get(i);
if (key == null)
continue;
IgniteTxKey txKey = ctx.txKey(key);
if (log.isDebugEnabled())
log.debug("Unmarshalled key: " + key);
GridDistributedCacheEntry entry = null;
while (true) {
try {
int part = ctx.affinity().partition(key);
GridDhtLocalPartition locPart = ctx.topology().localPartition(part, req.topologyVersion(), false);
if (locPart == null || !locPart.reserve()) {
if (log.isDebugEnabled())
log.debug("Local partition for given key is already evicted (will add to invalid " + "partition list) [key=" + key + ", part=" + part + ", locPart=" + locPart + ']');
res.addInvalidPartition(part);
// Invalidate key in near cache, if any.
if (isNearEnabled(cacheCfg))
obsoleteNearEntry(key);
break;
}
try {
// Handle implicit locks for pessimistic transactions.
if (req.inTx()) {
if (tx == null)
tx = ctx.tm().tx(req.version());
if (tx == null) {
tx = new GridDhtTxRemote(ctx.shared(), req.nodeId(), req.futureId(), nodeId, req.nearXidVersion(), req.topologyVersion(), req.version(), /*commitVer*/
null, ctx.systemTx(), ctx.ioPolicy(), PESSIMISTIC, req.isolation(), req.isInvalidate(), req.timeout(), req.txSize(), securitySubjectId(ctx), req.taskNameHash(), !req.skipStore() && req.storeUsed(), req.txLabel());
tx = ctx.tm().onCreated(null, tx);
if (tx == null || !ctx.tm().onStarted(tx))
throw new IgniteTxRollbackCheckedException("Failed to acquire lock (transaction " + "has been completed) [ver=" + req.version() + ", tx=" + tx + ']');
}
tx.addWrite(ctx, NOOP, txKey, null, null, req.accessTtl(), req.skipStore(), req.keepBinary());
}
entry = entryExx(key, req.topologyVersion());
// Add remote candidate before reordering.
entry.addRemote(req.nodeId(), nodeId, req.threadId(), req.version(), tx != null, tx != null && tx.implicitSingle(), null);
// Invalidate key in near cache, if any.
if (isNearEnabled(cacheCfg) && req.invalidateNearEntry(i))
invalidateNearEntry(key, req.version());
// Get entry info after candidate is added.
if (req.needPreloadKey(i)) {
entry.unswap();
GridCacheEntryInfo info = entry.info();
if (info != null && !info.isNew() && !info.isDeleted())
res.addPreloadEntry(info);
}
// Double-check in case if sender node left the grid.
if (ctx.discovery().node(req.nodeId()) == null) {
if (log.isDebugEnabled())
log.debug("Node requesting lock left grid (lock request will be ignored): " + req);
entry.removeLock(req.version());
if (tx != null) {
tx.clearEntry(txKey);
// COMMITTING state, but this lock is never acquired.
if (tx.state() == COMMITTING)
tx.forceCommit();
else
tx.rollbackRemoteTx();
}
return null;
}
// Entry is legit.
break;
} finally {
locPart.release();
}
} catch (GridDhtInvalidPartitionException e) {
if (log.isDebugEnabled())
log.debug("Received invalid partition exception [e=" + e + ", req=" + req + ']');
res.addInvalidPartition(e.partition());
// Invalidate key in near cache, if any.
if (isNearEnabled(cacheCfg))
obsoleteNearEntry(key);
if (tx != null) {
tx.clearEntry(txKey);
if (log.isDebugEnabled())
log.debug("Cleared invalid entry from remote transaction (will skip) [entry=" + entry + ", tx=" + tx + ']');
}
break;
} catch (GridCacheEntryRemovedException ignored) {
assert entry.obsoleteVersion() != null : "Obsolete flag not set on removed entry: " + entry;
if (log.isDebugEnabled())
log.debug("Received entry removed exception (will retry on renewed entry): " + entry);
if (tx != null) {
tx.clearEntry(txKey);
if (log.isDebugEnabled())
log.debug("Cleared removed entry from remote transaction (will retry) [entry=" + entry + ", tx=" + tx + ']');
}
}
}
}
if (tx != null && tx.empty()) {
if (log.isDebugEnabled())
log.debug("Rolling back remote DHT transaction because it is empty [req=" + req + ", res=" + res + ']');
tx.rollbackRemoteTx();
tx = null;
}
return tx;
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.
the class IdleVerifyUtility method getUpdateCountersSnapshot.
/**
* Gather updateCounters info.
* Holds {@link org.apache.ignite.internal.processors.cache.PartitionUpdateCounter#copy} of update counters.
*
* @param ign Ignite instance.
* @param grpIds Group Id`s.
* @return Current groups distribution with update counters per partitions.
*/
public static Map<Integer, Map<Integer, PartitionUpdateCounter>> getUpdateCountersSnapshot(IgniteEx ign, Set<Integer> grpIds) {
Map<Integer, Map<Integer, PartitionUpdateCounter>> partsWithCountersPerGrp = new HashMap<>();
for (Integer grpId : grpIds) {
CacheGroupContext grpCtx = ign.context().cache().cacheGroup(grpId);
if (grpCtx == null)
throw new GridNotIdleException("Group not found: " + grpId + "." + " Possible reasons: rebalance in progress or concurrent cache destroy.");
GridDhtPartitionTopology top = grpCtx.topology();
Map<Integer, PartitionUpdateCounter> partsWithCounters = partsWithCountersPerGrp.computeIfAbsent(grpId, k -> new HashMap<>());
for (GridDhtLocalPartition part : top.currentLocalPartitions()) {
if (part.state() != GridDhtPartitionState.OWNING)
continue;
@Nullable PartitionUpdateCounter updCntr = part.dataStore().partUpdateCounter();
partsWithCounters.put(part.id(), updCntr == null ? null : updCntr.copy());
}
}
return partsWithCountersPerGrp;
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.
the class IgniteCacheOffheapManagerImpl method evictionSafeIterator.
/**
* @param cacheId Cache ID.
* @param dataIt Data store iterator.
* @return Rows iterator
*/
private GridCloseableIterator<CacheDataRow> evictionSafeIterator(int cacheId, Iterator<CacheDataStore> dataIt) {
return new GridCloseableIteratorAdapter<CacheDataRow>() {
/**
*/
private GridCursor<? extends CacheDataRow> cur;
/**
*/
private GridDhtLocalPartition curPart;
/**
*/
private CacheDataRow next;
@Override
protected CacheDataRow onNext() {
CacheDataRow res = next;
next = null;
return res;
}
@Override
protected boolean onHasNext() throws IgniteCheckedException {
if (next != null)
return true;
while (true) {
if (cur == null) {
if (dataIt.hasNext()) {
CacheDataStore ds = dataIt.next();
if (!reservePartition(ds.partId()))
continue;
cur = cacheId == CU.UNDEFINED_CACHE_ID ? ds.cursor() : ds.cursor(cacheId);
} else
break;
}
if (cur.next()) {
next = cur.get();
next.key().partition(curPart.id());
break;
} else {
cur = null;
releaseCurrentPartition();
}
}
return next != null;
}
/**
*/
private void releaseCurrentPartition() {
GridDhtLocalPartition p = curPart;
assert p != null;
curPart = null;
p.release();
}
/**
* @param partId Partition number.
* @return {@code True} if partition was reserved.
*/
private boolean reservePartition(int partId) {
GridDhtLocalPartition p = grp.topology().localPartition(partId);
if (p != null && p.reserve()) {
curPart = p;
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
protected void onClose() throws IgniteCheckedException {
if (curPart != null)
releaseCurrentPartition();
}
};
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.topology.GridDhtLocalPartition in project ignite by apache.
the class IgniteCacheOffheapManagerImpl method reservedIterator.
/**
* {@inheritDoc}
*/
@Override
public GridCloseableIterator<CacheDataRow> reservedIterator(int part, AffinityTopologyVersion topVer) {
GridDhtLocalPartition loc = grp.topology().localPartition(part, topVer, false);
if (loc == null || !loc.reserve())
return null;
// It is necessary to check state after reservation to avoid race conditions.
if (loc.state() != OWNING) {
loc.release();
return null;
}
CacheDataStore data = dataStore(loc);
return new GridCloseableIteratorAdapter<CacheDataRow>() {
/**
*/
private CacheDataRow next;
/**
*/
private GridCursor<? extends CacheDataRow> cur;
@Override
protected CacheDataRow onNext() {
CacheDataRow res = next;
next = null;
return res;
}
@Override
protected boolean onHasNext() throws IgniteCheckedException {
if (cur == null)
cur = data.cursor(CacheDataRowAdapter.RowData.FULL_WITH_HINTS);
if (next != null)
return true;
if (cur.next())
next = cur.get();
boolean hasNext = next != null;
if (!hasNext)
cur = null;
return hasNext;
}
@Override
protected void onClose() throws IgniteCheckedException {
assert loc != null && loc.state() == OWNING && loc.reservations() > 0 : "Partition should be in OWNING state and has at least 1 reservation: " + loc;
loc.release();
cur = null;
}
};
}
Aggregations