@Override public void onNack(ResponseCode responseCode, String errorString, long version) throws ChannelException { throw new ChannelException(responseCode, "Operation channel failed on nack: code=" + responseCode + ", " + errorString + ", " + this + ", " + deltaChannel + ", " + cc, null, Recoverable.NOT_RECOVERABLE, null, null); }
/** * Wraps a channel exception in another providing wave and wavelet id context. */ private ChannelException exceptionWithContext(ChannelException e, WaveletId waveletId) { return new ChannelException(e.getResponseCode(), "Nested ChannelException", e, e.getRecoverable(), waveId, waveletId); }
/** * Handles failure of the view channel or an operation channel. * * @param e The exception that caused the channel to fail. */ private void onChannelException(ChannelException e) { if (e.getRecoverable() != Recoverable.RECOVERABLE) { shutdown(e.getResponseCode(), "Channel Exception", e); } else { reconnect(e); } }
public void testNackTooOldIsRecoverable() throws ChannelException { final long initialVersion = 0; checkedConnectChannel(initialVersion); // Submit delta. final long submitVersion = 0; final byte[] signature = sig(1); final int clientOps = 1; final WaveletDelta clientDelta = buildDelta(submitVersion, clientOps); submitDeltaOnConnectedChannel(clientDelta); // Nack delta immediately with TOO_OLD. try { nackDeltaOnConnectedChannel(submitVersion, signature, "too old", ResponseCode.TOO_OLD); fail("Expected an exception"); } catch (ChannelException e) { assertEquals(Recoverable.RECOVERABLE, e.getRecoverable()); } }
/** * Tests that an open failure results in a proper wavelet failure update. */ public void testOpenFailure() { ProtocolOpenRequest request = ProtocolOpenRequest.newBuilder() .setParticipantId(USER) .setWaveId(ModernIdSerialiser.INSTANCE.serialiseWaveId(WAVE_ID)).build(); counter = 0; rpcImpl.open(controller, request, new RpcCallback<ProtocolWaveletUpdate>() { @Override public void run(ProtocolWaveletUpdate update) { ++counter; } }); frontend.doUpdateFailure(WAVE_ID, FAIL_MESSAGE); assertEquals(0, counter); assertTrue(controller.failed()); assertEquals(new ChannelException(ResponseCode.INTERNAL_ERROR, FAIL_MESSAGE, null, Recoverable.NOT_RECOVERABLE, WAVE_ID, null).serialize(), controller.errorText()); }
} catch (ChannelException e) { triggerOnException(e, update.hasWaveletId() ? update.getWaveletId() : null); terminate("View update raised exception: " + e.toString()); onException(new ChannelException("First update did not contain channel id. Wave id: " + waveId + ", update: " + update, Recoverable.NOT_RECOVERABLE)); return; terminate("View update raised exception: " + e.toString()); if (!update.hasChannelId()) { onException(new ChannelException("First update did not contain channel id. Wave id: " + waveId + ", update: " + update, Recoverable.NOT_RECOVERABLE));
/** * Shuts down this multiplexer permanently after an exception. */ private void shutdown(String message, ChannelException e) { shutdown(e.getResponseCode(), message, e); }
public void testNackTooOldIsRecoverable() throws ChannelException { final long initialVersion = 0; checkedConnectChannel(initialVersion); // Submit delta. final long submitVersion = 0; final byte[] signature = sig(1); final int clientOps = 1; final WaveletDelta clientDelta = buildDelta(submitVersion, clientOps); submitDeltaOnConnectedChannel(clientDelta); // Nack delta immediately with TOO_OLD. try { nackDeltaOnConnectedChannel(submitVersion, signature, "too old", ResponseCode.TOO_OLD); fail("Expected an exception"); } catch (ChannelException e) { assertEquals(Recoverable.RECOVERABLE, e.getRecoverable()); } }
@Override public void onFailure(String reason) throws ChannelException { if (connectionIsCurrent()) { throw new ChannelException("Delta channel: submission failed: " + reason, RECOVERABLE); } }
/** * Tells the listener of an exception on handling server messages. Wave and * wavelet id context is attached to the exception. * * @param e exception causing failure * @param waveletId associated wavelet id (may be null) */ private void triggerOnException(ChannelException e, WaveletId waveletId) { if (openListener != null) { openListener.onException( new ChannelException(e.getResponseCode(), "Exception in view channel, state " + this, e, e.getRecoverable(), waveId, waveletId)); } }
@Override public void onAck(int opsApplied, HashedVersion signature) throws ChannelException { try { cc.onSuccess(opsApplied, signature); } catch (TransformException e) { throw new ChannelException(ResponseCode.INVALID_OPERATION, "Operation channel failed on ack: " + this + ", " + deltaChannel + ", " + cc, e, Recoverable.NOT_RECOVERABLE, null, null); } }
throw new ChannelException(ResponseCode.INTERNAL_ERROR, "Multiplexer received openFinished twice", null, Recoverable.NOT_RECOVERABLE, waveId, null); throw new ChannelException(ResponseCode.NOT_AUTHORIZED, "Server didn't acknowledge known wavelets; perhaps access has been lost: " + missingWavelets, null, Recoverable.NOT_RECOVERABLE, waveId, null);
@Override public void send(WaveletOperation... operations) throws ChannelException { if (state == State.CLOSED) { // TODO(anorth): throw an exception here after fixing clients. logger.error().log("Cannot send to closed operation channel: " + this); } else if (accessibility.isWritable()) { try { cc.onClientOperations(operations); } catch (TransformException e) { throw new ChannelException(ResponseCode.INVALID_OPERATION, "Operation channel failed on send: " + this + ", " + deltaChannel + ", " + cc, e, Recoverable.NOT_RECOVERABLE, null, null); } } else { throw new ChannelException(ResponseCode.NOT_AUTHORIZED, "Attempt to write to inaccessible wavelet", null, Recoverable.NOT_RECOVERABLE, null, null); } }
/** * Processes a subsequent (not first) incoming stream message. Either * parameter may be null. * * @param deltas message deltas * @param lastCommittedVersion committed version information */ private void processUpdateMessage(List<TransformedWaveletDelta> deltas, HashedVersion lastCommittedVersion) throws ChannelException { if (deltas != null) { // Update must contain deltas or lastCommittedVersion, no wave. if (deltas.size() == 0 && (lastCommittedVersion == null)) { throw new ChannelException("Delta channel: invalid non-first wave stream message: count " + (deltas.size()) + "deltas (lastServerVersion: " + lastServerVersion + ")", NOT_RECOVERABLE); } processDeltas(deltas); } processLastCommittedVersion(lastCommittedVersion); flushServerMessages(); }
/** * Queues up a message from the server in startVersion order. * * @param message server message to queue * @return the position in {@code queue} at which the message was inserted * @see #flushServerMessages() */ private int onServerMessage(ServerMessage message) throws ChannelException { if (message.startVersion() < lastServerVersion) { throw new ChannelException("Delta channel: out of sequence server message with version " + message.startVersion() + ": " + message + ", " + this.toString() + "; lastServerVersion: " + lastServerVersion, NOT_RECOVERABLE); } int pos = queue.size(); while (pos > 0 && (queue.get(pos - 1).compareTo(message) > 0)) { pos--; } queue.add(pos, message); return pos; }
throw new ChannelException(ResponseCode.INTERNAL_ERROR, "Multiplexer received openFinished twice", null, Recoverable.NOT_RECOVERABLE, waveId, null); throw new ChannelException(ResponseCode.NOT_AUTHORIZED, "Server didn't acknowledge known wavelets; perhaps access has been lost: " + missingWavelets, null, Recoverable.NOT_RECOVERABLE, waveId, null);
if (connectionIsCurrent()) { if (opsApplied < 0) { throw new ChannelException("Delta channel: invalid submit delta response, opsApplied: " + opsApplied, NOT_RECOVERABLE); throw new ChannelException(ResponseCode.TOO_OLD, "Delta targeted too old version", null, Recoverable.RECOVERABLE, null, null); } else if (responseCode != ResponseCode.OK) { throw new ChannelException( "Delta channel couldn't flush messages after submit response: lastServerVersion " + lastServerVersion + ", queued message version " + queue.get(0).startVersion()
@Override public void onDelta(TransformedWaveletDelta delta) throws ChannelException { try { if (logger.trace().shouldLog()) { logger.trace().log("Received delta: ", delta); } cc.onServerDelta(delta); } catch (TransformException e) { throw new ChannelException(ResponseCode.INVALID_OPERATION, "Operation channel failed on server delta: " + this + ", " + deltaChannel + ", " + cc, e, Recoverable.NOT_RECOVERABLE, null, null); } catch (OperationException e) { throw new ChannelException( e.isSchemaViolation() ? ResponseCode.SCHEMA_VIOLATION : ResponseCode.INVALID_OPERATION, "Operation channel failed on server delta: " + this + ", " + deltaChannel + ", " + cc, e, Recoverable.NOT_RECOVERABLE, null, null); } }
throw new ChannelException("Message missing! Incoming message " + incoming + " expected version " + expectedVersion + ", gap " + gap + ", in-flight delta has " + transmitDelta.size() + " ops", Recoverable.NOT_RECOVERABLE); throw new ChannelException("Message missing! Incoming message " + incoming + " expected version " + expectedVersion + ", gap " + gap + ", no in-flight delta", Recoverable.NOT_RECOVERABLE);
public void testCannotOpenWavesWhenNotLoggedIn() throws Exception { OpenListener listener = mock(OpenListener.class); clientFrontend.openRequest(null, WAVE_ID, IdFilters.ALL_IDS, NO_KNOWN_WAVELETS, listener); verify(listener).onFailure(new ChannelException(ResponseCode.NOT_LOGGED_IN, "Not Logged in", null, Recoverable.NOT_RECOVERABLE, WAVE_ID, null)); CommittedWaveletSnapshot snapshot = provideWavelet(WN1); clientFrontend.waveletUpdate(snapshot.snapshot, DELTAS); Mockito.verifyNoMoreInteractions(listener); }