@Override
 @SuppressWarnings("unchecked")
 public Listener onEvent(String event, Consumer listener) {
   return eventListeners
       .computeIfAbsent(Assert.notNull(event, "event"), e -> new Listeners<>())
       .add(Assert.notNull(listener, "listener"));
 }
Exemple #2
0
 /**
  * @throws IllegalStateException if candidate is not positive or if term, logIndex or logTerm
  *     are negative
  */
 @Override
 public VoteRequest build() {
   super.build();
   Assert.stateNot(request.term < 0, "term must not be negative");
   Assert.stateNot(request.logIndex < 0, "log index must not be negative");
   Assert.stateNot(request.logTerm < 0, "log term must not be negative");
   return request;
 }
 @Override
 public <T extends Operation<U>, U> StateMachineExecutor register(
     Class<T> type, Function<Commit<T>, U> callback) {
   Assert.notNull(type, "type");
   Assert.notNull(callback, "callback");
   operations.put(type, callback);
   return this;
 }
Exemple #4
0
 /**
  * Sets the maximum number of allows entries per segment, returning the builder for method
  * chaining.
  *
  * <p>The maximum entry count dictates when logs should roll over to new segments. As entries
  * are written to a segment of the log, if the entry count in that segment meets the configured
  * maximum entry count, the log will create a new segment and append new entries to that
  * segment.
  *
  * <p>By default, the maximum entries per segment is {@code 1024 * 1024}.
  *
  * @param maxEntriesPerSegment The maximum number of entries allowed per segment.
  * @return The storage builder.
  * @throws IllegalArgumentException If the {@code maxEntriesPerSegment} not greater than the
  *     default max entries per segment
  */
 public Builder withMaxEntriesPerSegment(int maxEntriesPerSegment) {
   Assert.arg(maxEntriesPerSegment > 0, "max entries per segment must be positive");
   Assert.argNot(
       maxEntriesPerSegment > DEFAULT_MAX_ENTRIES_PER_SEGMENT,
       "max entries per segment cannot be greater than " + DEFAULT_MAX_ENTRIES_PER_SEGMENT);
   storage.maxEntriesPerSegment = maxEntriesPerSegment;
   return this;
 }
Exemple #5
0
 private Builder(Address clientAddress, Address serverAddress, Collection<Address> members) {
   this.members = Assert.notNull(members, "members");
   Serializer serializer = new Serializer();
   this.clientAddress = Assert.notNull(clientAddress, "clientAddress");
   this.clientBuilder = CopycatClient.builder(members).withSerializer(serializer.clone());
   this.serverBuilder =
       CopycatServer.builder(clientAddress, serverAddress, members)
           .withSerializer(serializer.clone());
 }
 /** @throws IllegalStateException if status is OK and members is null */
 @Override
 public RegisterResponse build() {
   super.build();
   Assert.stateNot(
       response.status == Status.OK && response.members == null, "members cannot be null");
   Assert.stateNot(
       response.status == Status.OK && response.timeout <= 0, "timeout must be positive");
   return response;
 }
 public ClientSession(
     UUID clientId, Transport transport, Collection<Address> members, Serializer serializer) {
   this.clientId = Assert.notNull(clientId, "clientId");
   this.client = Assert.notNull(transport, "transport").client();
   this.members = new HashSet<>(Assert.notNull(members, "members"));
   this.context =
       new SingleThreadContext(
           "copycat-client-" + clientId.toString(),
           Assert.notNull(serializer, "serializer").clone());
   this.connectMembers = new ArrayList<>(members);
 }
Exemple #8
0
 private ClientSession(
     ClientConnection connection,
     ClientSessionState state,
     ThreadContext context,
     ConnectionStrategy connectionStrategy) {
   this.connection = Assert.notNull(connection, "connection");
   this.state = Assert.notNull(state, "state");
   this.manager = new ClientSessionManager(connection, state, context, connectionStrategy);
   ClientSequencer sequencer = new ClientSequencer(state);
   this.listener = new ClientSessionListener(connection, state, sequencer, context);
   this.submitter = new ClientSessionSubmitter(connection, state, sequencer, context);
 }
 @Override
 public <T extends Operation<Void>> StateMachineExecutor register(
     Class<T> type, Consumer<Commit<T>> callback) {
   Assert.notNull(type, "type");
   Assert.notNull(callback, "callback");
   operations.put(
       type,
       (Function<Commit<T>, Void>)
           commit -> {
             callback.accept(commit);
             return null;
           });
   return this;
 }
Exemple #10
0
  @Override
  public CompletableFuture<Void> listen(Address address, Consumer<Connection> listener) {
    Assert.notNull(address, "address");
    Assert.notNull(listener, "listener");
    if (listening) return CompletableFuture.completedFuture(null);

    ThreadContext context = ThreadContext.currentContextOrThrow();
    synchronized (this) {
      if (listenFuture == null) {
        listenFuture = new CompletableFuture<>();
        listen(address, listener, context);
      }
    }
    return listenFuture;
  }
Exemple #11
0
 /**
  * Sets the maximum segment size in bytes, returning the builder for method chaining.
  *
  * <p>The maximum segment size dictates when logs should roll over to new segments. As entries
  * are written to a segment of the log, once the size of the segment surpasses the configured
  * maximum segment size, the log will create a new segment and append new entries to that
  * segment.
  *
  * <p>By default, the maximum segment size is {@code 1024 * 1024 * 32}.
  *
  * @param maxSegmentSize The maximum segment size in bytes.
  * @return The storage builder.
  * @throws IllegalArgumentException If the {@code maxSegmentSize} is not positive
  */
 public Builder withMaxSegmentSize(int maxSegmentSize) {
   Assert.arg(
       maxSegmentSize > SegmentDescriptor.BYTES,
       "maxSegmentSize must be greater than " + SegmentDescriptor.BYTES);
   storage.maxSegmentSize = maxSegmentSize;
   return this;
 }
Exemple #12
0
 /**
  * Returns a boolean value indicating whether the selector state would be changed by the given
  * members.
  */
 private boolean changed(Address leader, Collection<Address> servers) {
   Assert.notNull(servers, "servers");
   Assert.argNot(servers.isEmpty(), "servers list cannot be empty");
   if (this.leader != null && leader == null) {
     return true;
   } else if (this.leader == null && leader != null) {
     Assert.arg(servers.contains(leader), "leader must be present in servers list");
     return true;
   } else if (this.leader != null && !this.leader.equals(leader)) {
     Assert.arg(servers.contains(leader), "leader must be present in servers list");
     return true;
   } else if (!matches(this.servers, servers)) {
     return true;
   }
   return false;
 }
Exemple #13
0
 /** @throws IllegalStateException if {@code term} is negative */
 @Override
 public VoteResponse build() {
   super.build();
   if (response.status == Response.Status.OK) {
     Assert.stateNot(response.term < 0, "term cannot be negative");
   }
   return response;
 }
Exemple #14
0
 @Override
 public Snapshot complete() {
   Buffer buffer = FileBuffer.allocate(file.file(), SnapshotDescriptor.BYTES);
   try (SnapshotDescriptor descriptor = new SnapshotDescriptor(buffer)) {
     Assert.stateNot(descriptor.locked(), "cannot complete locked snapshot descriptor");
     descriptor.lock();
   }
   return super.complete();
 }
Exemple #15
0
 @Override
 public synchronized SnapshotReader reader() {
   Assert.state(file.file().exists(), "missing snapshot file: %s", file.file());
   Buffer buffer = FileBuffer.allocate(file.file(), SnapshotDescriptor.BYTES);
   SnapshotDescriptor descriptor = new SnapshotDescriptor(buffer);
   int length = buffer.position(SnapshotDescriptor.BYTES).readInt();
   return openReader(
       new SnapshotReader(
           buffer.mark().limit(SnapshotDescriptor.BYTES + Integer.BYTES + length),
           this,
           store.serializer()),
       descriptor);
 }
 @Override
 public Session publish(String event, Object message) {
   Assert.notNull(event, "event");
   context
       .executor()
       .execute(
           () -> {
             Listeners<Object> listeners = eventListeners.get(event);
             if (listeners != null) {
               listeners.accept(message);
             }
           });
   return this;
 }
Exemple #17
0
 SnapshotWriter(Buffer buffer, Snapshot snapshot, Serializer serializer) {
   this.buffer = Assert.notNull(buffer, "buffer");
   this.snapshot = Assert.notNull(snapshot, "snapshot");
   this.serializer = Assert.notNull(serializer, "serializer");
 }
Exemple #18
0
 /**
  * Sets the log directory, returning the builder for method chaining.
  *
  * <p>The log will write segment files into the provided directory. If multiple {@link Storage}
  * objects are located on the same machine, they write logs to different directories.
  *
  * @param directory The log directory.
  * @return The storage builder.
  * @throws NullPointerException If the {@code directory} is {@code null}
  */
 public Builder withDirectory(String directory) {
   return withDirectory(new File(Assert.notNull(directory, "directory")));
 }
 @Override
 public Listener<Session> onClose(Consumer<Session> listener) {
   return closeListeners.add(Assert.notNull(listener, "listener"));
 }
Exemple #20
0
 /**
  * Sets the log directory, returning the builder for method chaining.
  *
  * <p>The log will write segment files into the provided directory. If multiple {@link Storage}
  * objects are located on the same machine, they write logs to different directories.
  *
  * @param directory The log directory.
  * @return The storage builder.
  * @throws NullPointerException If the {@code directory} is {@code null}
  */
 public Builder withDirectory(File directory) {
   storage.directory = Assert.notNull(directory, "directory");
   return this;
 }
 @Override
 public Listener<Session> onOpen(Consumer<Session> listener) {
   return openListeners.add(Assert.notNull(listener, "listener"));
 }
Exemple #22
0
 /** @throws NullPointerException if {@code directory} is null */
 public Storage(String directory) {
   this(new File(Assert.notNull(directory, "directory")));
 }
Exemple #23
0
 public Storage(StorageLevel storageLevel) {
   this.storageLevel = Assert.notNull(storageLevel, "storageLevel");
 }
Exemple #24
0
 /**
  * Sets the percentage of entries in the segment that must be cleaned before a segment can be
  * compacted, returning the builder for method chaining.
  *
  * <p>The compaction threshold is used during {@link
  * io.atomix.copycat.server.storage.compaction.Compaction#MINOR minor compaction} to determine
  * the set of segments to compact. By default, the compaction threshold is {@code 0.5}.
  * Increasing the compaction threshold will increase the number of {@link
  * io.atomix.copycat.server.storage.entry.Entry entries} that must be cleaned from the segment
  * before compaction and thus decrease the likelihood that a segment will be compacted.
  * Conversely, decreasing the compaction threshold will increase the frequency of compaction at
  * the cost of unnecessary I/O.
  *
  * @see io.atomix.copycat.server.storage.compaction.MinorCompactionManager
  * @param threshold The segment compact threshold.
  * @return The storage builder.
  */
 public Builder withCompactionThreshold(double threshold) {
   storage.compactionThreshold =
       Assert.argNot(threshold, threshold <= 0, "threshold must be positive");
   return this;
 }
Exemple #25
0
 /**
  * Sets the major compaction interval, returning the builder for method chaining.
  *
  * <p>The major compaction interval dictates the interval at which the {@link
  * io.atomix.copycat.server.storage.compaction.MajorCompactionManager} should evaluate {@link
  * Segment}s in the log for major compaction. Because of the performance costs of major
  * compaction, it is recommended that the major compaction interval be at least an order of
  * magnitude greater than the minor compaction interval.
  *
  * @see io.atomix.copycat.server.storage.compaction.MajorCompactionManager
  * @see io.atomix.copycat.server.storage.compaction.MajorCompactionTask
  * @param interval The major compaction interval.
  * @return The storage builder.
  */
 public Builder withMajorCompactionInterval(Duration interval) {
   storage.majorCompactionInterval = Assert.notNull(interval, "interval");
   return this;
 }
 /**
  * Sets the request member.
  *
  * @param member The request member.
  * @return The request builder.
  * @throws NullPointerException if {@code member} is null
  */
 public Builder withMember(Address member) {
   request.member = Assert.notNull(member, "member");
   return this;
 }
 public ResourceManagerState(ResourceRegistry registry) {
   this.registry = Assert.notNull(registry, "registry");
 }
Exemple #28
0
 /**
  * Sets the maximum size of snapshot files on disk, returning the builder for method chaining.
  *
  * <p>The maximum snapshot size dictates the size in bytes of a single snapshot file on disk.
  * Reducing the maximum snapshot file size can help ensure that the system is not bogged down
  * with storing and replicating snapshots. By default, snapshots are practically unlimited with
  * a 2GB limit, but in practice they should be fairly small.
  *
  * @param maxSnapshotSize The maximum snapshot size in bytes.
  * @return The storage builder.
  * @throws IllegalArgumentException if the {@code maxSnapshotSize} is not positive or is less
  *     than {@code 64}
  */
 public Builder withMaxSnapshotSize(int maxSnapshotSize) {
   storage.maxSnapshotSize =
       Assert.arg(maxSnapshotSize, maxSnapshotSize >= 64, "max snapshot size must be positive");
   return this;
 }
 /** @throws IllegalStateException if member is null */
 @Override
 public LeaveRequest build() {
   super.build();
   Assert.state(request.member != null, "member cannot be null");
   return request;
 }
Exemple #30
0
 /**
  * Sets the number of log compaction threads, returning the builder for method chaining.
  *
  * <p>The compaction thread count dictates the parallelism with which the log {@link
  * io.atomix.copycat.server.storage.compaction.Compactor} can rewrite segments in the log. By
  * default, the log uses {@code Runtime.getRuntime().availableProcessors() / 2} compaction
  * threads.
  *
  * @param compactionThreads The number of log compaction threads.
  * @return The storage builder.
  * @throws IllegalArgumentException if {@code compactionThreads} is not positive
  */
 public Builder withCompactionThreads(int compactionThreads) {
   storage.compactionThreads =
       Assert.arg(
           compactionThreads, compactionThreads > 0, "compactionThreads must be positive");
   return this;
 }