/* * Copyright 2012 David Tinker * * 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.qdb.buffer; import java.io.Closeable; import java.io.IOException; import java.nio.channels.ReadableByteChannel; import java.util.Date; import java.util.Timer; import java.util.concurrent.Executor; /** * Queue that supports sequential retrieval of old messages by id and timestamp. */ public interface MessageBuffer extends Closeable { /** * Is this buffer open? */ boolean isOpen(); /** * What should the id of the first message appended be? Throws IllegalStateException if the buffer is not * empty. */ void setFirstId(long firstMessageId) throws IOException; /** * Append a message and return its id. * Throws IllegalArgumentException if the payload exceeds {@link #getMaxPayloadSize()}. */ long append(long timestamp, String routingKey, byte[] payload) throws IOException; /** * Append a message and return its id. * Throws IllegalArgumentException if the payload exceeds {@link #getMaxPayloadSize()}. */ long append(long timestamp, String routingKey, ReadableByteChannel payload, int payloadSize) throws IOException; /** * How much space will the message consume in the buffer including header overhead? */ int getMessageSize(String routingKey, int payloadSize); /** * What ID will the next message appended have? */ long getNextId() throws IOException; /** * Create a cursor reading the next message with id greater than or equal to messageId onwards (i.e. messageId * can be 'between' messages). To read the oldest message use 0 as the message ID. To read the newest use * {@link #getNextId()}. If the messageId is before the oldest message the the cursor reads from the * oldest message onwards. The cursor should only be used from one thread at a time i.e. it is not thread safe. */ MessageCursor cursor(long messageId) throws IOException; /** * Create a cursor reading data from timestamp onwards. If timestamp is before the first message then the cursor * reads starting at the first message. If timestamp is past the last message then the cursor will return false * until more messages appear in the buffer. The cursor should only be used from one thread at a time i.e. it is * not thread safe. */ MessageCursor cursorByTimestamp(long timestamp) throws IOException; /** * Set the maximum size of this buffer in bytes. When it is full the oldest messages are deleted to make space. */ void setMaxSize(long bytes) throws IOException; /** * What is the maximum size of this buffer in bytes? */ long getMaxSize(); /** * What is the maximum size of a message payload in bytes? Set to 0 for the default of approximately * {@link #getMaxSize} / 1000. */ void setMaxPayloadSize(int maxPayloadSize); /** * What is the maximum size of a message payload in bytes? */ int getMaxPayloadSize(); /** * Is this buffer empty? */ boolean isEmpty() throws IOException; /** * How much space is this buffer currently consuming in bytes? */ long getSize() throws IOException; /** * How many messages are in the buffer? */ long getMessageCount() throws IOException; /** * What is the timestamp of the oldest message in the buffer? Returns null if the buffer is empty. */ Date getOldestTimestamp() throws IOException; /** * What is the id of the oldest message in the buffer? Returns {@link #setFirstId(long)} if the buffer is * empty or 0 if no firstMessageId has been set. */ long getOldestId() throws IOException; /** * What is the timestamp of the newest message in the buffer? Returns null if the buffer is empty. */ Date getMostRecentTimestamp() throws IOException; /** * When was this buffer instance created? Note that this is when this instance was created in this * virtual machine and has no relationship to when the actual disk files were created. */ long getCreationTime(); /** * Sync all changes to persistent storage. A system crash immediately following this call will not result in * any loss of messages. */ void sync() throws IOException; /** * A {@link #sync()} is done every this many ms if at least one message has been appended since the last * sync. Default is 1000 ms. Set to 0 to disable auto-sync. */ void setAutoSyncInterval(int ms); /** * How often are auto syncs done in ms? * @see #setAutoSyncInterval(int) */ int getAutoSyncInterval(); /** * Set the timer used for auto-sync (see {@link #setAutoSyncInterval(int)}). If none is set then one will be * created when it is first needed i.e. if auto-sync is enabled and a sync is scheduled. */ void setTimer(Timer timer); /** * Get a snapshot of the high level timeline for this buffer. Note that if the buffer is empty null is returned. */ Timeline getTimeline() throws IOException; /** * Get the detailed timeline from approximately messageId onwards in the buffer or null if this is not available * (e.g. the message has been deleted). */ Timeline getTimeline(long messageId) throws IOException; /** * Provide an executor (e.g. thread pool) to do cleanup's asynchronously when the buffer starts a new message * file. If no executor is set then cleanups are done synchronously i.e. on the thread appending the message. */ void setExecutor(Executor executor); }