/*
* Copyright 2014-2017 Real Logic Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.aeron.archiver;
import io.aeron.*;
import org.agrona.*;
class ControlSession implements ArchiveConductor.Session, ControlRequestListener
{
enum State
{
INIT, ACTIVE, INACTIVE, CLOSED
}
private final Image image;
private final ControlSessionProxy proxy;
private final ArchiveConductor conductor;
private final ControlRequestAdapter adapter = new ControlRequestAdapter(this);
private ExclusivePublication reply;
private State state = State.INIT;
ControlSession(final Image image, final ControlSessionProxy clientProxy, final ArchiveConductor conductor)
{
this.image = image;
this.proxy = clientProxy;
this.conductor = conductor;
}
public void abort()
{
state = State.INACTIVE;
}
public boolean isDone()
{
return state == State.CLOSED;
}
public void remove(final ArchiveConductor conductor)
{
}
public int doWork()
{
switch (state)
{
case INIT:
return waitForConnection();
case ACTIVE:
if (image.isClosed() || !reply.isConnected())
{
state = State.INACTIVE;
}
else
{
return image.poll(adapter, 16);
}
break;
case INACTIVE:
CloseHelper.quietClose(reply);
state = State.CLOSED;
break;
case CLOSED:
break;
default:
throw new IllegalStateException();
}
return 0;
}
private int waitForConnection()
{
if (reply == null)
{
try
{
image.poll(adapter, 1);
}
catch (final Exception e)
{
state = State.INACTIVE;
LangUtil.rethrowUnchecked(e);
}
}
else if (reply.isConnected())
{
state = State.ACTIVE;
}
// TODO: timeout
return 0;
}
public void onConnect(final String channel, final int streamId)
{
if (state != State.INIT)
{
throw new IllegalStateException();
}
reply = conductor.clientConnect(channel, streamId);
}
public void onStopRecording(final long correlationId, final long recordingId)
{
if (state != State.ACTIVE)
{
throw new IllegalStateException();
}
try
{
conductor.stopRecording(recordingId);
proxy.sendResponse(reply, null, correlationId);
}
catch (final Exception e)
{
proxy.sendResponse(reply, e.getMessage(), correlationId);
}
}
public void onStartRecording(final long correlationId, final String channel, final int streamId)
{
if (state != State.ACTIVE)
{
throw new IllegalStateException();
}
try
{
conductor.startRecording(channel, streamId);
proxy.sendResponse(reply, null, correlationId);
}
catch (final Exception e)
{
// e.printStackTrace(); TODO: logging?
proxy.sendResponse(reply, e.getMessage(), correlationId);
}
}
public void onListRecordings(final long correlationId, final long fromId, final long toId)
{
if (state != State.ACTIVE)
{
throw new IllegalStateException();
}
conductor.listRecordings(correlationId, reply, fromId, toId);
}
public void onAbortReplay(final long correlationId)
{
if (state != State.ACTIVE)
{
throw new IllegalStateException();
}
conductor.stopReplay(0);
}
public void onStartReplay(
final long correlationId,
final int replayStreamId,
final String replayChannel,
final long recordingId,
final long position,
final long length)
{
if (state != State.ACTIVE)
{
throw new IllegalStateException();
}
conductor.startReplay(
correlationId,
reply,
replayStreamId,
replayChannel,
recordingId,
position,
length);
}
}