use of org.apache.cassandra.utils.concurrent.UncheckedInterruptedException in project cassandra by apache.
the class Gossiper method doShadowRound.
/**
* Do a single 'shadow' round of gossip by retrieving endpoint states that will be stored exclusively in the
* map return value, instead of endpointStateMap.
*
* Used when preparing to join the ring:
* <ul>
* <li>when replacing a node, to get and assume its tokens</li>
* <li>when joining, to check that the local host id matches any previous id for the endpoint address</li>
* </ul>
*
* Method is synchronized, as we use an in-progress flag to indicate that shadow round must be cleared
* again by calling {@link Gossiper#maybeFinishShadowRound(InetAddressAndPort, boolean, Map)}. This will update
* {@link Gossiper#endpointShadowStateMap} with received values, in order to return an immutable copy to the
* caller of {@link Gossiper#doShadowRound()}. Therefor only a single shadow round execution is permitted at
* the same time.
*
* @param peers Additional peers to try gossiping with.
* @return endpoint states gathered during shadow round or empty map
*/
public synchronized Map<InetAddressAndPort, EndpointState> doShadowRound(Set<InetAddressAndPort> peers) {
buildSeedsList();
// list in which case, attempting a shadow round is pointless
if (seeds.isEmpty() && peers.isEmpty())
return endpointShadowStateMap;
boolean isSeed = DatabaseDescriptor.getSeeds().contains(getBroadcastAddressAndPort());
// We double RING_DELAY if we're not a seed to increase chance of successful startup during a full cluster bounce,
// giving the seeds a chance to startup before we fail the shadow round
int shadowRoundDelay = isSeed ? StorageService.RING_DELAY : StorageService.RING_DELAY * 2;
seedsInShadowRound.clear();
endpointShadowStateMap.clear();
// send a completely empty syn
List<GossipDigest> gDigests = new ArrayList<>();
GossipDigestSyn digestSynMessage = new GossipDigestSyn(getClusterName(), getPartitionerName(), gDigests);
Message<GossipDigestSyn> message = Message.out(GOSSIP_DIGEST_SYN, digestSynMessage);
inShadowRound = true;
boolean includePeers = false;
int slept = 0;
try {
while (true) {
if (slept % 5000 == 0) {
// CASSANDRA-8072, retry at the beginning and every 5 seconds
logger.trace("Sending shadow round GOSSIP DIGEST SYN to seeds {}", seeds);
for (InetAddressAndPort seed : seeds) MessagingService.instance().send(message, seed);
// Send to any peers we already know about, but only if a seed didn't respond.
if (includePeers) {
logger.trace("Sending shadow round GOSSIP DIGEST SYN to known peers {}", peers);
for (InetAddressAndPort peer : peers) MessagingService.instance().send(message, peer);
}
includePeers = true;
}
Thread.sleep(1000);
if (!inShadowRound)
break;
slept += 1000;
if (slept > shadowRoundDelay) {
// if we got here no peers could be gossiped to. If we're a seed that's OK, but otherwise we stop. See CASSANDRA-13851
if (!isSeed)
throw new RuntimeException("Unable to gossip with any peers");
inShadowRound = false;
break;
}
}
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
}
return ImmutableMap.copyOf(endpointShadowStateMap);
}
use of org.apache.cassandra.utils.concurrent.UncheckedInterruptedException in project cassandra by apache.
the class Gossiper method runInGossipStageBlocking.
public static void runInGossipStageBlocking(Runnable runnable) {
// run immediately if we're already in the gossip stage
if (isInGossipStage()) {
runnable.run();
return;
}
FutureTask<?> task = new FutureTask<>(runnable);
Stage.GOSSIP.execute(task);
try {
task.get();
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
} catch (ExecutionException e) {
throw new AssertionError(e);
}
}
use of org.apache.cassandra.utils.concurrent.UncheckedInterruptedException in project cassandra by apache.
the class HintsBufferPool method switchCurrentBuffer.
private synchronized boolean switchCurrentBuffer(HintsBuffer previous) {
if (currentBuffer != previous)
return false;
HintsBuffer buffer = reserveBuffers.poll();
if (buffer == null && allocatedBuffers >= MAX_ALLOCATED_BUFFERS) {
try {
// This BlockingQueue.take is a target for byteman in HintsBufferPoolTest
buffer = reserveBuffers.take();
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
}
}
currentBuffer = buffer == null ? createBuffer() : buffer;
return true;
}
use of org.apache.cassandra.utils.concurrent.UncheckedInterruptedException in project cassandra by apache.
the class HintsService method excise.
/**
* Cleans up hints-related state after a node with id = hostId left.
*
* Dispatcher can not stop itself (isHostAlive() can not start returning false for the leaving host because this
* method is called by the same thread as gossip, which blocks gossip), so we can't simply wait for
* completion.
*
* We should also flush the buffer if there are any hints for the node there, and close the writer (if any),
* so that we don't leave any hint files lying around.
*
* Once that is done, we can simply delete all hint files and remove the host id from the catalog.
*
* The worst that can happen if we don't get everything right is a hints file (or two) remaining undeleted.
*
* @param hostId id of the node being excised
*/
public void excise(UUID hostId) {
HintsStore store = catalog.getNullable(hostId);
if (store == null)
return;
// flush the buffer and then close the writer for the excised host id, to make sure that no new files will appear
// for this host id after we are done
Future flushFuture = writeExecutor.flushBufferPool(bufferPool, Collections.singleton(store));
Future closeFuture = writeExecutor.closeWriter(store);
try {
flushFuture.get();
closeFuture.get();
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
// interrupt the current dispatch session to end (if any), so that the currently dispatched file gets removed
dispatchExecutor.interruptDispatch(store.hostId);
// delete all the hints files and remove the HintsStore instance from the map in the catalog
catalog.exciseStore(hostId);
}
use of org.apache.cassandra.utils.concurrent.UncheckedInterruptedException in project cassandra by apache.
the class InterceptingMonitors method preMonitorEnter.
@Override
public void preMonitorEnter(Object monitor, float preMonitorDelayChance) {
if (disabled)
return;
Thread anyThread = Thread.currentThread();
if (!(anyThread instanceof InterceptibleThread))
return;
InterceptibleThread thread = (InterceptibleThread) anyThread;
if (!thread.isEvaluationDeterministic() && random.decide(preMonitorDelayChance)) {
// TODO (feature): hold a stack of threads already paused by the nemesis, and, if one of the threads
// is entering the monitor, put the contents of this stack into `waitingOn` for this monitor.
InterceptedConditionWait signal = new InterceptedConditionWait(NEMESIS, 0L, thread, interceptorOfWaits.captureWaitSite(thread), null);
thread.interceptWait(signal);
// save interrupt state to restore afterwards - new ones only arrive if terminating simulation
boolean wasInterrupted = Thread.interrupted();
signal.awaitThrowUncheckedOnInterrupt();
if (wasInterrupted)
thread.interrupt();
}
MonitorState state = state(monitor);
if (state.heldBy != thread) {
if (state.heldBy != null) {
if (!thread.isIntercepting() && disabled)
return;
else if (!thread.isIntercepting())
throw new AssertionError();
checkForDeadlock(thread, state.heldBy);
InterceptedMonitorWait wait = new InterceptedMonitorWait(UNBOUNDED_WAIT, 0L, state, thread, interceptorOfWaits.captureWaitSite(thread));
wait.suspendedMonitorDepth = 1;
state.waitOn(LOCK, wait);
thread.interceptWait(wait);
synchronized (wait) {
waitingOn.put(thread, monitor);
try {
wait.await();
} catch (InterruptedException e) {
throw new UncheckedInterruptedException(e);
} finally {
waitingOn.remove(thread);
}
}
state.restore(wait);
} else {
state.heldBy = thread;
state.depth = 1;
}
} else {
state.depth++;
}
}
Aggregations