use of com.hazelcast.cp.internal.raft.impl.log.LogEntry in project hazelcast by hazelcast.
the class SemaphoreAdvancedTest method testNewRaftGroupMemberSchedulesTimeoutsWithSnapshot.
@Test
public void testNewRaftGroupMemberSchedulesTimeoutsWithSnapshot() throws ExecutionException, InterruptedException {
semaphore.init(1);
spawn(() -> {
try {
semaphore.tryAcquire(2, 10, MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
CPGroupId groupId = getGroupId();
assertTrueEventually(() -> {
HazelcastInstance leader = leaderInstanceOf(groupId);
SemaphoreService service = getNodeEngineImpl(leader).getService(SemaphoreService.SERVICE_NAME);
SemaphoreRegistry registry = service.getRegistryOrNull(groupId);
assertFalse(registry.getWaitTimeouts().isEmpty());
});
for (int i = 0; i < LOG_ENTRY_COUNT_TO_SNAPSHOT; i++) {
semaphore.acquire();
semaphore.release();
}
assertTrueEventually(() -> {
for (HazelcastInstance instance : instances) {
RaftNodeImpl raftNode = getRaftNode(instance, groupId);
assertNotNull(raftNode);
LogEntry snapshotEntry = getSnapshotEntry(raftNode);
assertTrue(snapshotEntry.index() > 0);
List<RestoreSnapshotOp> ops = (List<RestoreSnapshotOp>) snapshotEntry.operation();
for (RestoreSnapshotOp op : ops) {
if (op.getServiceName().equals(SemaphoreService.SERVICE_NAME)) {
ResourceRegistry registry = (ResourceRegistry) op.getSnapshot();
assertFalse(registry.getWaitTimeouts().isEmpty());
return;
}
}
fail();
}
});
instances[1].shutdown();
HazelcastInstance newInstance = factory.newHazelcastInstance(createConfig(groupSize, groupSize));
newInstance.getCPSubsystem().getCPSubsystemManagementService().promoteToCPMember().toCompletableFuture().get();
assertTrueEventually(() -> {
SemaphoreService service = getNodeEngineImpl(newInstance).getService(SemaphoreService.SERVICE_NAME);
SemaphoreRegistry registry = service.getRegistryOrNull(groupId);
assertNotNull(registry);
assertFalse(registry.getWaitTimeouts().isEmpty());
assertEquals(1, registry.availablePermits(objectName));
});
}
use of com.hazelcast.cp.internal.raft.impl.log.LogEntry in project hazelcast by hazelcast.
the class ReplicateTask method run.
@Override
public void run() {
try {
if (!verifyRaftNodeStatus()) {
return;
}
RaftState state = raftNode.state();
if (state.role() != LEADER) {
resultFuture.completeExceptionally(new NotLeaderException(raftNode.getGroupId(), raftNode.getLocalMember(), state.leader()));
return;
}
if (!raftNode.canReplicateNewEntry(operation)) {
resultFuture.completeExceptionally(new CannotReplicateException(raftNode.getLocalMember()));
return;
}
if (logger.isFineEnabled()) {
logger.fine("Replicating: " + operation + " in term: " + state.term());
}
RaftLog log = state.log();
if (!log.checkAvailableCapacity(1)) {
resultFuture.completeExceptionally(new IllegalStateException("Not enough capacity in RaftLog!"));
return;
}
long newEntryLogIndex = log.lastLogOrSnapshotIndex() + 1;
raftNode.registerFuture(newEntryLogIndex, resultFuture);
log.appendEntries(new LogEntry(state.term(), newEntryLogIndex, operation));
preApplyRaftGroupCmd(newEntryLogIndex, operation);
raftNode.broadcastAppendRequest();
} catch (Throwable t) {
logger.severe(operation + " could not be replicated to leader: " + raftNode.getLocalMember(), t);
RaftEndpoint leader = raftNode.getLeader();
UUID leaderUuid = leader != null ? leader.getUuid() : null;
resultFuture.completeExceptionally(new CPSubsystemException("Internal failure", t, leaderUuid));
}
}
use of com.hazelcast.cp.internal.raft.impl.log.LogEntry in project hazelcast by hazelcast.
the class LeadershipTransferTask method run.
@Override
public void run() {
ILogger logger = raftNode.getLogger(getClass());
RaftState state = raftNode.state();
LeaderState leaderState = state.leaderState();
if (leaderState == null) {
logger.fine("Not retrying leadership transfer since not leader...");
return;
}
LeadershipTransferState leadershipTransferState = state.leadershipTransferState();
checkTrue(leadershipTransferState != null, "No leadership transfer state!");
if (retryCount == maxRetryCount) {
String msg = "Leadership transfer to " + leadershipTransferState.endpoint() + " timed out!";
logger.warning(msg);
state.completeLeadershipTransfer(new IllegalStateException(msg));
return;
}
RaftEndpoint targetEndpoint = leadershipTransferState.endpoint();
if (state.commitIndex() < state.log().lastLogOrSnapshotIndex()) {
logger.warning("Waiting until all appended entries to be committed before transferring leadership to " + targetEndpoint);
reschedule();
return;
}
if (retryCount > 0) {
logger.fine("Retrying leadership transfer to " + leadershipTransferState.endpoint());
} else {
logger.info("Transferring leadership to " + leadershipTransferState.endpoint());
}
leaderState.getFollowerState(targetEndpoint).appendRequestAckReceived();
raftNode.sendAppendRequest(targetEndpoint);
LogEntry entry = state.log().lastLogOrSnapshotEntry();
raftNode.send(new TriggerLeaderElection(raftNode.getLocalMember(), state.term(), entry.term(), entry.index()), targetEndpoint);
reschedule();
}
use of com.hazelcast.cp.internal.raft.impl.log.LogEntry in project hazelcast by hazelcast.
the class AppendRequest method writeData.
@Override
public void writeData(ObjectDataOutput out) throws IOException {
out.writeInt(term);
out.writeObject(leader);
out.writeInt(prevLogTerm);
out.writeLong(prevLogIndex);
out.writeLong(leaderCommitIndex);
out.writeInt(entries.length);
for (LogEntry entry : entries) {
out.writeObject(entry);
}
out.writeLong(queryRound);
}
use of com.hazelcast.cp.internal.raft.impl.log.LogEntry in project hazelcast by hazelcast.
the class RaftNodeImpl method applyRestoredRaftGroupCommands.
private void applyRestoredRaftGroupCommands(SnapshotEntry snapshot) {
// If there is a single Raft group command after the last snapshot,
// here we cannot know if the that command is committed or not so we
// just "pre-apply" that command without committing it.
// If there are multiple Raft group commands, it is definitely known
// that all the command up to the last command are committed,
// but the last command may not be committed.
// This conclusion boils down to the fact that once you append a Raft
// group command, you cannot append a new one before committing it.
RaftLog log = state.log();
LogEntry committedEntry = null;
LogEntry lastAppliedEntry = null;
for (long i = snapshot != null ? snapshot.index() + 1 : 1; i <= log.lastLogOrSnapshotIndex(); i++) {
LogEntry entry = log.getLogEntry(i);
assert entry != null : "index: " + i;
if (entry.operation() instanceof RaftGroupCmd) {
committedEntry = lastAppliedEntry;
lastAppliedEntry = entry;
}
}
if (committedEntry != null) {
state.commitIndex(committedEntry.index());
applyLogEntries();
}
if (lastAppliedEntry != null) {
if (lastAppliedEntry.operation() instanceof UpdateRaftGroupMembersCmd) {
setStatus(UPDATING_GROUP_MEMBER_LIST);
Collection<RaftEndpoint> members = ((UpdateRaftGroupMembersCmd) lastAppliedEntry.operation()).getMembers();
updateGroupMembers(lastAppliedEntry.index(), members);
} else if (lastAppliedEntry.operation() instanceof DestroyRaftGroupCmd) {
setStatus(TERMINATING);
} else {
throw new IllegalStateException("Invalid group command for restore: " + lastAppliedEntry);
}
}
}
Aggregations