/** * Closes the partition. */ CompletableFuture<Void> close() { return closeClient() .exceptionally(v -> null) .thenCompose(v -> closeServer()) .exceptionally(v -> null); }
/** * Deletes the server. */ public void delete() { try { Files.walkFileTree(partition.dataDirectory().toPath(), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { log.error("Failed to delete partition: {}", e); } }
public CompletableFuture<Void> join(Collection<MemberId> otherMembers) { log.info("Joining partition {} ({})", partition.id(), partition.name()); server = buildServer(); return server.join(otherMembers).whenComplete((r, e) -> { if (e == null) { log.debug("Successfully joined partition {} ({})", partition.id(), partition.name()); } else { log.warn("Failed to join partition {} ({})", partition.id(), partition.name(), e); } }).thenApply(v -> null); }
@Override public CompletableFuture<RaftPartitionClient> start() { synchronized (RaftPartitionClient.this) { client = newRaftClient(protocol); } return client.connect(partition.members()).whenComplete((r, e) -> { if (e == null) { log.debug("Successfully started client for partition {}", partition.id()); } else { log.warn("Failed to start client for partition {}", partition.id(), e); } }).thenApply(v -> null); }
/** * Opens the partition. */ CompletableFuture<Partition> open(PartitionMetadata metadata, PartitionManagementService managementService) { this.partition = metadata; this.client = createClient(managementService); if (partition.members().contains(managementService.getMembershipService().getLocalMember().id())) { server = createServer(managementService); return server.start() .thenCompose(v -> client.start()) .thenApply(v -> null); } return client.start() .thenApply(v -> this); }
private RaftServer buildServer() { return RaftServer.builder(localMemberId) .withName(partition.name()) .withMembershipService(membershipService) .withProtocol(new RaftServerCommunicator( partition.name(), Serializer.using(RaftNamespaces.RAFT_PROTOCOL), clusterCommunicator)) .withPrimitiveTypes(primitiveTypes) .withElectionTimeout(Duration.ofMillis(ELECTION_TIMEOUT_MILLIS)) .withHeartbeatInterval(Duration.ofMillis(HEARTBEAT_INTERVAL_MILLIS)) .withStorage(RaftStorage.builder() .withPrefix(partition.name()) .withDirectory(partition.dataDirectory()) .withStorageLevel(config.getStorageConfig().getLevel()) .withMaxSegmentSize((int) config.getStorageConfig().getSegmentSize().bytes()) .withMaxEntrySize((int) config.getStorageConfig().getMaxEntrySize().bytes()) .withFlushOnCommit(config.getStorageConfig().isFlushOnCommit()) .withDynamicCompaction(config.getCompactionConfig().isDynamic()) .withFreeDiskBuffer(config.getCompactionConfig().getFreeDiskBuffer()) .withFreeMemoryBuffer(config.getCompactionConfig().getFreeMemoryBuffer()) .withNamespace(RaftNamespaces.RAFT_STORAGE) .build()) .withThreadContextFactory(threadContextFactory) .build(); }
@Override public String toString() { return toStringHelper(this) .add("partitionId", id()) .toString(); } }
private static Collection<RaftPartition> buildPartitions( RaftPartitionGroupConfig config, ThreadContextFactory threadContextFactory) { File partitionsDir = new File(config.getStorageConfig().getDirectory(config.getName()), "partitions"); List<RaftPartition> partitions = new ArrayList<>(config.getPartitions()); for (int i = 0; i < config.getPartitions(); i++) { partitions.add(new RaftPartition( PartitionId.from(config.getName(), i + 1), config, new File(partitionsDir, String.valueOf(i + 1)), threadContextFactory)); } return partitions; }
/** * Updates the partition with the given metadata. */ CompletableFuture<Void> update(PartitionMetadata metadata, PartitionManagementService managementService) { if (server == null && metadata.members().contains(managementService.getMembershipService().getLocalMember().id())) { server = createServer(managementService); return server.join(metadata.members()); } else if (server != null && !metadata.members().contains(managementService.getMembershipService().getLocalMember().id())) { return server.leave().thenRun(() -> server = null); } return CompletableFuture.completedFuture(null); }
/** * Creates a Raft client. */ private RaftPartitionClient createClient(PartitionManagementService managementService) { return new RaftPartitionClient( this, managementService.getMembershipService().getLocalMember().id(), new RaftClientCommunicator( name(), Serializer.using(RaftNamespaces.RAFT_PROTOCOL), managementService.getMessagingService()), threadContextFactory); }
@Override public <S> ProxyClient<S> newProxy(String primitiveName, PrimitiveType primitiveType, Class<S> serviceType, ServiceConfig serviceConfig, PartitionService partitionService) { PartitionGroup partitionGroup = partitionService.getPartitionGroup(this); if (partitionGroup == null) { throw new ConfigurationException("No Raft partition group matching the configured protocol exists"); } Collection<SessionClient> partitions = partitionGroup.getPartitions().stream() .map(partition -> ((RaftPartition) partition).getClient() .sessionBuilder(primitiveName, primitiveType, serviceConfig) .withMinTimeout(config.getMinTimeout()) .withMaxTimeout(config.getMaxTimeout()) .withReadConsistency(config.getReadConsistency()) .withCommunicationStrategy(config.getCommunicationStrategy()) .withRecoveryStrategy(config.getRecoveryStrategy()) .withMaxRetries(config.getMaxRetries()) .withRetryDelay(config.getRetryDelay()) .build()) .collect(Collectors.toList()); return new DefaultProxyClient<>(primitiveName, primitiveType, this, serviceType, partitions, config.getPartitioner()); } }
@Override public CompletableFuture<RaftPartitionServer> start() { log.info("Starting server for partition {}", partition.id()); CompletableFuture<RaftServer> serverOpenFuture; if (partition.members().contains(localMemberId)) { if (server != null && server.isRunning()) { return CompletableFuture.completedFuture(null); } synchronized (this) { try { server = buildServer(); } catch (StorageException e) { return Futures.exceptionalFuture(e); } } serverOpenFuture = server.bootstrap(partition.members()); } else { serverOpenFuture = CompletableFuture.completedFuture(null); } return serverOpenFuture.whenComplete((r, e) -> { if (e == null) { log.debug("Successfully started server for partition {}", partition.id()); } else { log.warn("Failed to start server for partition {}", partition.id(), e); } }).thenApply(v -> this); }
public RaftPartitionGroup(RaftPartitionGroupConfig config) { Logger log = ContextualLoggerFactory.getLogger(DefaultRaftClient.class, LoggerContext.builder(RaftClient.class) .addValue(config.getName()) .build()); this.name = config.getName(); this.config = config; this.partitionSize = config.getPartitionSize(); int threadPoolSize = Math.max(Math.min(Runtime.getRuntime().availableProcessors() * 2, 16), 4); this.threadContextFactory = new BlockingAwareThreadPoolContextFactory( "raft-partition-group-" + name + "-%d", threadPoolSize, log); this.snapshotSubject = "raft-partition-group-" + name + "-snapshot"; buildPartitions(config, threadContextFactory).forEach(p -> { this.partitions.put(p.id(), p); this.sortedPartitionIds.add(p.id()); }); Collections.sort(sortedPartitionIds); }