/* * 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.ExclusivePublication; import org.agrona.*; import org.agrona.concurrent.UnsafeBuffer; import java.io.IOException; import java.nio.ByteBuffer; import static org.agrona.BitUtil.CACHE_LINE_LENGTH; class ListRecordingsSession implements ArchiveConductor.Session { private enum State { INIT, ACTIVE, INACTIVE, CLOSED } private final ByteBuffer byteBuffer = BufferUtil.allocateDirectAligned(Catalog.RECORD_LENGTH, CACHE_LINE_LENGTH); private final UnsafeBuffer descriptorBuffer = new UnsafeBuffer(byteBuffer); private final ExclusivePublication reply; private final long fromId; private final long toId; private final Catalog index; private final ControlSessionProxy proxy; private final long correlationId; private long recordingId; private State state = State.INIT; ListRecordingsSession( final long correlationId, final ExclusivePublication reply, final long fromId, final long toId, final Catalog index, final ControlSessionProxy proxy) { this.reply = reply; recordingId = fromId; this.fromId = fromId; this.toId = toId; this.index = index; this.proxy = proxy; this.correlationId = correlationId; } public void abort() { state = State.INACTIVE; } public boolean isDone() { return state == State.CLOSED; } public void remove(final ArchiveConductor conductor) { } public int doWork() { int workDone = 0; switch (state) { case INIT: workDone += init(); break; case ACTIVE: workDone += sendDescriptors(); break; case INACTIVE: workDone += close(); break; } return workDone; } private int close() { state = State.CLOSED; return 1; } private int sendDescriptors() { final RecordingSession session = index.getRecordingSession(recordingId); if (session == null) { byteBuffer.clear(); descriptorBuffer.wrap(byteBuffer); try { if (!index.readDescriptor(recordingId, byteBuffer)) { proxy.sendDescriptorNotFound(reply, recordingId, index.maxRecordingId(), correlationId); state = State.INACTIVE; return 0; } } catch (final IOException ex) { state = State.INACTIVE; LangUtil.rethrowUnchecked(ex); } } else { descriptorBuffer.wrap(session.metaDataBuffer()); } proxy.sendDescriptor(reply, descriptorBuffer, correlationId); if (++recordingId > toId) { state = State.INACTIVE; } return 1; } private int init() { if (fromId > toId) { proxy.sendResponse(reply, "Requested range is reversed (to < from)", correlationId); state = State.INACTIVE; } else if (toId > index.maxRecordingId()) { proxy.sendResponse(reply, "Requested range exceeds available range (to > max)", correlationId); state = State.INACTIVE; } else { state = State.ACTIVE; } return 1; } }