All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kolibrifx.plovercrest.server.internal.EngineAdapter Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2017, KolibriFX AS. Licensed under the Apache License, version 2.0.
 */

package com.kolibrifx.plovercrest.server.internal;

import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import com.kolibrifx.plovercrest.client.PlovercrestTableNotFound;
import com.kolibrifx.plovercrest.client.RangeQuery;
import com.kolibrifx.plovercrest.client.TableMetadata;
import com.kolibrifx.plovercrest.server.TableInfo;
import com.kolibrifx.plovercrest.server.internal.protocol.ReadContinuationCache;
import com.kolibrifx.plovercrest.server.internal.streams.RangeReadInfo;
import com.kolibrifx.plovercrest.server.internal.streams.RangeStreamUtils;
import com.kolibrifx.plovercrest.server.internal.streams.RuntimeReadContinuation;
import com.kolibrifx.plovercrest.server.streams.ReaderPosition;
import com.kolibrifx.plovercrest.server.streams.Stream;
import com.kolibrifx.plovercrest.server.streams.StreamEngine;
import com.kolibrifx.plovercrest.server.streams.StreamInfo;

/**
 * Helper class for {@link com.kolibrifx.plovercrest.server.internal.protocol.StreamConnection}.
 * Adapts some {@link StreamEngine} functionality to the plovercrest protocol, and provides wrappers
 * that throw exceptions for missing tables/streams.
 * 

* Note: this (and StreamConnection itself) should ideally be split into smaller utility classes. */ public class EngineAdapter { //private static final Logger log = Logger.getLogger(EngineAdapter.class); public interface ChunkedDataHandler extends OverflowHandler { void writeRemainingData(); } /** * Common parameters for the different read functions. */ public static class ReadRequest { private final ReadContinuationCache cache; private final String name; private final int maxCount; private final ByteBuffer targetBuffer; private final ChunkedDataHandler dataHandler; private final AtomicBoolean timedOut; public ReadRequest(final ReadContinuationCache cache, final String name, final int maxCount, final ByteBuffer targetBuffer, final ChunkedDataHandler dataHandler, final AtomicBoolean timedOut) { this.cache = cache; this.name = name; this.maxCount = maxCount; this.targetBuffer = targetBuffer; this.dataHandler = dataHandler; this.timedOut = timedOut; } } private final StreamEngine streamEngine; public EngineAdapter(final StreamEngine streamEngine) { this.streamEngine = streamEngine; } private void putTrailer(final ByteBuffer buffer, final long trailer, final ReaderPosition position, final boolean isAtEndOfRange) { buffer.putLong(trailer); buffer.putInt(ReaderPositionUtils.getTag(position.getPositionType())); buffer.putLong(position.getTimestampOrIndex()); buffer.putInt(position.getSkipCount()); buffer.put((byte) (isAtEndOfRange ? 1 : 0)); } public void read(final ReadRequest request, final RangeQuery rangeQuery) { final Stream stream = openOrThrow(request.name); final ByteBufferStreamObserver observer = new ByteBufferStreamObserver(request.targetBuffer, request.dataHandler); final RuntimeReadContinuation continuation = RangeStreamUtils.readRange(stream, request.maxCount, rangeQuery, observer, request.timedOut); final RangeReadInfo info = continuation.getInfo(); finishRead(request, continuation, info); } public void readContinue(final ReadRequest request, final RangeQuery.RangeType rangeType, final long endTimestampOrIndex, final ReaderPosition readerPosition) { final ByteBufferStreamObserver observer = new ByteBufferStreamObserver(request.targetBuffer, request.dataHandler); final RuntimeReadContinuation continuation = request.cache.tryGetAndRemove(request.name, readerPosition); final RangeReadInfo info; if (continuation != null) { continuation.getObserver().setWrappedObserver(observer); info = RangeStreamUtils.doRead(continuation.getReader(), request.maxCount, continuation.getObserver(), request.timedOut).getInfo(); } else { final Stream stream = openOrThrow(request.name); info = RangeStreamUtils.continueReadRange(stream, request.maxCount, rangeType, endTimestampOrIndex, observer, readerPosition, request.timedOut); } finishRead(request, continuation, info); } private void finishRead(final ReadRequest request, final RuntimeReadContinuation continuation, final RangeReadInfo info) { request.dataHandler.writeRemainingData(); // trailer: last valid timestamp, and the reader index (continuation) // if the end has been reached, the "last valid timestamp". Otherwise, -1. final long trailer = info.isAtEndOfStream() ? info.getLastValidTimestamp() : -1; putTrailer(request.targetBuffer, trailer, info.getPosition(), info.isAtEndOfRange()); if (!info.isAtEndOfRange()) { request.cache.register(request.name, continuation); } } public Stream open(final String name) { return streamEngine.openRaw(name); } public Stream openOrThrow(final String name) { final Stream s = open(name); if (s == null) { throw new PlovercrestTableNotFound("Table not found: " + name); } return s; } public void readStreamInfo(final String tableName, final ByteBuffer buffer) { final Stream t = openOrThrow(tableName); buffer.putLong(t.getFirstTimestamp()); buffer.putLong(t.getLastTimestamp()); buffer.putLong(t.getLastValidTimestamp()); buffer.putLong(t.getDataLengthInBytes()); buffer.putLong(t.getEntryCount()); final byte frozen = (byte) (t.isFrozen() ? 1 : 0); buffer.put(frozen); } public void write(final String tableName, final long timestamp, final ByteBuffer buf) { openOrThrow(tableName).getWriter().write(timestamp, buf); } public void freeze(final String tableName) { openOrThrow(tableName).getWriter().freeze(); } public void unfreeze(final String tableName) { openOrThrow(tableName).getWriter().unfreeze(); } public Collection list() { return streamEngine.list(); } public StreamEngine getStreamEngine() { return streamEngine; } public TableMetadata getMetadata(final String name) { final Stream stream = streamEngine.openRaw(name); if (stream == null) { return null; } else { return stream.getMetadata(); } } public void flush(final String tableName) { openOrThrow(tableName).getWriter().flush(); } public void create(final TableInfo info) { streamEngine.create(info); } public boolean delete(final String tableName) { return streamEngine.delete(tableName); } public boolean rename(final String oldName, final String newName) { return streamEngine.rename(oldName, newName); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy