/** {@inheritDoc} */
  @Override
  public GridDhtPartitionMap localPartitionMap() {
    lock.readLock().lock();

    try {
      return new GridDhtPartitionMap(
          cctx.nodeId(), updateSeq.get(), F.viewReadOnly(locParts, CU.part2state()), true);
    } finally {
      lock.readLock().unlock();
    }
  }
  /** @param nodeId Node to remove. */
  private void removeNode(UUID nodeId) {
    assert nodeId != null;
    assert lock.writeLock().isHeldByCurrentThread();

    ClusterNode oldest = CU.oldestAliveCacheServerNode(cctx.shared(), topVer);

    assert oldest != null;

    ClusterNode loc = cctx.localNode();

    if (node2part != null) {
      if (oldest.equals(loc) && !node2part.nodeId().equals(loc.id())) {
        updateSeq.setIfGreater(node2part.updateSequence());

        node2part =
            new GridDhtPartitionFullMap(
                loc.id(), loc.order(), updateSeq.incrementAndGet(), node2part, false);
      } else node2part = new GridDhtPartitionFullMap(node2part, node2part.updateSequence());

      part2node = new HashMap<>(part2node);

      GridDhtPartitionMap parts = node2part.remove(nodeId);

      if (parts != null) {
        for (Integer p : parts.keySet()) {
          Set<UUID> nodeIds = part2node.get(p);

          if (nodeIds != null) {
            nodeIds.remove(nodeId);

            if (nodeIds.isEmpty()) part2node.remove(p);
          }
        }
      }

      consistencyCheck();
    }
  }
  public void onReconnected() {
    lock.writeLock().lock();

    try {
      node2part = null;

      part2node = new HashMap<>();

      lastExchangeId = null;

      updateSeq.set(1);

      topReadyFut = null;

      topVer = AffinityTopologyVersion.NONE;
    } finally {
      lock.writeLock().unlock();
    }
  }
  /** {@inheritDoc} */
  @Override
  public boolean own(GridDhtLocalPartition part) {
    ClusterNode loc = cctx.localNode();

    lock.writeLock().lock();

    try {
      if (part.own()) {
        updateLocal(part.id(), loc.id(), part.state(), updateSeq.incrementAndGet());

        consistencyCheck();

        return true;
      }

      consistencyCheck();

      return false;
    } finally {
      lock.writeLock().unlock();
    }
  }
  /** {@inheritDoc} */
  @Override
  public void updateTopologyVersion(
      GridDhtPartitionExchangeId exchId,
      GridDhtPartitionsExchangeFuture exchFut,
      long updSeq,
      boolean stopping) {
    lock.writeLock().lock();

    try {
      assert exchId.topologyVersion().compareTo(topVer) > 0
          : "Invalid topology version [topVer=" + topVer + ", exchId=" + exchId + ']';

      this.stopping = stopping;

      topVer = exchId.topologyVersion();

      updateSeq.setIfGreater(updSeq);

      topReadyFut = exchFut;
    } finally {
      lock.writeLock().unlock();
    }
  }
 /** {@inheritDoc} */
 @Override
 public long updateSequence() {
   return updateSeq.get();
 }