All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.internal.util.iterator.RestartingMemberIterator Maven / Gradle / Ivy

There is a newer version: 5.5.0
Show newest version
/*
 * Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.hazelcast.internal.util.iterator;

import com.hazelcast.core.HazelcastException;
import com.hazelcast.core.HazelcastInstanceNotActiveException;
import com.hazelcast.core.Member;
import com.hazelcast.core.MemberLeftException;
import com.hazelcast.internal.cluster.ClusterService;
import com.hazelcast.internal.cluster.impl.ClusterTopologyChangedException;
import com.hazelcast.internal.util.futures.ChainingFuture;
import com.hazelcast.spi.exception.TargetNotMemberException;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;

import static java.lang.String.format;

/**
 * Iterates over stable cluster from the oldest to youngest member.
 * It restarts when detects a cluster topology change.
 * 

* It can be used from multiple threads, but not concurrently. */ public class RestartingMemberIterator implements Iterator, ChainingFuture.ExceptionHandler { private final Queue memberQueue = new ConcurrentLinkedQueue(); private final AtomicInteger retryCounter = new AtomicInteger(); private final ClusterService clusterService; private final int maxRetries; private volatile boolean topologyChanged; private volatile Member nextMember; private volatile Set initialMembers; public RestartingMemberIterator(ClusterService clusterService, int maxRetries) { this.clusterService = clusterService; this.maxRetries = maxRetries; Set currentMembers = clusterService.getMembers(); startNewRound(currentMembers); } private void startNewRound(Set currentMembers) { topologyChanged = false; memberQueue.addAll(currentMembers); nextMember = memberQueue.poll(); initialMembers = currentMembers; } @Override public boolean hasNext() { if (nextMember != null) { return true; } return advance(); } private boolean advance() { Set currentMembers = clusterService.getMembers(); if (topologyChanged(currentMembers)) { retry(currentMembers); // at any given moment there should always be at least one cluster member (our own member) assert nextMember != null; return true; } nextMember = memberQueue.poll(); return nextMember != null; } private void retry(Set currentMembers) { if (retryCounter.incrementAndGet() > maxRetries) { throw new HazelcastException(format("Cluster topology was not stable for %d retries," + " invoke on stable cluster failed", maxRetries)); } memberQueue.clear(); startNewRound(currentMembers); } private boolean topologyChanged(Set currentMembers) { return topologyChanged || !currentMembers.equals(initialMembers); } @Override public Member next() { Member memberToReturn = nextMember; nextMember = null; if (memberToReturn != null) { return memberToReturn; } if (!advance()) { throw new NoSuchElementException("no more elements"); } memberToReturn = nextMember; nextMember = null; return memberToReturn; } @Override public void remove() { throw new UnsupportedOperationException("not implemented"); } @Override public void handle(T throwable) throws T { if (throwable instanceof ClusterTopologyChangedException) { topologyChanged = true; return; } if (throwable instanceof MemberLeftException || throwable instanceof TargetNotMemberException || throwable instanceof HazelcastInstanceNotActiveException) { return; } throw throwable; } public int getRetryCount() { return retryCounter.get(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy