/** * Applies a journal entry commit to the state machine. * * This method is automatically discovered by the Copycat framework. * * @param commit the commit */ public synchronized void applyJournalEntryCommand(Commit<JournalEntryCommand> commit) { JournalEntry entry; try { entry = JournalEntry.parseFrom(commit.command().getSerializedJournalEntry()); } catch (Exception e) { ProcessUtils.fatalError(LOG, e, "Encountered invalid journal entry in commit: {}.", commit); System.exit(-1); throw new IllegalStateException(e); // We should never reach here. } try { applyEntry(entry); } finally { Preconditions.checkState(commit.index() > mLastAppliedCommitIndex); mLastAppliedCommitIndex = commit.index(); commit.close(); } }
@Override public void close(ServerSession session) { if (lock != null && lock.session().id() == session.id()) { lock.close(); lock = queue.poll(); while (lock != null) { Scheduled timer = timers.remove(lock.index()); if (timer != null) timer.cancel(); if (lock.session().state() == ServerSession.State.EXPIRED || lock.session().state() == ServerSession.State.CLOSED) { lock = queue.poll(); } else { lock.session().publish("lock", new LockCommands.LockEvent(lock.operation().id(), lock.index())); break; } } } }
/** * Handles an execute commit. */ public void execute(Commit<GroupCommands.Execute> commit) { try { Commit<GroupCommands.Join> member = members.get(commit.operation().member()); if (member == null) { throw new IllegalArgumentException("unknown member: " + commit.operation().member()); } member.session().publish("execute", commit.operation().callback()); } finally { commit.close(); } }
@Override @SuppressWarnings("unchecked") public Class<T> type() { return (Class<T>) parent.operation().getClass(); }
/** * Handles a get commit. */ public T get(Commit<ValueCommands.Get<T>> commit) { try { return current != null ? value : null; } finally { commit.close(); } }
/** * Returns the message session. */ public ServerSession session() { return commit.session(); }
/** * Handles a subscribe commit. */ public void subscribe(Commit<TaskQueueCommands.Subscribe> commit) { workers.put(commit.session().id(), commit); Commit<TaskQueueCommands.Submit> task = taskQueue.poll(); if (task != null) { processing.put(commit.session().id(), task); commit.session().publish("process", task.operation().task()); } else { workerQueue.add(commit.session()); } }
/** * Returns the message index. */ public long index() { return commit.index(); }
/** * Registers a key change listener. */ public void listen(Commit<MapCommands.KeyListen> commit) { Map<Integer, Map<Long, Commit<MapCommands.KeyListen>>> listeners = this.listeners.computeIfAbsent(commit.command().key(), k -> new HashMap<>()); Map<Long, Commit<MapCommands.KeyListen>> sessions = listeners.computeIfAbsent(commit.command().event(), e -> new HashMap<>()); if (!sessions.containsKey(commit.session().id())) { sessions.put(commit.session().id(), commit); } else { commit.release(); } }
/** * Handles an offer commit. */ public boolean offer(Commit<QueueCommands.Offer> commit) { try { if (queue.offer(commit)) { notify(new ValueEvent<>(Events.ADD, commit.command().value())); return true; } else { commit.release(); return false; } } catch (Exception e) { commit.release(); throw e; } }
@Override public boolean release() { return parent.release(); }