use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap in project ignite by apache.
the class GridDhtPartitionTopologyImpl method update.
/**
* {@inheritDoc}
*/
@SuppressWarnings({ "MismatchedQueryAndUpdateOfCollection" })
@Override
public boolean update(@Nullable AffinityTopologyVersion exchangeVer, GridDhtPartitionFullMap partMap, @Nullable CachePartitionFullCountersMap incomeCntrMap, Set<Integer> partsToReload, @Nullable AffinityTopologyVersion msgTopVer) {
if (log.isDebugEnabled()) {
log.debug("Updating full partition map [grp=" + grp.cacheOrGroupName() + ", exchVer=" + exchangeVer + ", fullMap=" + fullMapString() + ']');
}
assert partMap != null;
ctx.database().checkpointReadLock();
try {
lock.writeLock().lock();
try {
if (stopping || !lastTopChangeVer.initialized() || // Ignore message not-related to exchange if exchange is in progress.
(exchangeVer == null && !lastTopChangeVer.equals(readyTopVer)))
return false;
if (incomeCntrMap != null) {
// update local counters in partitions
for (int i = 0; i < locParts.length(); i++) {
GridDhtLocalPartition part = locParts.get(i);
if (part == null)
continue;
if (part.state() == OWNING || part.state() == MOVING) {
long updCntr = incomeCntrMap.updateCounter(part.id());
if (updCntr != 0 && updCntr > part.updateCounter())
part.updateCounter(updCntr);
}
}
}
if (exchangeVer != null) {
// Ignore if exchange already finished or new exchange started.
if (readyTopVer.compareTo(exchangeVer) > 0 || lastTopChangeVer.compareTo(exchangeVer) > 0) {
U.warn(log, "Stale exchange id for full partition map update (will ignore) [" + "grp=" + grp.cacheOrGroupName() + ", lastTopChange=" + lastTopChangeVer + ", readTopVer=" + readyTopVer + ", exchVer=" + exchangeVer + ']');
return false;
}
}
if (msgTopVer != null && lastTopChangeVer.compareTo(msgTopVer) > 0) {
U.warn(log, "Stale version for full partition map update message (will ignore) [" + "grp=" + grp.cacheOrGroupName() + ", lastTopChange=" + lastTopChangeVer + ", readTopVer=" + readyTopVer + ", msgVer=" + msgTopVer + ']');
return false;
}
boolean fullMapUpdated = (node2part == null);
if (node2part != null) {
for (GridDhtPartitionMap part : node2part.values()) {
GridDhtPartitionMap newPart = partMap.get(part.nodeId());
if (shouldOverridePartitionMap(part, newPart)) {
fullMapUpdated = true;
if (log.isDebugEnabled()) {
log.debug("Overriding partition map in full update map [" + "grp=" + grp.cacheOrGroupName() + ", exchVer=" + exchangeVer + ", curPart=" + mapString(part) + ", newPart=" + mapString(newPart) + ']');
}
if (newPart.nodeId().equals(ctx.localNodeId()))
updateSeq.setIfGreater(newPart.updateSequence());
} else {
// If for some nodes current partition has a newer map,
// then we keep the newer value.
partMap.put(part.nodeId(), part);
}
}
// Check that we have new nodes.
for (GridDhtPartitionMap part : partMap.values()) {
if (fullMapUpdated)
break;
fullMapUpdated = !node2part.containsKey(part.nodeId());
}
// Remove entry if node left.
for (Iterator<UUID> it = partMap.keySet().iterator(); it.hasNext(); ) {
UUID nodeId = it.next();
if (!ctx.discovery().alive(nodeId)) {
if (log.isDebugEnabled())
log.debug("Removing left node from full map update [grp=" + grp.cacheOrGroupName() + ", nodeId=" + nodeId + ", partMap=" + partMap + ']');
it.remove();
}
}
} else {
GridDhtPartitionMap locNodeMap = partMap.get(ctx.localNodeId());
if (locNodeMap != null)
updateSeq.setIfGreater(locNodeMap.updateSequence());
}
if (!fullMapUpdated) {
if (log.isDebugEnabled()) {
log.debug("No updates for full partition map (will ignore) [" + "grp=" + grp.cacheOrGroupName() + ", lastExch=" + lastTopChangeVer + ", exchVer=" + exchangeVer + ", curMap=" + node2part + ", newMap=" + partMap + ']');
}
return false;
}
if (exchangeVer != null) {
assert exchangeVer.compareTo(readyTopVer) >= 0 && exchangeVer.compareTo(lastTopChangeVer) >= 0;
lastTopChangeVer = readyTopVer = exchangeVer;
}
node2part = partMap;
if (exchangeVer == null && !grp.isReplicated() && (readyTopVer.initialized() && readyTopVer.compareTo(diffFromAffinityVer) >= 0)) {
AffinityAssignment affAssignment = grp.affinity().readyAffinity(readyTopVer);
for (Map.Entry<UUID, GridDhtPartitionMap> e : partMap.entrySet()) {
for (Map.Entry<Integer, GridDhtPartitionState> e0 : e.getValue().entrySet()) {
int p = e0.getKey();
Set<UUID> diffIds = diffFromAffinity.get(p);
if ((e0.getValue() == MOVING || e0.getValue() == OWNING || e0.getValue() == RENTING) && !affAssignment.getIds(p).contains(e.getKey())) {
if (diffIds == null)
diffFromAffinity.put(p, diffIds = U.newHashSet(3));
diffIds.add(e.getKey());
} else {
if (diffIds != null && diffIds.remove(e.getKey())) {
if (diffIds.isEmpty())
diffFromAffinity.remove(p);
}
}
}
}
diffFromAffinityVer = readyTopVer;
}
boolean changed = false;
GridDhtPartitionMap nodeMap = partMap.get(ctx.localNodeId());
if (nodeMap != null && grp.persistenceEnabled() && readyTopVer.initialized()) {
for (Map.Entry<Integer, GridDhtPartitionState> e : nodeMap.entrySet()) {
int p = e.getKey();
GridDhtPartitionState state = e.getValue();
if (state == OWNING) {
GridDhtLocalPartition locPart = locParts.get(p);
assert locPart != null : grp.cacheOrGroupName();
if (locPart.state() == MOVING) {
boolean success = locPart.own();
assert success : locPart;
changed |= success;
}
} else if (state == MOVING) {
GridDhtLocalPartition locPart = locParts.get(p);
if (!partsToReload.contains(p)) {
if (locPart == null || locPart.state() == EVICTED)
locPart = createPartition(p);
if (locPart.state() == OWNING) {
locPart.moving();
changed = true;
}
} else {
if (locPart == null || locPart.state() == EVICTED) {
createPartition(p);
changed = true;
} else if (locPart.state() == OWNING || locPart.state() == MOVING) {
if (locPart.state() == OWNING)
locPart.moving();
locPart.clearAsync();
changed = true;
} else if (locPart.state() == RENTING) {
// Try to prevent partition eviction.
if (locPart.reserve()) {
try {
locPart.moving();
locPart.clearAsync();
} finally {
locPart.release();
}
} else // In other case just recreate it.
{
assert locPart.state() == EVICTED;
createPartition(p);
}
changed = true;
}
}
}
}
}
long updateSeq = this.updateSeq.incrementAndGet();
if (readyTopVer.initialized() && readyTopVer.equals(lastTopChangeVer)) {
AffinityAssignment aff = grp.affinity().readyAffinity(readyTopVer);
if (exchangeVer == null)
changed |= checkEvictions(updateSeq, aff);
updateRebalanceVersion(aff.assignment());
}
consistencyCheck();
if (log.isDebugEnabled()) {
log.debug("Partition map after full update [grp=" + grp.cacheOrGroupName() + ", map=" + fullMapString() + ']');
}
if (changed)
ctx.exchange().scheduleResendPartitions();
return changed;
} finally {
lock.writeLock().unlock();
}
} finally {
ctx.database().checkpointReadUnlock();
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap in project ignite by apache.
the class GridDhtPartitionTopologyImpl method rebuildDiff.
/**
* Rebuilds {@link #diffFromAffinity} from given assignment.
*
* @param affAssignment New affinity assignment.
*/
private void rebuildDiff(AffinityAssignment affAssignment) {
assert lock.isWriteLockedByCurrentThread();
if (node2part == null)
return;
if (FAST_DIFF_REBUILD) {
Collection<UUID> affNodes = F.nodeIds(ctx.discovery().cacheGroupAffinityNodes(grp.groupId(), affAssignment.topologyVersion()));
for (Map.Entry<Integer, Set<UUID>> e : diffFromAffinity.entrySet()) {
int p = e.getKey();
Iterator<UUID> iter = e.getValue().iterator();
while (iter.hasNext()) {
UUID nodeId = iter.next();
if (!affNodes.contains(nodeId) || affAssignment.getIds(p).contains(nodeId))
iter.remove();
}
}
} else {
for (Map.Entry<UUID, GridDhtPartitionMap> e : node2part.entrySet()) {
UUID nodeId = e.getKey();
for (Map.Entry<Integer, GridDhtPartitionState> e0 : e.getValue().entrySet()) {
Integer p0 = e0.getKey();
GridDhtPartitionState state = e0.getValue();
Set<UUID> ids = diffFromAffinity.get(p0);
if ((state == MOVING || state == OWNING || state == RENTING) && !affAssignment.getIds(p0).contains(nodeId)) {
if (ids == null)
diffFromAffinity.put(p0, ids = U.newHashSet(3));
ids.add(nodeId);
} else {
if (ids != null)
ids.remove(nodeId);
}
}
}
}
diffFromAffinityVer = affAssignment.topologyVersion();
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap in project ignite by apache.
the class GridDhtPartitionTopologyImpl method localPartitionMap.
/**
* {@inheritDoc}
*/
@Override
public GridDhtPartitionMap localPartitionMap() {
GridPartitionStateMap map = new GridPartitionStateMap(locParts.length());
lock.readLock().lock();
try {
for (int i = 0; i < locParts.length(); i++) {
GridDhtLocalPartition part = locParts.get(i);
if (part == null)
continue;
map.put(i, part.state());
}
GridDhtPartitionMap locPartMap = node2part != null ? node2part.get(ctx.localNodeId()) : null;
return new GridDhtPartitionMap(ctx.localNodeId(), updateSeq.get(), locPartMap != null ? locPartMap.topologyVersion() : readyTopVer, map, true);
} finally {
lock.readLock().unlock();
}
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap in project ignite by apache.
the class GridClientPartitionTopology method updateLocal.
/**
* Updates value for single partition.
*
* @param p Partition.
* @param nodeId Node ID.
* @param state State.
* @param updateSeq Update sequence.
*/
private void updateLocal(int p, UUID nodeId, GridDhtPartitionState state, long updateSeq) {
assert lock.isWriteLockedByCurrentThread();
assert nodeId.equals(cctx.localNodeId());
// In case if node joins, get topology at the time of joining node.
ClusterNode oldest = discoCache.oldestAliveServerNode();
// If this node became the oldest node.
if (cctx.localNode().equals(oldest)) {
long seq = node2part.updateSequence();
if (seq != updateSeq) {
if (seq > updateSeq) {
if (this.updateSeq.get() < seq) {
// Update global counter if necessary.
boolean b = this.updateSeq.compareAndSet(this.updateSeq.get(), seq + 1);
assert b : "Invalid update sequence [updateSeq=" + updateSeq + ", seq=" + seq + ", curUpdateSeq=" + this.updateSeq.get() + ", node2part=" + node2part.toFullString() + ']';
updateSeq = seq + 1;
} else
updateSeq = seq;
}
node2part.updateSequence(updateSeq);
}
}
GridDhtPartitionMap map = node2part.get(nodeId);
if (map == null)
node2part.put(nodeId, map = new GridDhtPartitionMap(nodeId, updateSeq, topVer, GridPartitionStateMap.EMPTY, false));
map.updateSequence(updateSeq, topVer);
map.put(p, state);
Set<UUID> ids = part2node.get(p);
if (ids == null)
part2node.put(p, ids = U.newHashSet(3));
ids.add(nodeId);
}
use of org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap in project ignite by apache.
the class GridClientPartitionTopology method setOwners.
/**
* {@inheritDoc}
*/
@Override
public Set<UUID> setOwners(int p, Set<UUID> owners, boolean haveHistory, boolean updateSeq) {
Set<UUID> result = haveHistory ? Collections.<UUID>emptySet() : new HashSet<UUID>();
lock.writeLock().lock();
try {
for (Map.Entry<UUID, GridDhtPartitionMap> e : node2part.entrySet()) {
GridDhtPartitionMap partMap = e.getValue();
UUID remoteNodeId = e.getKey();
if (!partMap.containsKey(p))
continue;
if (partMap.get(p) == OWNING && !owners.contains(remoteNodeId)) {
partMap.put(p, MOVING);
if (!haveHistory)
result.add(remoteNodeId);
partMap.updateSequence(partMap.updateSequence() + 1, partMap.topologyVersion());
U.warn(log, "Partition has been scheduled for rebalancing due to outdated update counter " + "[nodeId=" + remoteNodeId + ", groupId=" + grpId + ", partId=" + p + ", haveHistory=" + haveHistory + "]");
}
}
part2node.put(p, owners);
if (updateSeq)
this.updateSeq.incrementAndGet();
} finally {
lock.writeLock().unlock();
}
return result;
}
Aggregations