From cde23fdf5190d4f48ebf59a27202a4d80367f737 Mon Sep 17 00:00:00 2001 From: Vlad Ilyushchenko Date: Thu, 26 May 2016 01:06:15 +0100 Subject: [PATCH] issue #49: closing listening socket by client cancels query execution on server. --- core/CMakeLists.txt | 1 + core/src/main/c/share/net.c | 6 + core/src/main/c/share/net.h | 8 + .../main/java/com/questdb/BootstrapMain.java | 2 +- .../DisconnectedChannelRuntimeException.java | 44 ++++ core/src/main/java/com/questdb/misc/Net.java | 2 + .../com/questdb/net/http/EpollDispatcher.java | 17 +- .../java/com/questdb/net/http/IOContext.java | 28 ++- .../java/com/questdb/net/http/IOHttpJob.java | 23 +- .../questdb/net/http/KQueueDispatcher.java | 17 +- .../java/com/questdb/net/http/Request.java | 14 +- .../java/com/questdb/net/http/Response.java | 10 +- .../questdb/net/http/ServerConfiguration.java | 10 +- .../net/http/Win32SelectDispatcher.java | 17 +- .../http/handlers/AbstractQueryContext.java | 215 +++++++++++++++++ .../questdb/net/http/handlers/CsvHandler.java | 206 ++++------------ .../net/http/handlers/QueryHandler.java | 221 +++--------------- .../http/handlers/QueryHandlerContext.java | 86 +++++++ .../http/handlers/StaticContentHandler.java | 27 ++- .../com/questdb/ql/CancellationHandler.java | 40 ++++ .../java/com/questdb/ql/RecordSource.java | 2 +- .../main/java/com/questdb/ql/RowSource.java | 2 +- .../questdb/ql/impl/AbstractRowSource.java | 24 +- .../impl/ChannelCheckCancellationHandler.java | 70 ++++++ .../ql/impl/FilteredJournalRecordSource.java | 9 +- .../questdb/ql/impl/FilteredRowSource.java | 9 +- .../com/questdb/ql/impl/JournalSource.java | 4 +- .../ql/impl/NoOpCancellationHandler.java | 49 ++++ .../ql/impl/NoOpJournalRecordSource.java | 9 +- .../com/questdb/ql/impl/TopRecordSource.java | 9 +- .../aggregation/AggregatedRecordSource.java | 10 +- .../impl/aggregation/CountRecordSource.java | 2 +- .../aggregation/ResampledRecordSource.java | 4 +- .../impl/interval/IntervalRecordSource.java | 9 +- .../ql/impl/join/AsOfJoinRecordSource.java | 11 +- .../join/AsOfPartitionedJoinRecordSource.java | 11 +- .../ql/impl/join/CrossJoinRecordSource.java | 11 +- .../ql/impl/join/HashJoinRecordSource.java | 16 +- .../lambda/KvIndexIntLambdaHeadRowSource.java | 4 +- .../lambda/KvIndexStrLambdaHeadRowSource.java | 4 +- .../lambda/KvIndexSymLambdaHeadRowSource.java | 4 +- .../ql/impl/latest/HeapMergingRowSource.java | 15 +- .../latest/KvIndexIntListHeadRowSource.java | 3 +- .../latest/KvIndexStrListHeadRowSource.java | 3 +- .../latest/KvIndexSymAllHeadRowSource.java | 3 +- .../latest/KvIndexSymListHeadRowSource.java | 3 +- .../latest/KvIndexSymLookupRowSource.java | 3 +- .../ql/impl/latest/MergingRowSource.java | 11 +- .../select/SelectedColumnsRecordSource.java | 9 +- .../impl/sort/RBTreeSortedRecordSource.java | 19 +- .../virtual/VirtualColumnRecordSource.java | 9 +- .../com/questdb/ql/parser/QueryCompiler.java | 2 +- .../resources/binaries/osx/libquestdb.dylib | Bin 160340 -> 160668 bytes .../src/main/resources/site/conf/questdb.conf | 8 +- .../handlers/QueryHandlerConsistencyTest.java | 46 +++- .../AsOfPartitionedJoinRecordSourceTest.java | 46 ++-- .../questdb/ql/HashJoinRecordSourceTest.java | 9 +- .../questdb/ql/JoinStringToSymbolTest.java | 3 +- .../com/questdb/ql/MergingRowSourceTest.java | 26 ++- .../questdb/ql/SingleJournalSearchTest.java | 24 +- .../questdb/ql/TailPartitionSourceTest.java | 24 +- .../com/questdb/ql/TopRecordSourceTest.java | 30 +-- .../com/questdb/ql/VirtualColumnTest.java | 26 ++- .../MultiIntervalPartitionSourceTest.java | 23 +- .../com/questdb/ql/impl/NoRowidSource.java | 5 +- .../ql/impl/sort/ComparatorCompilerTest.java | 24 +- .../ql/parser/AbstractOptimiserTest.java | 3 +- .../com/questdb/ql/parser/JoinQueryTest.java | 3 +- .../ql/parser/SingleJournalQueryTest.java | 13 +- 69 files changed, 953 insertions(+), 707 deletions(-) create mode 100644 core/src/main/java/com/questdb/ex/DisconnectedChannelRuntimeException.java create mode 100644 core/src/main/java/com/questdb/net/http/handlers/AbstractQueryContext.java create mode 100644 core/src/main/java/com/questdb/net/http/handlers/QueryHandlerContext.java create mode 100644 core/src/main/java/com/questdb/ql/CancellationHandler.java create mode 100644 core/src/main/java/com/questdb/ql/impl/ChannelCheckCancellationHandler.java create mode 100644 core/src/main/java/com/questdb/ql/impl/NoOpCancellationHandler.java diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index f8ffa132b98f..6f920cedbde8 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.3) project(questdb) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -m64 -Wimplicit-function-declaration") +#set(CMAKE_VERBOSE_MAKEFILE on) # deal with windows slashes in JAVA_HOME if ($ENV{JAVA_HOME}) diff --git a/core/src/main/c/share/net.c b/core/src/main/c/share/net.c index e5a2414fe315..626debfa832c 100644 --- a/core/src/main/c/share/net.c +++ b/core/src/main/c/share/net.c @@ -106,6 +106,12 @@ JNIEXPORT jint JNICALL Java_com_questdb_misc_Net_recv return convert_error(recv((int) fd, (void *) ptr, (size_t) len, 0)); } +JNIEXPORT jboolean JNICALL Java_com_questdb_misc_Net_isDead + (JNIEnv *e, jclass cl, jlong fd) { + int c; + return (jboolean) (recv((int) fd, &c, 1, 0) == 0); +} + JNIEXPORT jint JNICALL Java_com_questdb_misc_Net_configureNonBlocking (JNIEnv *e, jclass cl, jlong fd) { int flags; diff --git a/core/src/main/c/share/net.h b/core/src/main/c/share/net.h index 9bb057061f5e..e0bbcc0bb3b1 100644 --- a/core/src/main/c/share/net.h +++ b/core/src/main/c/share/net.h @@ -77,6 +77,14 @@ JNIEXPORT void JNICALL Java_com_questdb_misc_Net_listen JNIEXPORT jint JNICALL Java_com_questdb_misc_Net_recv (JNIEnv *, jclass, jlong, jlong, jint); +/* + * Class: com_questdb_misc_Net + * Method: recv + * Signature: (JJI)I + */ +JNIEXPORT jboolean JNICALL Java_com_questdb_misc_Net_isDead + (JNIEnv *, jclass, jlong); + /* * Class: com_questdb_misc_Net * Method: send diff --git a/core/src/main/java/com/questdb/BootstrapMain.java b/core/src/main/java/com/questdb/BootstrapMain.java index a3f52940276d..4c01b1074490 100644 --- a/core/src/main/java/com/questdb/BootstrapMain.java +++ b/core/src/main/java/com/questdb/BootstrapMain.java @@ -93,7 +93,7 @@ public static void main(String[] args) throws Exception { JournalFactoryPool pool = new JournalFactoryPool(factory.getConfiguration(), configuration.getJournalPoolSize()); matcher.put("/imp", new ImportHandler(factory)); matcher.put("/js", new QueryHandler(pool, configuration)); - matcher.put("/csv", new CsvHandler(pool)); + matcher.put("/csv", new CsvHandler(pool, configuration)); matcher.put("/chk", new ExistenceCheckHandler(factory)); matcher.setDefaultHandler(new StaticContentHandler(configuration.getHttpPublic(), new MimeTypes(configuration.getMimeTypes()))); diff --git a/core/src/main/java/com/questdb/ex/DisconnectedChannelRuntimeException.java b/core/src/main/java/com/questdb/ex/DisconnectedChannelRuntimeException.java new file mode 100644 index 000000000000..adcb5af52579 --- /dev/null +++ b/core/src/main/java/com/questdb/ex/DisconnectedChannelRuntimeException.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.ex; + +@SuppressWarnings("ThrowableInstanceNeverThrown") +public final class DisconnectedChannelRuntimeException extends RuntimeException { + public final static DisconnectedChannelRuntimeException INSTANCE = new DisconnectedChannelRuntimeException(); + + private DisconnectedChannelRuntimeException() { + } +} diff --git a/core/src/main/java/com/questdb/misc/Net.java b/core/src/main/java/com/questdb/misc/Net.java index fbbd9f1e7e96..36c00443aaba 100644 --- a/core/src/main/java/com/questdb/misc/Net.java +++ b/core/src/main/java/com/questdb/misc/Net.java @@ -72,6 +72,8 @@ public static boolean bind(long fd, CharSequence address, int port) { public native static int getPeerPort(long fd); + public static native boolean isDead(long fd); + public native static void listen(long fd, int backlog); public static native int recv(long fd, long ptr, int len); diff --git a/core/src/main/java/com/questdb/net/http/EpollDispatcher.java b/core/src/main/java/com/questdb/net/http/EpollDispatcher.java index d0e28b1b9fba..8d47d5a5eefe 100644 --- a/core/src/main/java/com/questdb/net/http/EpollDispatcher.java +++ b/core/src/main/java/com/questdb/net/http/EpollDispatcher.java @@ -46,7 +46,6 @@ import com.questdb.mp.*; import com.questdb.net.Epoll; import com.questdb.net.NetworkChannelImpl; -import com.questdb.net.NonBlockingSecureSocketChannel; import com.questdb.std.LongMatrix; import java.io.IOException; @@ -169,21 +168,7 @@ private void addPending(long _fd, long timestamp) { pending.set(r, M_ID, fdid++); NetworkChannelImpl channel = new NetworkChannelImpl(_fd); - pending.set(r, new IOContext( - configuration.getSslConfig().isSecure() ? - new NonBlockingSecureSocketChannel(channel, configuration.getSslConfig()) : - channel, - clock, - configuration.getHttpBufReqHeader(), - configuration.getHttpBufReqContent(), - configuration.getHttpBufReqMultipart(), - configuration.getHttpBufRespHeader(), - configuration.getHttpBufRespContent(), - configuration.getHttpSoRcvSmall(), - configuration.getHttpSoRcvLarge(), - configuration.getHttpSoRetries() - ) - ); + pending.set(r, new IOContext(channel, configuration, clock)); } private void disconnect(IOContext context, DisconnectReason reason) { diff --git a/core/src/main/java/com/questdb/net/http/IOContext.java b/core/src/main/java/com/questdb/net/http/IOContext.java index 58763e09a3fd..c79c399e5f9f 100644 --- a/core/src/main/java/com/questdb/net/http/IOContext.java +++ b/core/src/main/java/com/questdb/net/http/IOContext.java @@ -40,7 +40,7 @@ import com.questdb.iter.clock.Clock; import com.questdb.misc.Misc; import com.questdb.net.NetworkChannel; -import com.questdb.std.FlyweightCharSequence; +import com.questdb.net.NonBlockingSecureSocketChannel; import com.questdb.std.LocalValueMap; import com.questdb.std.Locality; import com.questdb.std.Mutable; @@ -51,24 +51,18 @@ public class IOContext implements Closeable, Mutable, Locality { public final NetworkChannel channel; public final Request request; - public final FlyweightCharSequence ext = new FlyweightCharSequence(); + private final ServerConfiguration serverConfiguration; private final LocalValueMap map = new LocalValueMap(); private final Response response; private final AtomicBoolean open = new AtomicBoolean(true); - public IOContext(NetworkChannel channel, - Clock clock, - int reqHeaderSize, - int reqContentSize, - int reqMultipartHeaderSize, - int respHeaderSize, - int respContentSize, - int soRcvSmall, - int soRcvLarge, - int soRetries) { - this.channel = channel; - this.request = new Request(channel, reqHeaderSize, reqContentSize, reqMultipartHeaderSize, soRcvSmall, soRcvLarge, soRetries); - this.response = new Response(channel, respHeaderSize, respContentSize, clock); + public IOContext(NetworkChannel channel, ServerConfiguration configuration, Clock clock) { + this.channel = configuration.getSslConfig().isSecure() ? + new NonBlockingSecureSocketChannel(channel, configuration.getSslConfig()) : + channel; + this.serverConfiguration = configuration; + this.request = new Request(this.channel, configuration); + this.response = new Response(this.channel, configuration, clock); } public ChunkedResponse chunkedResponse() { @@ -106,6 +100,10 @@ public LocalValueMap getMap() { return map; } + public ServerConfiguration getServerConfiguration() { + return serverConfiguration; + } + public ResponseSink responseSink() { return response.asSink(); } diff --git a/core/src/main/java/com/questdb/net/http/IOHttpJob.java b/core/src/main/java/com/questdb/net/http/IOHttpJob.java index 67b1d881a10c..7592472bc596 100644 --- a/core/src/main/java/com/questdb/net/http/IOHttpJob.java +++ b/core/src/main/java/com/questdb/net/http/IOHttpJob.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.net.http; @@ -158,7 +159,7 @@ private void process(IOContext context, final ChannelStatus status) { LOG.info().$("Headers too large").$(); logAccess(context); result = ChannelStatus.READ; - } catch (MalformedHeaderException | DisconnectedChannelException e) { + } catch (MalformedHeaderException | DisconnectedChannelException | DisconnectedChannelRuntimeException e) { result = ChannelStatus.DISCONNECTED; } catch (EndOfChannelException e) { result = ChannelStatus.EOF; diff --git a/core/src/main/java/com/questdb/net/http/KQueueDispatcher.java b/core/src/main/java/com/questdb/net/http/KQueueDispatcher.java index 11924b28ccf3..b4662c43a842 100644 --- a/core/src/main/java/com/questdb/net/http/KQueueDispatcher.java +++ b/core/src/main/java/com/questdb/net/http/KQueueDispatcher.java @@ -45,7 +45,6 @@ import com.questdb.mp.*; import com.questdb.net.Kqueue; import com.questdb.net.NetworkChannelImpl; -import com.questdb.net.NonBlockingSecureSocketChannel; import com.questdb.std.LongMatrix; import java.io.IOException; @@ -163,21 +162,7 @@ private void addPending(long _fd, long timestamp) { pending.set(r, 0, timestamp); pending.set(r, 1, _fd); NetworkChannelImpl channel = new NetworkChannelImpl(_fd); - pending.set(r, new IOContext( - configuration.getSslConfig().isSecure() ? - new NonBlockingSecureSocketChannel(channel, configuration.getSslConfig()) : - channel, - clock, - configuration.getHttpBufReqHeader(), - configuration.getHttpBufReqContent(), - configuration.getHttpBufReqMultipart(), - configuration.getHttpBufRespHeader(), - configuration.getHttpBufRespContent(), - configuration.getHttpSoRcvSmall(), - configuration.getHttpSoRcvLarge(), - configuration.getHttpSoRetries() - ) - ); + pending.set(r, new IOContext(channel, configuration, clock)); } private void disconnect(IOContext context, DisconnectReason reason) { diff --git a/core/src/main/java/com/questdb/net/http/Request.java b/core/src/main/java/com/questdb/net/http/Request.java index 9bf79f950bbc..22d175e280a2 100644 --- a/core/src/main/java/com/questdb/net/http/Request.java +++ b/core/src/main/java/com/questdb/net/http/Request.java @@ -64,15 +64,15 @@ public class Request implements Closeable, Mutable { private final int soRcvLarge; private final int soRetries; - public Request(NetworkChannel channel, int headerBufferSize, int contentBufferSize, int multipartHeaderBufferSize, int soRcvSmall, int soRcvLarge, int soRetries) { + public Request(NetworkChannel channel, ServerConfiguration configuration) { this.channel = channel; - this.hb = new RequestHeaderBuffer(headerBufferSize, pool); - this.in = ByteBuffer.allocateDirect(Numbers.ceilPow2(contentBufferSize)); + this.hb = new RequestHeaderBuffer(configuration.getHttpBufReqHeader(), pool); + this.in = ByteBuffer.allocateDirect(Numbers.ceilPow2(configuration.getHttpBufReqContent())); this.inAddr = ByteBuffers.getAddress(in); - this.multipartParser = new MultipartParser(multipartHeaderBufferSize, pool); - this.soRcvSmall = soRcvSmall; - this.soRcvLarge = soRcvLarge; - this.soRetries = soRetries; + this.multipartParser = new MultipartParser(configuration.getHttpBufReqMultipart(), pool); + this.soRcvSmall = configuration.getHttpSoRcvSmall(); + this.soRcvLarge = configuration.getHttpSoRcvLarge(); + this.soRetries = configuration.getHttpSoRetries(); } @Override diff --git a/core/src/main/java/com/questdb/net/http/Response.java b/core/src/main/java/com/questdb/net/http/Response.java index 4ab63c341fb5..41b38a195bf0 100644 --- a/core/src/main/java/com/questdb/net/http/Response.java +++ b/core/src/main/java/com/questdb/net/http/Response.java @@ -80,19 +80,19 @@ public class Response implements Closeable, Mutable { private long total = 0; private boolean header = true; - public Response(WritableByteChannel channel, int headerBufferSize, int contentBufferSize, Clock clock) { - if (headerBufferSize <= 0) { + public Response(WritableByteChannel channel, ServerConfiguration configuration, Clock clock) { + if (configuration.getHttpBufRespHeader() <= 0) { throw new IllegalArgumentException("headerBufferSize"); } - if (contentBufferSize <= 0) { + if (configuration.getHttpBufRespContent() <= 0) { throw new IllegalArgumentException("contentBufferSize"); } this.channel = channel; - this.sz = Numbers.ceilPow2(contentBufferSize); + this.sz = Numbers.ceilPow2(configuration.getHttpBufRespContent()); this.out = ByteBuffer.allocateDirect(sz); - this.hb = new ResponseHeaderBuffer(headerBufferSize, clock); + this.hb = new ResponseHeaderBuffer(configuration.getHttpBufRespHeader(), clock); // size is 32bit int, as hex string max 8 bytes this.chunkHeader = ByteBuffer.allocateDirect(8 + 2 * Misc.EOL.length()); this.chunkSink = new DirectUnboundedAnsiSink(ByteBuffers.getAddress(chunkHeader)); diff --git a/core/src/main/java/com/questdb/net/http/ServerConfiguration.java b/core/src/main/java/com/questdb/net/http/ServerConfiguration.java index b0ee01a3d7bb..bb20825a05d3 100644 --- a/core/src/main/java/com/questdb/net/http/ServerConfiguration.java +++ b/core/src/main/java/com/questdb/net/http/ServerConfiguration.java @@ -74,7 +74,7 @@ public class ServerConfiguration { private int dbHashKeyPage = 4 * 1024 * 1024; private int dbHashDataPage = 8 * 1024 * 1024; private int dbHashRowPage = 1024 * 1024; - + private int dbCyclesBeforeCancel = 1024 * 1024; private File dbPath = new File("db"); private File mimeTypes = new File("conf/mime.types"); private File httpPublic = new File("public"); @@ -201,6 +201,10 @@ public ServerConfiguration(File conf) throws Exception { this.dbHashRowPage = n; } + if ((n = parseInt(props, "db.cycles.before.cancel")) > -1) { + this.dbCyclesBeforeCancel = Numbers.ceilPow2(n); + } + if ((s = props.getProperty("mime.types")) != null) { this.mimeTypes = normalize(root, new File(s)); } else { @@ -276,6 +280,10 @@ public int getDbAsOfRowPage() { return dbAsOfRowPage; } + public int getDbCyclesBeforeCancel() { + return dbCyclesBeforeCancel; + } + public int getDbHashDataPage() { return dbHashDataPage; } diff --git a/core/src/main/java/com/questdb/net/http/Win32SelectDispatcher.java b/core/src/main/java/com/questdb/net/http/Win32SelectDispatcher.java index 57db0e33f1bd..ecf33be05e4c 100644 --- a/core/src/main/java/com/questdb/net/http/Win32SelectDispatcher.java +++ b/core/src/main/java/com/questdb/net/http/Win32SelectDispatcher.java @@ -42,7 +42,6 @@ import com.questdb.misc.*; import com.questdb.mp.*; import com.questdb.net.NetworkChannelImpl; -import com.questdb.net.NonBlockingSecureSocketChannel; import com.questdb.std.LongIntHashMap; import com.questdb.std.LongMatrix; @@ -185,21 +184,7 @@ private void addPending(long _fd, long timestamp) { pending.set(r, M_FD, _fd); pending.set(r, M_OPERATION, ChannelStatus.READ.ordinal()); NetworkChannelImpl channel = new NetworkChannelImpl(_fd); - pending.set(r, new IOContext( - configuration.getSslConfig().isSecure() ? - new NonBlockingSecureSocketChannel(channel, configuration.getSslConfig()) : - channel, - clock, - configuration.getHttpBufReqHeader(), - configuration.getHttpBufReqContent(), - configuration.getHttpBufReqMultipart(), - configuration.getHttpBufRespHeader(), - configuration.getHttpBufRespContent(), - configuration.getHttpSoRcvSmall(), - configuration.getHttpSoRcvLarge(), - configuration.getHttpSoRetries() - ) - ); + pending.set(r, new IOContext(channel, configuration, clock)); } private void disconnect(IOContext context, DisconnectReason reason) { diff --git a/core/src/main/java/com/questdb/net/http/handlers/AbstractQueryContext.java b/core/src/main/java/com/questdb/net/http/handlers/AbstractQueryContext.java new file mode 100644 index 000000000000..37b12b681ad3 --- /dev/null +++ b/core/src/main/java/com/questdb/net/http/handlers/AbstractQueryContext.java @@ -0,0 +1,215 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.net.http.handlers; + +import com.questdb.ex.*; +import com.questdb.factory.JournalFactoryPool; +import com.questdb.factory.JournalReaderFactory; +import com.questdb.factory.configuration.RecordMetadata; +import com.questdb.log.Log; +import com.questdb.log.LogFactory; +import com.questdb.log.LogRecord; +import com.questdb.misc.Chars; +import com.questdb.misc.Misc; +import com.questdb.misc.Numbers; +import com.questdb.net.http.ChunkedResponse; +import com.questdb.net.http.Request; +import com.questdb.net.http.ServerConfiguration; +import com.questdb.ql.Record; +import com.questdb.ql.RecordCursor; +import com.questdb.ql.RecordSource; +import com.questdb.ql.impl.ChannelCheckCancellationHandler; +import com.questdb.ql.parser.QueryCompiler; +import com.questdb.ql.parser.QueryError; +import com.questdb.std.AssociativeCache; +import com.questdb.std.Mutable; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicLong; + + +public abstract class AbstractQueryContext implements Mutable, Closeable { + static final ThreadLocal COMPILER = new ThreadLocal<>(); + static final ThreadLocal> CACHE = new ThreadLocal<>(); + static final Log LOG = LogFactory.getLog(AbstractQueryContext.class); + final ChannelCheckCancellationHandler cancellationHandler; + final long fd; + RecordSource recordSource; + CharSequence query; + RecordMetadata metadata; + RecordCursor cursor; + long count; + long skip; + long stop; + Record record; + JournalReaderFactory factory; + QueryState state = QueryState.PREFIX; + int columnIndex; + + public AbstractQueryContext(long fd, int cyclesBeforeCancel) { + this.cancellationHandler = new ChannelCheckCancellationHandler(fd, cyclesBeforeCancel); + this.fd = fd; + } + + @Override + public void clear() { + debug().$("Cleaning context").$(); + metadata = null; + cursor = null; + record = null; + debug().$("Closing journal factory").$(); + factory = Misc.free(factory); + if (recordSource != null) { + CACHE.get().put(query.toString(), recordSource); + recordSource = null; + } + query = null; + state = QueryState.PREFIX; + columnIndex = 0; + } + + @Override + public void close() throws IOException { + debug().$("Closing context").$(); + clear(); + } + + public void compileQuery(ChunkedResponse r, JournalFactoryPool pool, AtomicLong misses, AtomicLong hits) throws IOException { + try { + // Prepare Context. + this.factory = pool.get(); + recordSource = CACHE.get().poll(query); + if (recordSource == null) { + recordSource = COMPILER.get().compileSource(factory, query); + misses.incrementAndGet(); + } else { + recordSource.reset(); + hits.incrementAndGet(); + } + cursor = recordSource.prepareCursor(factory, cancellationHandler); + metadata = cursor.getMetadata(); + header(r, 200); + } catch (ParserException e) { + info().$("Parser error executing query ").$(query).$(": at (").$(QueryError.getPosition()).$(") ").$(QueryError.getMessage()).$(); + sendException(r, QueryError.getPosition(), QueryError.getMessage(), 400); + } catch (JournalException e) { + error().$("Server error executing query ").$(query).$(e).$(); + sendException(r, 0, e.getMessage(), 500); + } catch (InterruptedException e) { + error().$("Error executing query. Server is shutting down. Query: ").$(query).$(e).$(); + sendException(r, 0, "Server is shutting down.", 500); + } + } + + public boolean parseUrl(ChunkedResponse r, Request request) throws DisconnectedChannelException, SlowWritableChannelException { + // Query text. + CharSequence query = request.getUrlParam("query"); + if (query == null || query.length() == 0) { + info().$("Empty query request received. Sending empty reply.").$(); + sendException(r, 0, "", 200); + return false; + } + + // Url Params. + long skip = 0; + long stop = Long.MAX_VALUE; + + CharSequence limit = request.getUrlParam("limit"); + if (limit != null) { + int sepPos = Chars.indexOf(limit, ','); + try { + if (sepPos > 0) { + skip = Numbers.parseLong(limit, 0, sepPos); + if (sepPos + 1 < limit.length()) { + stop = Numbers.parseLong(limit, sepPos + 1, limit.length()); + } + } else { + stop = Numbers.parseLong(limit); + } + } catch (NumericException ex) { + // Skip or stop will have default value. + } + } + if (stop < 0) { + stop = 0; + } + + if (skip < 0) { + skip = 0; + } + + this.query = query; + this.skip = skip; + this.count = 0L; + this.stop = stop; + + info().$("Query: ").$(query). + $(", skip: ").$(skip). + $(", stop: ").$(stop).$(); + + return true; + } + + static void setupThread(ServerConfiguration configuration) { + if (COMPILER.get() == null) { + COMPILER.set(new QueryCompiler(configuration)); + } + if (CACHE.get() == null) { + CACHE.set(new AssociativeCache(8, 128)); + } + } + + LogRecord debug() { + return LOG.debug().$('[').$(fd).$("] "); + } + + LogRecord error() { + return LOG.error().$('[').$(fd).$("] "); + } + + protected abstract void header(ChunkedResponse r, int code) throws DisconnectedChannelException, SlowWritableChannelException; + + LogRecord info() { + return LOG.info().$('[').$(fd).$("] "); + } + + protected abstract void sendException(ChunkedResponse r, int position, CharSequence message, int code) throws DisconnectedChannelException, SlowWritableChannelException; + + enum QueryState { + PREFIX, METADATA, META_SUFFIX, RECORD_START, RECORD_COLUMNS, RECORD_SUFFIX, DATA_SUFFIX + } +} diff --git a/core/src/main/java/com/questdb/net/http/handlers/CsvHandler.java b/core/src/main/java/com/questdb/net/http/handlers/CsvHandler.java index d82335a235be..0ab1d4f68660 100644 --- a/core/src/main/java/com/questdb/net/http/handlers/CsvHandler.java +++ b/core/src/main/java/com/questdb/net/http/handlers/CsvHandler.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,28 +30,23 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.net.http.handlers; -import com.questdb.ex.*; -import com.questdb.factory.JournalCachingFactory; +import com.questdb.ex.DisconnectedChannelException; +import com.questdb.ex.ResponseContentBufferTooSmallException; +import com.questdb.ex.SlowWritableChannelException; import com.questdb.factory.JournalFactoryPool; import com.questdb.factory.configuration.RecordColumnMetadata; -import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.log.Log; -import com.questdb.log.LogFactory; -import com.questdb.log.LogRecord; -import com.questdb.misc.Chars; import com.questdb.misc.Misc; import com.questdb.misc.Numbers; import com.questdb.net.http.ChunkedResponse; import com.questdb.net.http.ContextHandler; import com.questdb.net.http.IOContext; +import com.questdb.net.http.ServerConfiguration; import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.parser.QueryError; import com.questdb.std.CharSink; import com.questdb.std.LocalValue; import com.questdb.std.Mutable; @@ -61,76 +56,30 @@ import java.io.IOException; import java.util.concurrent.atomic.AtomicLong; -import static com.questdb.net.http.handlers.QueryHandler.CACHE; -import static com.questdb.net.http.handlers.QueryHandler.COMPILER; - public class CsvHandler implements ContextHandler { private final JournalFactoryPool factoryPool; private final LocalValue localContext = new LocalValue<>(); private final AtomicLong cacheHits = new AtomicLong(); private final AtomicLong cacheMisses = new AtomicLong(); + private final ServerConfiguration configuration; + - public CsvHandler(JournalFactoryPool factoryPool) { + public CsvHandler(JournalFactoryPool factoryPool, ServerConfiguration configuration) { this.factoryPool = factoryPool; + this.configuration = configuration; } @Override public void handle(IOContext context) throws IOException { ExportHandlerContext ctx = localContext.get(context); if (ctx == null) { - localContext.set(context, ctx = new ExportHandlerContext()); + localContext.set(context, ctx = new ExportHandlerContext(context.channel.getFd(), context.getServerConfiguration().getDbCyclesBeforeCancel())); } - ctx.fd = context.channel.getFd(); - - // Query text. ChunkedResponse r = context.chunkedResponse(); - CharSequence query = context.request.getUrlParam("query"); - if (query == null || query.length() == 0) { - ctx.info().$("Empty query request received. Sending empty reply.").$(); - header(r, 200); - r.done(); - return; - } - - // Url Params. - long skip = 0; - long stop = Long.MAX_VALUE; - - CharSequence limit = context.request.getUrlParam("limit"); - if (limit != null) { - int sepPos = Chars.indexOf(limit, ','); - try { - if (sepPos > 0) { - skip = Numbers.parseLong(limit, 0, sepPos); - if (sepPos + 1 < limit.length()) { - stop = Numbers.parseLong(limit, sepPos + 1, limit.length()); - } - } else { - stop = Numbers.parseLong(limit); - } - } catch (NumericException ex) { - // Skip or stop will have default value. - } - } - if (stop < 0) { - stop = 0; - } - - if (skip < 0) { - skip = 0; + if (ctx.parseUrl(r, context.request)) { + ctx.compileQuery(r, factoryPool, cacheMisses, cacheHits); + resume(context); } - - ctx.query = query; - ctx.skip = skip; - ctx.count = 0L; - ctx.stop = stop; - - ctx.info().$("Query: ").$(query). - $(", skip: ").$(skip). - $(", stop: ").$(stop).$(); - - executeQuery(r, ctx); - resume(context); } @SuppressWarnings("ConstantConditions") @@ -160,7 +109,7 @@ public void resume(IOContext context) throws IOException { r.putQuoted(column.getName()); } r.put(Misc.EOL); - ctx.state = QueryState.RECORD_START; + ctx.state = AbstractQueryContext.QueryState.RECORD_START; // fall through case RECORD_START: if (ctx.record == null) { @@ -174,18 +123,18 @@ public void resume(IOContext context) throws IOException { break; } } else { - ctx.state = QueryState.DATA_SUFFIX; + ctx.state = AbstractQueryContext.QueryState.DATA_SUFFIX; break SWITCH; } } } if (ctx.count > ctx.stop) { - ctx.state = QueryState.DATA_SUFFIX; + ctx.state = AbstractQueryContext.QueryState.DATA_SUFFIX; break; } - ctx.state = QueryState.RECORD_COLUMNS; + ctx.state = AbstractQueryContext.QueryState.RECORD_COLUMNS; ctx.columnIndex = 0; // fall through case RECORD_COLUMNS: @@ -202,7 +151,7 @@ public void resume(IOContext context) throws IOException { r.bookmark(); r.put(Misc.EOL); ctx.record = null; - ctx.state = QueryState.RECORD_START; + ctx.state = AbstractQueryContext.QueryState.RECORD_START; break; case DATA_SUFFIX: sendDone(r, ctx); @@ -227,14 +176,9 @@ public void resume(IOContext context) throws IOException { @Override public void setupThread() { + AbstractQueryContext.setupThread(configuration); } - private static void sendException(ChunkedResponse r, int position, CharSequence message, int status) throws DisconnectedChannelException, SlowWritableChannelException { - header(r, status); - r.put("Error at(").put(position).put("): ").put(message).put(Misc.EOL); - r.sendChunk(); - r.done(); - } private static void putValue(CharSink sink, ColumnType type, Record rec, int col) { switch (type) { @@ -297,43 +241,6 @@ private static void putValue(CharSink sink, ColumnType type, Record rec, int col } } - private static void header(ChunkedResponse r, int code) throws DisconnectedChannelException, SlowWritableChannelException { - r.status(code, "text/csv; charset=utf-8"); - r.headers().put("Content-Disposition: attachment; filename=\"questdb-query-").put(System.currentTimeMillis()).put(".csv\"").put(Misc.EOL); - r.sendHeader(); - } - - private void executeQuery(ChunkedResponse r, ExportHandlerContext ctx) throws IOException { - try { - // Prepare Context. - JournalCachingFactory factory = factoryPool.get(); - ctx.factory = factory; - ctx.recordSource = CACHE.get().poll(ctx.query); - if (ctx.recordSource == null) { - ctx.recordSource = COMPILER.get().compileSource(factory, ctx.query); - cacheMisses.incrementAndGet(); - } else { - ctx.recordSource.reset(); - cacheHits.incrementAndGet(); - } - ctx.cursor = ctx.recordSource.prepareCursor(factory); - ctx.metadata = ctx.cursor.getMetadata(); - ctx.state = QueryState.METADATA; - ctx.columnIndex = 0; - - header(r, 200); - } catch (ParserException e) { - ctx.info().$("Parser error executing query ").$(ctx.query).$(": at (").$(QueryError.getPosition()).$(") ").$(QueryError.getMessage()).$(); - sendException(r, QueryError.getPosition(), QueryError.getMessage(), 400); - } catch (JournalException e) { - ctx.error().$("Server error executing query ").$(ctx.query).$(e).$(); - sendException(r, 0, e.getMessage(), 500); - } catch (InterruptedException e) { - ctx.error().$("Error executing query. Server is shutting down. Query: ").$(ctx.query).$(e).$(); - sendException(r, 0, "Server is shutting down.", 500); - } - } - private void sendDone(ChunkedResponse r, ExportHandlerContext ctx) throws DisconnectedChannelException, SlowWritableChannelException { if (ctx.count > -1) { ctx.count = -1; @@ -342,38 +249,15 @@ private void sendDone(ChunkedResponse r, ExportHandlerContext ctx) throws Discon r.done(); } - private enum QueryState { - METADATA, RECORD_START, RECORD_COLUMNS, DATA_SUFFIX - } - - private static class ExportHandlerContext implements Mutable, Closeable { - private static final Log LOG = LogFactory.getLog(ExportHandlerContext.class); - private RecordSource recordSource; - private CharSequence query; - private RecordMetadata metadata; - private RecordCursor cursor; - private long count; - private long skip; - private long stop; - private Record record; - private JournalCachingFactory factory; - private long fd; - private QueryState state = QueryState.METADATA; - private int columnIndex; + private static class ExportHandlerContext extends AbstractQueryContext implements Mutable, Closeable { + public ExportHandlerContext(long fd, int cyclesBeforeCancel) { + super(fd, cyclesBeforeCancel); + state = QueryState.METADATA; + } @Override public void clear() { - debug().$("Cleaning context").$(); - metadata = null; - cursor = null; - record = null; - debug().$("Closing journal factory").$(); - factory = Misc.free(factory); - if (recordSource != null) { - CACHE.get().put(query.toString(), recordSource); - recordSource = null; - } - query = null; + super.clear(); state = QueryState.METADATA; } @@ -383,16 +267,20 @@ public void close() throws IOException { clear(); } - private LogRecord debug() { - return LOG.debug().$('[').$(fd).$("] "); - } - - private LogRecord error() { - return LOG.error().$('[').$(fd).$("] "); + @Override + protected void header(ChunkedResponse r, int code) throws DisconnectedChannelException, SlowWritableChannelException { + state = QueryState.METADATA; + r.status(code, "text/csv; charset=utf-8"); + r.headers().put("Content-Disposition: attachment; filename=\"questdb-query-").put(System.currentTimeMillis()).put(".csv\"").put(Misc.EOL); + r.sendHeader(); } - private LogRecord info() { - return LOG.info().$('[').$(fd).$("] "); + @Override + protected void sendException(ChunkedResponse r, int position, CharSequence message, int status) throws DisconnectedChannelException, SlowWritableChannelException { + header(r, status); + r.put("Error at(").put(position).put("): ").put(message).put(Misc.EOL); + r.sendChunk(); + r.done(); } } } diff --git a/core/src/main/java/com/questdb/net/http/handlers/QueryHandler.java b/core/src/main/java/com/questdb/net/http/handlers/QueryHandler.java index b55c14bc8d50..d0f7640aaa59 100644 --- a/core/src/main/java/com/questdb/net/http/handlers/QueryHandler.java +++ b/core/src/main/java/com/questdb/net/http/handlers/QueryHandler.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,43 +30,30 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.net.http.handlers; -import com.questdb.ex.*; -import com.questdb.factory.JournalCachingFactory; +import com.questdb.ex.DisconnectedChannelException; +import com.questdb.ex.ResponseContentBufferTooSmallException; +import com.questdb.ex.SlowWritableChannelException; import com.questdb.factory.JournalFactoryPool; import com.questdb.factory.configuration.RecordColumnMetadata; -import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.log.Log; -import com.questdb.log.LogFactory; -import com.questdb.log.LogRecord; -import com.questdb.misc.Chars; -import com.questdb.misc.Misc; import com.questdb.misc.Numbers; import com.questdb.net.http.ChunkedResponse; import com.questdb.net.http.ContextHandler; import com.questdb.net.http.IOContext; import com.questdb.net.http.ServerConfiguration; import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.parser.QueryCompiler; -import com.questdb.ql.parser.QueryError; -import com.questdb.std.AssociativeCache; import com.questdb.std.CharSink; import com.questdb.std.LocalValue; -import com.questdb.std.Mutable; import com.questdb.store.ColumnType; -import java.io.Closeable; import java.io.IOException; import java.util.concurrent.atomic.AtomicLong; public class QueryHandler implements ContextHandler { - public static final ThreadLocal COMPILER = new ThreadLocal<>(); - public static final ThreadLocal> CACHE = new ThreadLocal<>(); private final JournalFactoryPool factoryPool; private final LocalValue localContext = new LocalValue<>(); @@ -83,64 +70,14 @@ public QueryHandler(JournalFactoryPool factoryPool, ServerConfiguration configur public void handle(IOContext context) throws IOException { QueryHandlerContext ctx = localContext.get(context); if (ctx == null) { - localContext.set(context, ctx = new QueryHandlerContext()); + localContext.set(context, + ctx = new QueryHandlerContext(context.channel.getFd(), context.getServerConfiguration().getDbCyclesBeforeCancel())); } - ctx.fd = context.channel.getFd(); - - // Query text. ChunkedResponse r = context.chunkedResponse(); - CharSequence query = context.request.getUrlParam("query"); - if (query == null || query.length() == 0) { - ctx.info().$("Empty query request received. Sending empty reply.").$(); - r.status(200, "application/json; charset=utf-8"); - r.sendHeader(); - r.put('{').putQuoted("query").put(':').putQuoted("").put('}'); - r.sendChunk(); - r.done(); - return; - } - - // Url Params. - long skip = 0; - long stop = Long.MAX_VALUE; - - CharSequence limit = context.request.getUrlParam("limit"); - if (limit != null) { - int sepPos = Chars.indexOf(limit, ','); - try { - if (sepPos > 0) { - skip = Numbers.parseLong(limit, 0, sepPos); - if (sepPos + 1 < limit.length()) { - stop = Numbers.parseLong(limit, sepPos + 1, limit.length()); - } - } else { - stop = Numbers.parseLong(limit); - } - } catch (NumericException ex) { - // Skip or stop will have default value. - } + if (ctx.parseUrl(r, context.request)) { + ctx.compileQuery(r, factoryPool, cacheMisses, cacheHits); + resume(context); } - if (stop < 0) { - stop = 0; - } - - if (skip < 0) { - skip = 0; - } - - ctx.noMeta = Chars.equalsNc("true", context.request.getUrlParam("nm")); - ctx.query = query; - ctx.skip = skip; - ctx.count = 0L; - ctx.stop = stop; - ctx.fetchAll = Chars.equalsNc("true", context.request.getUrlParam("count")); - - ctx.info().$("Query: ").$(query). - $(", skip: ").$(skip). - $(", stop: ").$(stop).$(); - - executeQuery(r, ctx); - resume(context); } @SuppressWarnings("ConstantConditions") @@ -162,13 +99,13 @@ public void resume(IOContext context) throws IOException { case PREFIX: if (ctx.noMeta) { r.put("{\"result\":["); - ctx.state = QueryState.RECORD_START; + ctx.state = QueryHandlerContext.QueryState.RECORD_START; break; } r.bookmark(); r.put('{').putQuoted("query").put(':').putUtf8EscapedAndQuoted(ctx.query); r.put(',').putQuoted("columns").put(':').put('['); - ctx.state = QueryState.METADATA; + ctx.state = QueryHandlerContext.QueryState.METADATA; ctx.columnIndex = 0; // fall through case METADATA: @@ -186,12 +123,12 @@ public void resume(IOContext context) throws IOException { putQuoted("type").put(':').putQuoted(column.getType().name()); r.put('}'); } - ctx.state = QueryState.META_SUFFIX; + ctx.state = QueryHandlerContext.QueryState.META_SUFFIX; // fall through case META_SUFFIX: r.bookmark(); r.put("],\"result\":["); - ctx.state = QueryState.RECORD_START; + ctx.state = QueryHandlerContext.QueryState.RECORD_START; // fall through case RECORD_START: @@ -210,14 +147,14 @@ public void resume(IOContext context) throws IOException { break; } } else { - ctx.state = QueryState.DATA_SUFFIX; + ctx.state = QueryHandlerContext.QueryState.DATA_SUFFIX; break SWITCH; } } } if (ctx.count > ctx.stop) { - ctx.state = QueryState.DATA_SUFFIX; + ctx.state = QueryHandlerContext.QueryState.DATA_SUFFIX; break; } @@ -227,7 +164,7 @@ public void resume(IOContext context) throws IOException { } r.put('['); - ctx.state = QueryState.RECORD_COLUMNS; + ctx.state = QueryHandlerContext.QueryState.RECORD_COLUMNS; ctx.columnIndex = 0; // fall through case RECORD_COLUMNS: @@ -241,14 +178,14 @@ public void resume(IOContext context) throws IOException { putValue(r, m.getType(), ctx.record, ctx.columnIndex); } - ctx.state = QueryState.RECORD_SUFFIX; + ctx.state = QueryHandlerContext.QueryState.RECORD_SUFFIX; // fall through case RECORD_SUFFIX: r.bookmark(); r.put(']'); ctx.record = null; - ctx.state = QueryState.RECORD_START; + ctx.state = QueryHandlerContext.QueryState.RECORD_START; break; case DATA_SUFFIX: sendDone(r, ctx); @@ -273,20 +210,7 @@ public void resume(IOContext context) throws IOException { @Override public void setupThread() { - COMPILER.set(new QueryCompiler(configuration)); - CACHE.set(new AssociativeCache(8, 128)); - } - - private static void sendException(ChunkedResponse r, CharSequence query, int position, CharSequence message, int status) throws DisconnectedChannelException, SlowWritableChannelException { - r.status(status, "application/json; charset=utf-8"); - r.sendHeader(); - r.put('{'). - putQuoted("query").put(':').putUtf8EscapedAndQuoted(query).put(','). - putQuoted("error").put(':').putQuoted(message).put(','). - putQuoted("position").put(':').put(position); - r.put('}'); - r.sendChunk(); - r.done(); + AbstractQueryContext.setupThread(configuration); } private static void putValue(CharSink sink, ColumnType type, Record rec, int col) { @@ -353,37 +277,6 @@ private static void putStringOrNull(CharSink r, CharSequence str) { } } - private void executeQuery(ChunkedResponse r, QueryHandlerContext ctx) throws IOException { - try { - // Prepare Context. - JournalCachingFactory factory = factoryPool.get(); - ctx.factory = factory; - ctx.recordSource = CACHE.get().poll(ctx.query); - if (ctx.recordSource == null) { - ctx.recordSource = COMPILER.get().compileSource(factory, ctx.query); - cacheMisses.incrementAndGet(); - } else { - ctx.recordSource.reset(); - cacheHits.incrementAndGet(); - } - ctx.cursor = ctx.recordSource.prepareCursor(factory); - ctx.metadata = ctx.cursor.getMetadata(); - ctx.state = QueryState.PREFIX; - - r.status(200, "application/json; charset=utf-8"); - r.sendHeader(); - } catch (ParserException e) { - ctx.info().$("Parser error executing query ").$(ctx.query).$(": at (").$(QueryError.getPosition()).$(") ").$(QueryError.getMessage()).$(); - sendException(r, ctx.query, QueryError.getPosition(), QueryError.getMessage(), 400); - } catch (JournalException e) { - ctx.error().$("Server error executing query ").$(ctx.query).$(e).$(); - sendException(r, ctx.query, 0, e.getMessage(), 500); - } catch (InterruptedException e) { - ctx.error().$("Error executing query. Server is shutting down. Query: ").$(ctx.query).$(e).$(); - sendException(r, ctx.query, 0, "Server is shutting down.", 500); - } - } - long getCacheHits() { return cacheHits.longValue(); } @@ -404,60 +297,4 @@ private void sendDone(ChunkedResponse r, QueryHandlerContext ctx) throws Disconn r.done(); } - private enum QueryState { - PREFIX, METADATA, META_SUFFIX, RECORD_START, RECORD_COLUMNS, RECORD_SUFFIX, DATA_SUFFIX - } - - private static class QueryHandlerContext implements Mutable, Closeable { - private static final Log LOG = LogFactory.getLog(QueryHandlerContext.class); - private RecordSource recordSource; - private CharSequence query; - private RecordMetadata metadata; - private RecordCursor cursor; - private long count; - private long skip; - private long stop; - private Record record; - private JournalCachingFactory factory; - private long fd; - private QueryState state = QueryState.PREFIX; - private int columnIndex; - private boolean noMeta = false; - private boolean fetchAll = false; - - @Override - public void clear() { - debug().$("Cleaning context").$(); - metadata = null; - cursor = null; - record = null; - debug().$("Closing journal factory").$(); - factory = Misc.free(factory); - if (recordSource != null) { - CACHE.get().put(query.toString(), recordSource); - recordSource = null; - } - query = null; - state = QueryState.PREFIX; - fetchAll = false; - } - - @Override - public void close() throws IOException { - debug().$("Closing context").$(); - clear(); - } - - private LogRecord debug() { - return LOG.debug().$('[').$(fd).$("] "); - } - - private LogRecord error() { - return LOG.error().$('[').$(fd).$("] "); - } - - private LogRecord info() { - return LOG.info().$('[').$(fd).$("] "); - } - } } diff --git a/core/src/main/java/com/questdb/net/http/handlers/QueryHandlerContext.java b/core/src/main/java/com/questdb/net/http/handlers/QueryHandlerContext.java new file mode 100644 index 000000000000..d6feb7ccbde2 --- /dev/null +++ b/core/src/main/java/com/questdb/net/http/handlers/QueryHandlerContext.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.net.http.handlers; + +import com.questdb.ex.DisconnectedChannelException; +import com.questdb.ex.SlowWritableChannelException; +import com.questdb.misc.Chars; +import com.questdb.net.http.ChunkedResponse; +import com.questdb.net.http.Request; + +public class QueryHandlerContext extends AbstractQueryContext { + boolean fetchAll = false; + boolean noMeta = false; + + public QueryHandlerContext(long fd, int cyclesBeforeCancel) { + super(fd, cyclesBeforeCancel); + } + + @Override + public void clear() { + super.clear(); + state = QueryState.PREFIX; + fetchAll = false; + } + + @Override + public boolean parseUrl(ChunkedResponse r, Request request) throws DisconnectedChannelException, SlowWritableChannelException { + if (super.parseUrl(r, request)) { + noMeta = Chars.equalsNc("true", request.getUrlParam("nm")); + fetchAll = Chars.equalsNc("true", request.getUrlParam("count")); + return true; + } + return false; + } + + @Override + protected void header(ChunkedResponse r, int status) throws DisconnectedChannelException, SlowWritableChannelException { + r.status(status, "application/json; charset=utf-8"); + r.sendHeader(); + } + + @Override + protected void sendException(ChunkedResponse r, int position, CharSequence message, int status) throws DisconnectedChannelException, SlowWritableChannelException { + header(r, status); + r.put('{'). + putQuoted("query").put(':').putUtf8EscapedAndQuoted(query == null ? "" : query).put(','). + putQuoted("error").put(':').putQuoted(message).put(','). + putQuoted("position").put(':').put(position); + r.put('}'); + r.sendChunk(); + r.done(); + } +} diff --git a/core/src/main/java/com/questdb/net/http/handlers/StaticContentHandler.java b/core/src/main/java/com/questdb/net/http/handlers/StaticContentHandler.java index 3ef5d28e48fa..41be8dfc4789 100644 --- a/core/src/main/java/com/questdb/net/http/handlers/StaticContentHandler.java +++ b/core/src/main/java/com/questdb/net/http/handlers/StaticContentHandler.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.net.http.handlers; @@ -50,6 +51,8 @@ public class StaticContentHandler implements ContextHandler { private final MimeTypes mimeTypes; private final ThreadLocal tlPrefixedPath = new ThreadLocal<>(); private final ThreadLocal tlRangeParser = new ThreadLocal<>(); + private final ThreadLocal tlExt = new ThreadLocal<>(); + private final LocalValue lvFd = new LocalValue<>(); private final File publicDir; @@ -103,6 +106,7 @@ public void resume(IOContext context) throws IOException { public void setupThread() { tlRangeParser.set(RangeParser.FACTORY.newInstance()); tlPrefixedPath.set(new PrefixedPath(publicDir.getAbsolutePath())); + tlExt.set(new FlyweightCharSequence()); } private void send(IOContext context, LPSZ path, boolean asAttachment) throws IOException { @@ -112,8 +116,7 @@ private void send(IOContext context, LPSZ path, boolean asAttachment) throws IOE return; } - CharSequence contentType = mimeTypes.get(context.ext.of(path, n + 1, path.length() - n - 1)); - + CharSequence contentType = mimeTypes.get(tlExt.get().of(path, n + 1, path.length() - n - 1)); CharSequence val; if ((val = context.request.getHeader("Range")) != null) { sendRange(context, val, path, contentType, asAttachment); diff --git a/core/src/main/java/com/questdb/ql/CancellationHandler.java b/core/src/main/java/com/questdb/ql/CancellationHandler.java new file mode 100644 index 000000000000..9332ac9ad699 --- /dev/null +++ b/core/src/main/java/com/questdb/ql/CancellationHandler.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.ql; + +public interface CancellationHandler { + void check(); +} diff --git a/core/src/main/java/com/questdb/ql/RecordSource.java b/core/src/main/java/com/questdb/ql/RecordSource.java index 081daa380546..51be8f1b6b3f 100644 --- a/core/src/main/java/com/questdb/ql/RecordSource.java +++ b/core/src/main/java/com/questdb/ql/RecordSource.java @@ -48,7 +48,7 @@ public interface RecordSource extends Sinkable { Parameter getParam(CharSequence name); - RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException; + RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException; void reset(); diff --git a/core/src/main/java/com/questdb/ql/RowSource.java b/core/src/main/java/com/questdb/ql/RowSource.java index c5fbcf3ec450..045bc22d13f5 100644 --- a/core/src/main/java/com/questdb/ql/RowSource.java +++ b/core/src/main/java/com/questdb/ql/RowSource.java @@ -42,7 +42,7 @@ public interface RowSource extends Sinkable { void configure(JournalMetadata metadata); - void prepare(StorageFacade storageFacade); + void prepare(StorageFacade storageFacade, CancellationHandler cancellationHandler); RowCursor prepareCursor(PartitionSlice slice); diff --git a/core/src/main/java/com/questdb/ql/impl/AbstractRowSource.java b/core/src/main/java/com/questdb/ql/impl/AbstractRowSource.java index 2c7c43117fb7..ba49237e19ca 100644 --- a/core/src/main/java/com/questdb/ql/impl/AbstractRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/AbstractRowSource.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,10 +30,12 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql.impl; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.RowCursor; import com.questdb.ql.RowSource; import com.questdb.ql.StorageFacade; @@ -42,6 +44,6 @@ public abstract class AbstractRowSource implements RowSource, RowCursor { @SuppressFBWarnings({"ACEM_ABSTRACT_CLASS_EMPTY_METHODS"}) @Override - public void prepare(StorageFacade storageFacade) { + public void prepare(StorageFacade storageFacade, CancellationHandler cancellationHandler) { } } diff --git a/core/src/main/java/com/questdb/ql/impl/ChannelCheckCancellationHandler.java b/core/src/main/java/com/questdb/ql/impl/ChannelCheckCancellationHandler.java new file mode 100644 index 000000000000..84259b953c69 --- /dev/null +++ b/core/src/main/java/com/questdb/ql/impl/ChannelCheckCancellationHandler.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.ql.impl; + +import com.questdb.ex.DisconnectedChannelRuntimeException; +import com.questdb.misc.Net; +import com.questdb.misc.Numbers; +import com.questdb.ql.CancellationHandler; + +public class ChannelCheckCancellationHandler implements CancellationHandler { + private final long fd; + private long loop = 0; + private long mask; + + public ChannelCheckCancellationHandler(long fd, int cyclesBeforeCheck) { + this.fd = fd; + this.mask = Numbers.ceilPow2(cyclesBeforeCheck) - 1; + } + + @Override + public void check() { + if (loop > 0 && (loop & mask) == 0) { + checkChannel(); + } + loop++; + } + + public void reset() { + this.loop = 0; + } + + private void checkChannel() { + if (Net.isDead(fd)) { + throw DisconnectedChannelRuntimeException.INSTANCE; + } + } +} diff --git a/core/src/main/java/com/questdb/ql/impl/FilteredJournalRecordSource.java b/core/src/main/java/com/questdb/ql/impl/FilteredJournalRecordSource.java index 039acc2b47a6..92d1c83ff3e7 100644 --- a/core/src/main/java/com/questdb/ql/impl/FilteredJournalRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/FilteredJournalRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.model.ExprNode; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.ql.ops.VirtualColumn; @@ -83,8 +80,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.cursor = delegate.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.cursor = delegate.prepareCursor(factory, cancellationHandler); filter.prepare(cursor.getStorageFacade()); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/FilteredRowSource.java b/core/src/main/java/com/questdb/ql/impl/FilteredRowSource.java index fb005893d71a..48319c2f6d77 100644 --- a/core/src/main/java/com/questdb/ql/impl/FilteredRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/FilteredRowSource.java @@ -36,10 +36,7 @@ package com.questdb.ql.impl; import com.questdb.factory.configuration.JournalMetadata; -import com.questdb.ql.PartitionSlice; -import com.questdb.ql.RowCursor; -import com.questdb.ql.RowSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.VirtualColumn; import com.questdb.std.CharSink; @@ -90,8 +87,8 @@ public long next() { } @Override - public void prepare(StorageFacade facade) { - delegate.prepare(facade); + public void prepare(StorageFacade facade, CancellationHandler cancellationHandler) { + delegate.prepare(facade, cancellationHandler); filter.prepare(facade); } diff --git a/core/src/main/java/com/questdb/ql/impl/JournalSource.java b/core/src/main/java/com/questdb/ql/impl/JournalSource.java index 8fff7e0afbdc..ec2d033617fb 100644 --- a/core/src/main/java/com/questdb/ql/impl/JournalSource.java +++ b/core/src/main/java/com/questdb/ql/impl/JournalSource.java @@ -78,9 +78,9 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { this.partitionCursor = partitionSource.prepareCursor(factory); - this.rowSource.prepare(partitionCursor.getStorageFacade()); + this.rowSource.prepare(partitionCursor.getStorageFacade(), cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/NoOpCancellationHandler.java b/core/src/main/java/com/questdb/ql/impl/NoOpCancellationHandler.java new file mode 100644 index 000000000000..433058f66fed --- /dev/null +++ b/core/src/main/java/com/questdb/ql/impl/NoOpCancellationHandler.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + +package com.questdb.ql.impl; + +import com.questdb.ql.CancellationHandler; + +public class NoOpCancellationHandler implements CancellationHandler { + public static final NoOpCancellationHandler INSTANCE = new NoOpCancellationHandler(); + + private NoOpCancellationHandler() { + } + + @Override + public void check() { + } +} diff --git a/core/src/main/java/com/questdb/ql/impl/NoOpJournalRecordSource.java b/core/src/main/java/com/questdb/ql/impl/NoOpJournalRecordSource.java index 5a5fdd1522f5..74efbbdfc45a 100644 --- a/core/src/main/java/com/questdb/ql/impl/NoOpJournalRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/NoOpJournalRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.std.CharSink; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -71,8 +68,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.cursor = delegate.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.cursor = delegate.prepareCursor(factory, cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/TopRecordSource.java b/core/src/main/java/com/questdb/ql/impl/TopRecordSource.java index 36b76d89cfbc..9a745b5bd30a 100644 --- a/core/src/main/java/com/questdb/ql/impl/TopRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/TopRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.ql.ops.VirtualColumn; import com.questdb.std.CharSink; @@ -77,10 +74,10 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { this._top = lo.getLong(null); this._count = hi.getLong(null) - this._top; - this.recordCursor = recordSource.prepareCursor(factory); + this.recordCursor = recordSource.prepareCursor(factory, cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/aggregation/AggregatedRecordSource.java b/core/src/main/java/com/questdb/ql/impl/aggregation/AggregatedRecordSource.java index b48737e3aef7..ec5808ecca19 100644 --- a/core/src/main/java/com/questdb/ql/impl/aggregation/AggregatedRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/aggregation/AggregatedRecordSource.java @@ -131,9 +131,9 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.recordCursor = recordSource.prepareCursor(factory); - buildMap(); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.recordCursor = recordSource.prepareCursor(factory, cancellationHandler); + buildMap(cancellationHandler); return this; } @@ -166,10 +166,12 @@ public void toSink(CharSink sink) { sink.put('}'); } - private void buildMap() { + private void buildMap(CancellationHandler cancellationHandler) { while (recordCursor.hasNext()) { + cancellationHandler.check(); + Record rec = recordCursor.next(); // we are inside of time window, compute aggregates diff --git a/core/src/main/java/com/questdb/ql/impl/aggregation/CountRecordSource.java b/core/src/main/java/com/questdb/ql/impl/aggregation/CountRecordSource.java index 6c16476ec682..f29caae4b853 100644 --- a/core/src/main/java/com/questdb/ql/impl/aggregation/CountRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/aggregation/CountRecordSource.java @@ -80,7 +80,7 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { partitionCursor = partitionSource.prepareCursor(factory); computeCount(); return this; diff --git a/core/src/main/java/com/questdb/ql/impl/aggregation/ResampledRecordSource.java b/core/src/main/java/com/questdb/ql/impl/aggregation/ResampledRecordSource.java index 2566b3864885..de051a75d13e 100644 --- a/core/src/main/java/com/questdb/ql/impl/aggregation/ResampledRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/aggregation/ResampledRecordSource.java @@ -134,8 +134,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.recordCursor = recordSource.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.recordCursor = recordSource.prepareCursor(factory, cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/interval/IntervalRecordSource.java b/core/src/main/java/com/questdb/ql/impl/interval/IntervalRecordSource.java index 72d0667eaeb3..c5fd42c6fba6 100644 --- a/core/src/main/java/com/questdb/ql/impl/interval/IntervalRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/interval/IntervalRecordSource.java @@ -39,10 +39,7 @@ import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; import com.questdb.misc.Interval; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.std.CharSink; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; @@ -81,8 +78,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.cursor = delegate.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.cursor = delegate.prepareCursor(factory, cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/join/AsOfJoinRecordSource.java b/core/src/main/java/com/questdb/ql/impl/join/AsOfJoinRecordSource.java index 55004551fcc0..17d4fe939cfc 100644 --- a/core/src/main/java/com/questdb/ql/impl/join/AsOfJoinRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/join/AsOfJoinRecordSource.java @@ -40,10 +40,7 @@ import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; import com.questdb.misc.Misc; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.impl.join.asof.FixRecordHolder; import com.questdb.ql.impl.join.asof.RecordHolder; import com.questdb.ql.impl.join.asof.RowidRecordHolder; @@ -133,9 +130,9 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.masterCursor = master.prepareCursor(factory); - this.slaveCursor = slave.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.masterCursor = master.prepareCursor(factory, cancellationHandler); + this.slaveCursor = slave.prepareCursor(factory, cancellationHandler); this.recordHolder.setCursor(slaveCursor); this.delayedHolder.setCursor(slaveCursor); this.storageFacade.prepare(factory, masterCursor.getStorageFacade(), slaveCursor.getStorageFacade()); diff --git a/core/src/main/java/com/questdb/ql/impl/join/AsOfPartitionedJoinRecordSource.java b/core/src/main/java/com/questdb/ql/impl/join/AsOfPartitionedJoinRecordSource.java index c92aed2353e8..1628164ae47f 100644 --- a/core/src/main/java/com/questdb/ql/impl/join/AsOfPartitionedJoinRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/join/AsOfPartitionedJoinRecordSource.java @@ -40,10 +40,7 @@ import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; import com.questdb.misc.Misc; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.impl.join.asof.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.std.CharSequenceHashSet; @@ -141,9 +138,9 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.masterCursor = master.prepareCursor(factory); - this.slaveCursor = slave.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.masterCursor = master.prepareCursor(factory, cancellationHandler); + this.slaveCursor = slave.prepareCursor(factory, cancellationHandler); map.setSlaveCursor(slaveCursor); holder.setCursor(slaveCursor); storageFacade.prepare(factory, masterCursor.getStorageFacade(), map.getStorageFacade()); diff --git a/core/src/main/java/com/questdb/ql/impl/join/CrossJoinRecordSource.java b/core/src/main/java/com/questdb/ql/impl/join/CrossJoinRecordSource.java index 5e20c61b8b52..743e630df9e1 100644 --- a/core/src/main/java/com/questdb/ql/impl/join/CrossJoinRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/join/CrossJoinRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.std.CharSink; @@ -77,9 +74,9 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - masterCursor = masterSource.prepareCursor(factory); - slaveCursor = slaveSource.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + masterCursor = masterSource.prepareCursor(factory, cancellationHandler); + slaveCursor = slaveSource.prepareCursor(factory, cancellationHandler); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/join/HashJoinRecordSource.java b/core/src/main/java/com/questdb/ql/impl/join/HashJoinRecordSource.java index 79984cc4963d..ecab9ae39e9a 100644 --- a/core/src/main/java/com/questdb/ql/impl/join/HashJoinRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/join/HashJoinRecordSource.java @@ -40,10 +40,7 @@ import com.questdb.factory.configuration.RecordColumnMetadata; import com.questdb.factory.configuration.RecordMetadata; import com.questdb.misc.Misc; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.impl.join.hash.FakeRecord; import com.questdb.ql.impl.join.hash.MultiRecordMap; import com.questdb.ql.impl.join.hash.NullRecord; @@ -127,10 +124,10 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.slaveCursor = slave.prepareCursor(factory); - this.masterCursor = master.prepareCursor(factory); - buildHashTable(); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.slaveCursor = slave.prepareCursor(factory, cancellationHandler); + this.masterCursor = master.prepareCursor(factory, cancellationHandler); + buildHashTable(cancellationHandler); recordMap.setStorageFacade(slaveCursor.getStorageFacade()); storageFacade.prepare(factory, masterCursor.getStorageFacade(), slaveCursor.getStorageFacade()); return this; @@ -189,8 +186,9 @@ public void toSink(CharSink sink) { sink.put("]]}"); } - private void buildHashTable() { + private void buildHashTable(CancellationHandler cancellationHandler) { for (Record r : slaveCursor) { + cancellationHandler.check(); MultiMap.KeyWriter key = recordMap.claimKey(); for (int i = 0, k = slaveColumns.size(); i < k; i++) { setKey(key, r, slaveColIndex.getQuick(i), slaveColumns.getQuick(i).getType()); diff --git a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexIntLambdaHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexIntLambdaHeadRowSource.java index c89e6fcabd52..554db8e441d7 100644 --- a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexIntLambdaHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexIntLambdaHeadRowSource.java @@ -125,14 +125,14 @@ public long next() { @SuppressFBWarnings("EXS_EXCEPTION_SOFTENING_NO_CHECKED") @Override - public void prepare(StorageFacade fa) { + public void prepare(StorageFacade fa, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(fa); } keys.clear(); try { - for (Record r : recordSource.prepareCursor(fa.getFactory())) { + for (Record r : recordSource.prepareCursor(fa.getFactory(), cancellationHandler)) { keys.add(r.getInt(recordSourceColumn)); } } catch (JournalException e) { diff --git a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexStrLambdaHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexStrLambdaHeadRowSource.java index d34116241bda..779e39461b3b 100644 --- a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexStrLambdaHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexStrLambdaHeadRowSource.java @@ -127,7 +127,7 @@ public long next() { @SuppressFBWarnings("EXS_EXCEPTION_SOFTENING_NO_CHECKED") @Override - public void prepare(StorageFacade fa) { + public void prepare(StorageFacade fa, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(fa); } @@ -135,7 +135,7 @@ public void prepare(StorageFacade fa) { keys.clear(); hashes.clear(); try { - for (Record r : recordSource.prepareCursor(fa.getFactory())) { + for (Record r : recordSource.prepareCursor(fa.getFactory(), cancellationHandler)) { CharSequence s = getKey(r, recordSourceColumn); if (keys.add(s)) { hashes.add(Hash.boundedHash(s, buckets)); diff --git a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexSymLambdaHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexSymLambdaHeadRowSource.java index d34d712db03a..7e31de1b1646 100644 --- a/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexSymLambdaHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/lambda/KvIndexSymLambdaHeadRowSource.java @@ -117,7 +117,7 @@ public long next() { @SuppressFBWarnings("EXS_EXCEPTION_SOFTENING_NO_CHECKED") @Override - public void prepare(StorageFacade fa) { + public void prepare(StorageFacade fa, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(fa); @@ -126,7 +126,7 @@ public void prepare(StorageFacade fa) { SymbolTable tab = fa.getSymbolTable(column); keys.clear(); try { - for (Record r : recordSource.prepareCursor(fa.getFactory())) { + for (Record r : recordSource.prepareCursor(fa.getFactory(), cancellationHandler)) { int k = tab.getQuick(getKey(r, recordSourceColumn)); if (k > -1) { keys.add(k); diff --git a/core/src/main/java/com/questdb/ql/impl/latest/HeapMergingRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/HeapMergingRowSource.java index df6a9ecfeade..2e272fdd89b5 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/HeapMergingRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/HeapMergingRowSource.java @@ -37,10 +37,7 @@ import com.questdb.factory.configuration.JournalMetadata; import com.questdb.misc.Unsafe; -import com.questdb.ql.PartitionSlice; -import com.questdb.ql.RowCursor; -import com.questdb.ql.RowSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.std.CharSink; import com.questdb.std.IntLongPriorityQueue; @@ -57,15 +54,15 @@ public HeapMergingRowSource(RowSource... sources) { @Override public void configure(JournalMetadata metadata) { - for (RowSource src : sources) { - src.configure(metadata); + for (int i = 0, n = sources.length; i < n; i++) { + Unsafe.arrayGet(sources, i).configure(metadata); } } @Override - public void prepare(StorageFacade facade) { - for (RowSource src : sources) { - src.prepare(facade); + public void prepare(StorageFacade facade, CancellationHandler cancellationHandler) { + for (int i = 0, n = sources.length; i < n; i++) { + Unsafe.arrayGet(sources, i).prepare(facade, cancellationHandler); } } diff --git a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexIntListHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexIntListHeadRowSource.java index b18ac61630fd..5a2cd62d31b1 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexIntListHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexIntListHeadRowSource.java @@ -39,6 +39,7 @@ import com.questdb.ex.JournalException; import com.questdb.ex.JournalRuntimeException; import com.questdb.factory.configuration.JournalMetadata; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.PartitionSlice; import com.questdb.ql.RowCursor; import com.questdb.ql.StorageFacade; @@ -127,7 +128,7 @@ public long next() { } @Override - public void prepare(StorageFacade storageFacade) { + public void prepare(StorageFacade storageFacade, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(storageFacade); } diff --git a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexStrListHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexStrListHeadRowSource.java index ed420c83afb9..e2d6df792ff8 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexStrListHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexStrListHeadRowSource.java @@ -40,6 +40,7 @@ import com.questdb.ex.JournalRuntimeException; import com.questdb.factory.configuration.JournalMetadata; import com.questdb.misc.Hash; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.PartitionSlice; import com.questdb.ql.RowCursor; import com.questdb.ql.StorageFacade; @@ -123,7 +124,7 @@ public long next() { } @Override - public void prepare(StorageFacade storageFacade) { + public void prepare(StorageFacade storageFacade, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(storageFacade); } diff --git a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymAllHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymAllHeadRowSource.java index c06124fdeeb3..16b99ef867eb 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymAllHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymAllHeadRowSource.java @@ -39,6 +39,7 @@ import com.questdb.ex.JournalException; import com.questdb.ex.JournalRuntimeException; import com.questdb.factory.configuration.JournalMetadata; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.PartitionSlice; import com.questdb.ql.RowCursor; import com.questdb.ql.StorageFacade; @@ -115,7 +116,7 @@ public long next() { } @Override - public void prepare(StorageFacade facade) { + public void prepare(StorageFacade facade, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(facade); } diff --git a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymListHeadRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymListHeadRowSource.java index 05556a3b432e..8340e5ff6eb5 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymListHeadRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymListHeadRowSource.java @@ -39,6 +39,7 @@ import com.questdb.ex.JournalException; import com.questdb.ex.JournalRuntimeException; import com.questdb.factory.configuration.JournalMetadata; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.PartitionSlice; import com.questdb.ql.RowCursor; import com.questdb.ql.StorageFacade; @@ -123,7 +124,7 @@ public long next() { } @Override - public void prepare(StorageFacade fa) { + public void prepare(StorageFacade fa, CancellationHandler cancellationHandler) { if (filter != null) { filter.prepare(fa); diff --git a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymLookupRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymLookupRowSource.java index 0df0fc8cb559..d5925473c933 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymLookupRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/KvIndexSymLookupRowSource.java @@ -38,6 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.ex.JournalRuntimeException; import com.questdb.factory.configuration.JournalMetadata; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.PartitionSlice; import com.questdb.ql.RowCursor; import com.questdb.ql.StorageFacade; @@ -127,7 +128,7 @@ public long next() { } @Override - public void prepare(StorageFacade facade) { + public void prepare(StorageFacade facade, CancellationHandler cancellationHandler) { symbolKey = facade.getSymbolTable(symbol).getQuick(value); } diff --git a/core/src/main/java/com/questdb/ql/impl/latest/MergingRowSource.java b/core/src/main/java/com/questdb/ql/impl/latest/MergingRowSource.java index dbf84c0ae3ea..6a6858270080 100644 --- a/core/src/main/java/com/questdb/ql/impl/latest/MergingRowSource.java +++ b/core/src/main/java/com/questdb/ql/impl/latest/MergingRowSource.java @@ -36,10 +36,7 @@ package com.questdb.ql.impl.latest; import com.questdb.factory.configuration.JournalMetadata; -import com.questdb.ql.PartitionSlice; -import com.questdb.ql.RowCursor; -import com.questdb.ql.RowSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.std.CharSink; public class MergingRowSource implements RowSource, RowCursor { @@ -62,9 +59,9 @@ public void configure(JournalMetadata metadata) { } @Override - public void prepare(StorageFacade facade) { - lhs.prepare(facade); - rhs.prepare(facade); + public void prepare(StorageFacade facade, CancellationHandler cancellationHandler) { + lhs.prepare(facade, cancellationHandler); + rhs.prepare(facade, cancellationHandler); } @Override diff --git a/core/src/main/java/com/questdb/ql/impl/select/SelectedColumnsRecordSource.java b/core/src/main/java/com/questdb/ql/impl/select/SelectedColumnsRecordSource.java index 5d33d71a44f1..523bc473d17e 100644 --- a/core/src/main/java/com/questdb/ql/impl/select/SelectedColumnsRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/select/SelectedColumnsRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.std.CharSequenceHashSet; import com.questdb.std.CharSink; @@ -87,8 +84,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.recordCursor = recordSource.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.recordCursor = recordSource.prepareCursor(factory, cancellationHandler); this.storageFacade.of(recordCursor.getStorageFacade()); return this; } diff --git a/core/src/main/java/com/questdb/ql/impl/sort/RBTreeSortedRecordSource.java b/core/src/main/java/com/questdb/ql/impl/sort/RBTreeSortedRecordSource.java index 387171d2e82b..688be1e7e3ad 100644 --- a/core/src/main/java/com/questdb/ql/impl/sort/RBTreeSortedRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/sort/RBTreeSortedRecordSource.java @@ -39,10 +39,7 @@ import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; import com.questdb.misc.Unsafe; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.impl.RecordList; import com.questdb.ql.impl.join.hash.FakeRecord; import com.questdb.ql.ops.AbstractRecordSource; @@ -101,13 +98,13 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - sourceCursor = recordSource.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + sourceCursor = recordSource.prepareCursor(factory, cancellationHandler); records.setStorageFacade(sourceCursor.getStorageFacade()); if (byRowId) { - buildMapByRowId(sourceCursor); + buildMapByRowId(sourceCursor, cancellationHandler); } else { - buildMap(sourceCursor); + buildMap(sourceCursor, cancellationHandler); } cursor.setup(); return cursor; @@ -218,14 +215,16 @@ private long allocateBlock() { return p; } - private void buildMap(RecordCursor cursor) { + private void buildMap(RecordCursor cursor, CancellationHandler cancellationHandler) { while (cursor.hasNext()) { + cancellationHandler.check(); put(cursor.next()); } } - private void buildMapByRowId(RecordCursor cursor) { + private void buildMapByRowId(RecordCursor cursor, CancellationHandler cancellationHandler) { while (cursor.hasNext()) { + cancellationHandler.check(); put(cursor.next().getRowId()); } } diff --git a/core/src/main/java/com/questdb/ql/impl/virtual/VirtualColumnRecordSource.java b/core/src/main/java/com/questdb/ql/impl/virtual/VirtualColumnRecordSource.java index 7968c9d33c8b..e54cefa21dc6 100644 --- a/core/src/main/java/com/questdb/ql/impl/virtual/VirtualColumnRecordSource.java +++ b/core/src/main/java/com/questdb/ql/impl/virtual/VirtualColumnRecordSource.java @@ -38,10 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; -import com.questdb.ql.Record; -import com.questdb.ql.RecordCursor; -import com.questdb.ql.RecordSource; -import com.questdb.ql.StorageFacade; +import com.questdb.ql.*; import com.questdb.ql.ops.AbstractCombinedRecordSource; import com.questdb.ql.ops.VirtualColumn; import com.questdb.std.CharSink; @@ -80,8 +77,8 @@ public RecordMetadata getMetadata() { } @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - this.recordCursor = recordSource.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + this.recordCursor = recordSource.prepareCursor(factory, cancellationHandler); current.prepare(recordCursor.getStorageFacade()); return this; } diff --git a/core/src/main/java/com/questdb/ql/parser/QueryCompiler.java b/core/src/main/java/com/questdb/ql/parser/QueryCompiler.java index 44040bd50451..4ef6cc32551a 100644 --- a/core/src/main/java/com/questdb/ql/parser/QueryCompiler.java +++ b/core/src/main/java/com/questdb/ql/parser/QueryCompiler.java @@ -145,7 +145,7 @@ public RecordCursor compile(JournalReaderFactory factory, Class clazz) th } public RecordCursor compile(JournalReaderFactory factory, CharSequence query) throws ParserException, JournalException { - return compileSource(factory, query).prepareCursor(factory); + return compileSource(factory, query).prepareCursor(factory, NoOpCancellationHandler.INSTANCE); } public RecordSource compileSource(JournalReaderFactory factory, CharSequence query) throws ParserException, JournalException { diff --git a/core/src/main/resources/binaries/osx/libquestdb.dylib b/core/src/main/resources/binaries/osx/libquestdb.dylib index 3b44b028c6cfcbbbb15487bce34b6212b9e05137..f4dbca6aa076f5f869ce252fd6d2b79491e57830 100755 GIT binary patch delta 11506 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 G@V@~*AxY{0 delta 11228 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 diff --git a/core/src/main/resources/site/conf/questdb.conf b/core/src/main/resources/site/conf/questdb.conf index ae4c7dae0a3c..01e6f82f44bd 100644 --- a/core/src/main/resources/site/conf/questdb.conf +++ b/core/src/main/resources/site/conf/questdb.conf @@ -137,4 +137,10 @@ db.hash.datapage = 8M # Size of memory allocation page for storing row ids in hash join algorithm. # Default value is 4Mb -db.hash.rowpage = 1M \ No newline at end of file +db.hash.rowpage = 1M + +# Number of rows processed by internal algorithms before they check if receiving socket is +# still open. This is applicable to non-streaming algorithms, such as hashing or sorting. +# Making this value too large increases time interval between socket closed and +# thread releasing. Making it too small adds overhead of socket check making queries slower. +db.cycles.before.cancel = 1048576 \ No newline at end of file diff --git a/core/src/test/java/com/questdb/net/http/handlers/QueryHandlerConsistencyTest.java b/core/src/test/java/com/questdb/net/http/handlers/QueryHandlerConsistencyTest.java index e6f68c5df537..7cfc0ecdf10f 100644 --- a/core/src/test/java/com/questdb/net/http/handlers/QueryHandlerConsistencyTest.java +++ b/core/src/test/java/com/questdb/net/http/handlers/QueryHandlerConsistencyTest.java @@ -1,3 +1,38 @@ +/******************************************************************************* + * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * + * Copyright (C) 2014-2016 Appsicle + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + * + ******************************************************************************/ + package com.questdb.net.http.handlers; import com.questdb.factory.JournalFactoryPool; @@ -31,12 +66,12 @@ public static void setUp() throws Exception { @Test public void testCsvHandlerConsistency() throws Exception { - testHandler(new CsvHandler(new JournalFactoryPool(factory.getConfiguration(), 1))); + testHandler(new CsvHandler(new JournalFactoryPool(factory.getConfiguration(), 1), new ServerConfiguration())); } @Test public void testCsvOutput() throws Exception { - ContextHandler handler = new CsvHandler(new JournalFactoryPool(factory.getConfiguration(), 1)); + ContextHandler handler = new CsvHandler(new JournalFactoryPool(factory.getConfiguration(), 1), new ServerConfiguration()); handler.setupThread(); TestChannel channel = new TestChannel(QUERY1); String expected = "\"id\",\"x\",\"y\",\"z\",\"w\",\"timestamp\"\r\n" + @@ -142,7 +177,7 @@ public void testCsvOutput() throws Exception { "id99,-384.0000000000,0.0000000980,-264,355,\"2015-03-12T00:00:00.990Z\"\r\n"; try { channel.reset(); - try (IOContext context = new IOContext(channel, MilliClock.INSTANCE, 1024, 1024, 1024, 512, 1024, 128 * 1024, 4 * 1024 * 1024, 1024)) { + try (IOContext context = new IOContext(channel, new ServerConfiguration(), MilliClock.INSTANCE)) { context.request.read(); handler.handle(context); TestUtils.assertEquals(expected, channel.getOutput()); @@ -162,9 +197,11 @@ private void testHandler(ContextHandler handler) throws Exception { String expected = null; handler.setupThread(); try { + ServerConfiguration configuration = new ServerConfiguration(); for (int i = 128; i < 7500; i++) { channel.reset(); - try (IOContext context = new IOContext(channel, MilliClock.INSTANCE, 1024, 1024, 1024, 512, i, 128 * 1024, 4 * 1024 * 1024, 1024)) { + configuration.setHttpBufRespContent(i); + try (IOContext context = new IOContext(channel, configuration, MilliClock.INSTANCE)) { context.request.read(); handler.handle(context); if (expected != null) { @@ -177,5 +214,6 @@ private void testHandler(ContextHandler handler) throws Exception { } finally { channel.free(); } + System.out.println(expected); } } diff --git a/core/src/test/java/com/questdb/ql/AsOfPartitionedJoinRecordSourceTest.java b/core/src/test/java/com/questdb/ql/AsOfPartitionedJoinRecordSourceTest.java index b05269d69afe..08caaae734f0 100644 --- a/core/src/test/java/com/questdb/ql/AsOfPartitionedJoinRecordSourceTest.java +++ b/core/src/test/java/com/questdb/ql/AsOfPartitionedJoinRecordSourceTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -43,6 +44,7 @@ import com.questdb.misc.Chars; import com.questdb.misc.Dates; import com.questdb.misc.Rnd; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.NoRowidSource; import com.questdb.ql.impl.join.AsOfJoinRecordSource; import com.questdb.ql.impl.join.AsOfPartitionedJoinRecordSource; @@ -291,11 +293,11 @@ public void testFixJoin() throws Exception { , 128 , 128 )) { - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); source.reset(); sink.clear(); - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); } } @@ -319,11 +321,11 @@ public void testFixNonPartitionedJoin() throws Exception { , new NoRowidSource().of(compiler.compileSource(factory, "select timestamp, ccy, rate, amount, contra, ln, fl, sh, b from x")) , 0 )) { - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); source.reset(); sink.clear(); - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); } } @@ -383,11 +385,11 @@ public void testRowidJoin() throws Exception { , 512 , 512 )) { - printer.printCursor(source.prepareCursor(factory), true); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), true); TestUtils.assertEquals(expected, sink); sink.clear(); source.reset(); - printer.printCursor(source.prepareCursor(factory), true); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), true); TestUtils.assertEquals(expected, sink); } } @@ -412,11 +414,11 @@ public void testRowidNonPartitioned() throws Exception { "2015-03-10T00:08:00.000Z\tSWHYRX\t-810.375000000000\tPULKHMJLLKQZJIONCLBYNYYWYBEPKPNZXNYWIGPCMLCBMUPYMRIGQWSZMUMXMSYXCEEDCL\t2015-03-10T00:07:50.000Z\tPEHNRX\t-969.125000000000\t0.207036912441\tSUZHUEVVELXBCOGQQGZZNTEZNOOZGQPKNLKUWCXHYPNZEBESMTXULVCTMKCZJGHRIMUNWUUQHXCRSLYJFTDNSEPESIUROKI\tVTJWCP\t0.3852\t27447\t3768436831039810156\ttrue\n" + "2015-03-10T00:09:00.000Z\tSWHYRX\t-384.000000000000\tZGUJBKNTPYXUBYXGDDULXVVSCNJINCQSDOQILSLXZEMDBLNXHYUUTVSXURFLRJLIUC\t2015-03-10T00:08:50.000Z\tVTJWCP\t-1024.000000000000\t0.000000084048\tJOZWRXKMTFXRYPHFPUYWNLBVVHNSJLVKRTLXHBHDHIMFYOJREFU\tSWHYRX\t0.4008\t-25237\t-2694211234414702926\ttrue\n" + "2015-03-10T00:10:00.000Z\tVTJWCP\t384.000000000000\tPGKJRQGKHQHXYUVDUZQTICMPWFZEINPQOGHUGZGDCFLNGCEFBTDNSYQTIGUTKIESOSYYLIBUFGPWTQJQWTGERXRSYZCKPFWECEH\t2015-03-10T00:09:50.000Z\tVTJWCP\t0.062803771347\t896.000000000000\tYVJISIQFNSEUHOSVSIKJFJLNEKTSLZFPGDVCLMZTXOYEPKECCJZJOSDCIWCZECJGNWQNKCYVZJRRZYDBL\tPEHNRX\t0.9202\t-15664\t-5743731661904518905\ttrue\n"; - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); source.reset(); sink.clear(); - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); } @@ -435,7 +437,7 @@ public void testStrings() throws Exception { )) { StringSink testSink = new StringSink(); int idx = source.getMetadata().getColumnIndex("trader"); - for (Record r : source.prepareCursor(factory)) { + for (Record r : source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)) { testSink.clear(); r.getStr(idx, testSink); @@ -474,11 +476,11 @@ public void testVarJoin() throws Exception { , 512 , 512 )) { - printer.printCursor(source.prepareCursor(factory), true); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), true); TestUtils.assertEquals(expected, sink); source.reset(); sink.clear(); - printer.printCursor(source.prepareCursor(factory), true); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), true); TestUtils.assertEquals(expected, sink); } } @@ -503,7 +505,7 @@ public void testVarNonPartitioned() throws Exception { "2015-03-10T00:08:00.000Z\tSWHYRX\t-810.375000000000\tPULKHMJLLKQZJIONCLBYNYYWYBEPKPNZXNYWIGPCMLCBMUPYMRIGQWSZMUMXMSYXCEEDCL\t2015-03-10T00:07:50.000Z\tPEHNRX\t-969.125000000000\t0.207036912441\tSUZHUEVVELXBCOGQQGZZNTEZNOOZGQPKNLKUWCXHYPNZEBESMTXULVCTMKCZJGHRIMUNWUUQHXCRSLYJFTDNSEPESIUROKI\tVTJWCP\t0.3852\t27447\t3768436831039810156\ttrue\n" + "2015-03-10T00:09:00.000Z\tSWHYRX\t-384.000000000000\tZGUJBKNTPYXUBYXGDDULXVVSCNJINCQSDOQILSLXZEMDBLNXHYUUTVSXURFLRJLIUC\t2015-03-10T00:08:50.000Z\tVTJWCP\t-1024.000000000000\t0.000000084048\tJOZWRXKMTFXRYPHFPUYWNLBVVHNSJLVKRTLXHBHDHIMFYOJREFU\tSWHYRX\t0.4008\t-25237\t-2694211234414702926\ttrue\n" + "2015-03-10T00:10:00.000Z\tVTJWCP\t384.000000000000\tPGKJRQGKHQHXYUVDUZQTICMPWFZEINPQOGHUGZGDCFLNGCEFBTDNSYQTIGUTKIESOSYYLIBUFGPWTQJQWTGERXRSYZCKPFWECEH\t2015-03-10T00:09:50.000Z\tVTJWCP\t0.062803771347\t896.000000000000\tYVJISIQFNSEUHOSVSIKJFJLNEKTSLZFPGDVCLMZTXOYEPKECCJZJOSDCIWCZECJGNWQNKCYVZJRRZYDBL\tPEHNRX\t0.9202\t-15664\t-5743731661904518905\ttrue\n"; - printer.printCursor(source.prepareCursor(factory)); + printer.printCursor(source.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); } diff --git a/core/src/test/java/com/questdb/ql/HashJoinRecordSourceTest.java b/core/src/test/java/com/questdb/ql/HashJoinRecordSourceTest.java index a7580b10f5f7..2b13f9cbfc1f 100644 --- a/core/src/test/java/com/questdb/ql/HashJoinRecordSourceTest.java +++ b/core/src/test/java/com/questdb/ql/HashJoinRecordSourceTest.java @@ -48,6 +48,7 @@ import com.questdb.ql.impl.AllRowSource; import com.questdb.ql.impl.JournalPartitionSource; import com.questdb.ql.impl.JournalSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.join.HashJoinRecordSource; import com.questdb.ql.impl.select.SelectedColumnsRecordSource; import com.questdb.std.IntList; @@ -118,7 +119,7 @@ public void testHashJoinJournalRecordSource() throws Exception { add("genre"); }} ); - p.printCursor(joinResult.prepareCursor(factory)); + p.printCursor(joinResult.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); Assert.assertEquals("pop\n" + "rock\n" + "metal\n" + @@ -153,7 +154,7 @@ public void testHashJoinPerformance() throws Exception { long t = System.currentTimeMillis(); int count = 0; // ExportManager.export(j, new File("c:/temp/join.csv"), TextFileFormat.TAB); - RecordCursor c = j.prepareCursor(factory); + RecordCursor c = j.prepareCursor(factory, NoOpCancellationHandler.INSTANCE); while (c.hasNext()) { c.next(); count++; @@ -203,7 +204,7 @@ public void testHashJoinRecordSource() throws Exception { add("genre"); }} ); - p.printCursor(joinResult.prepareCursor(factory)); + p.printCursor(joinResult.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); Assert.assertEquals("pop\n" + "rock\n" + "metal\n" + @@ -249,7 +250,7 @@ public void testOuterHashJoin() throws Exception { add("url"); }} ); - p.printCursor(joinResult.prepareCursor(factory)); + p.printCursor(joinResult.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); Assert.assertEquals("pop\thttp://band1.com\n" + "rock\thttp://band1.com\n" + "\thttp://band2.com\n" + diff --git a/core/src/test/java/com/questdb/ql/JoinStringToSymbolTest.java b/core/src/test/java/com/questdb/ql/JoinStringToSymbolTest.java index 15465f0f2622..8f19eae73be8 100644 --- a/core/src/test/java/com/questdb/ql/JoinStringToSymbolTest.java +++ b/core/src/test/java/com/questdb/ql/JoinStringToSymbolTest.java @@ -47,6 +47,7 @@ import com.questdb.ql.impl.AllRowSource; import com.questdb.ql.impl.JournalPartitionSource; import com.questdb.ql.impl.JournalSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.join.CrossJoinRecordSource; import com.questdb.test.tools.JournalTestFactory; import com.questdb.test.tools.TestUtils; @@ -116,7 +117,7 @@ public void testCrossJoin() throws Exception { new JournalSource( new JournalPartitionSource(bw.getMetadata(), false), new AllRowSource() ) - ).prepareCursor(factory) + ).prepareCursor(factory, NoOpCancellationHandler.INSTANCE) ); final String expected = "band1\talbum X\tpop\t1970-01-01T00:00:00.000Z\t1970-01-01T00:00:00.000Z\tband1\thttp://band1.com\trock\t\n" + diff --git a/core/src/test/java/com/questdb/ql/MergingRowSourceTest.java b/core/src/test/java/com/questdb/ql/MergingRowSourceTest.java index 89c7d24be968..e9cf6e4d2889 100644 --- a/core/src/test/java/com/questdb/ql/MergingRowSourceTest.java +++ b/core/src/test/java/com/questdb/ql/MergingRowSourceTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -41,6 +42,7 @@ import com.questdb.model.Quote; import com.questdb.ql.impl.JournalPartitionSource; import com.questdb.ql.impl.JournalSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.latest.HeapMergingRowSource; import com.questdb.ql.impl.latest.KvIndexSymLookupRowSource; import com.questdb.ql.impl.latest.MergingRowSource; @@ -61,7 +63,7 @@ public void testHeapMerge() throws JournalException, NumericException { RecordSource rs = new JournalSource(new JournalPartitionSource(w.getMetadata(), true), new HeapMergingRowSource(srcA, srcB)); long last = 0; - RecordCursor c = rs.prepareCursor(factory); + RecordCursor c = rs.prepareCursor(factory, NoOpCancellationHandler.INSTANCE); int ts = rs.getMetadata().getColumnIndex("timestamp"); while (c.hasNext()) { long r = c.next().getDate(ts); @@ -81,7 +83,7 @@ public void testMerge() throws JournalException, NumericException { RecordSource rs = new JournalSource(new JournalPartitionSource(w.getMetadata(), true), new MergingRowSource(srcA, srcB)); long last = 0; - RecordCursor c = rs.prepareCursor(factory); + RecordCursor c = rs.prepareCursor(factory, NoOpCancellationHandler.INSTANCE); int ts = rs.getMetadata().getColumnIndex("timestamp"); while (c.hasNext()) { long r = c.next().getDate(ts); diff --git a/core/src/test/java/com/questdb/ql/SingleJournalSearchTest.java b/core/src/test/java/com/questdb/ql/SingleJournalSearchTest.java index 7a44e6b07b3b..2239914de952 100644 --- a/core/src/test/java/com/questdb/ql/SingleJournalSearchTest.java +++ b/core/src/test/java/com/questdb/ql/SingleJournalSearchTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -46,6 +47,7 @@ import com.questdb.model.Quote; import com.questdb.ql.impl.JournalPartitionSource; import com.questdb.ql.impl.JournalSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.interval.MultiIntervalPartitionSource; import com.questdb.ql.impl.interval.SingleIntervalSource; import com.questdb.ql.impl.latest.KvIndexSymAllHeadRowSource; @@ -158,7 +160,7 @@ public void testHeadAfterFilter() throws Exception { } private void assertEquals(CharSequence expected, RecordSource src) throws JournalException, IOException { - new RecordSourcePrinter(sink).printCursor(src.prepareCursor(factory)); + new RecordSourcePrinter(sink).printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); Assert.assertEquals(expected, sink.toString()); sink.flush(); } diff --git a/core/src/test/java/com/questdb/ql/TailPartitionSourceTest.java b/core/src/test/java/com/questdb/ql/TailPartitionSourceTest.java index 884138ef6a62..ae26221ae627 100644 --- a/core/src/test/java/com/questdb/ql/TailPartitionSourceTest.java +++ b/core/src/test/java/com/questdb/ql/TailPartitionSourceTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -43,6 +44,7 @@ import com.questdb.model.Quote; import com.questdb.ql.impl.AllRowSource; import com.questdb.ql.impl.JournalSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.unused.JournalTailPartitionSource; import com.questdb.test.tools.AbstractTest; import com.questdb.test.tools.TestUtils; @@ -110,7 +112,7 @@ public void testTail() throws Exception { new JournalSource( new JournalTailPartitionSource(w.getMetadata(), false, Rows.toRowID(1, 30)) , new AllRowSource() - ).prepareCursor(factory) + ).prepareCursor(factory, NoOpCancellationHandler.INSTANCE) ); Assert.assertEquals(expected, sink.toString()); diff --git a/core/src/test/java/com/questdb/ql/TopRecordSourceTest.java b/core/src/test/java/com/questdb/ql/TopRecordSourceTest.java index 4fce0599f309..c3f0210670a3 100644 --- a/core/src/test/java/com/questdb/ql/TopRecordSourceTest.java +++ b/core/src/test/java/com/questdb/ql/TopRecordSourceTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -38,6 +39,7 @@ import com.questdb.io.RecordSourcePrinter; import com.questdb.io.sink.StringSink; import com.questdb.model.Quote; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.TopRecordSource; import com.questdb.ql.ops.constant.LongConstant; import com.questdb.test.tools.AbstractTest; @@ -54,7 +56,7 @@ public void testBottomSource() throws Exception { StringSink sink = new StringSink(); RecordSourcePrinter p = new RecordSourcePrinter(sink); - p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(99997), new LongConstant(100000)).prepareCursor(factory)); + p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(99997), new LongConstant(100000)).prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); final String expected = "2013-11-04T10:00:00.000Z\tBT-A.L\t168.000000000000\t0.001307277009\t319936098\t1456039311\tFast trading\tLXE\n" + "2013-11-04T10:00:00.000Z\tAGK.L\t0.000031983279\t878.000000000000\t819380635\t1732419403\tFast trading\tLXE\n" + @@ -69,7 +71,7 @@ public void testMiddleSource() throws Exception { StringSink sink = new StringSink(); RecordSourcePrinter p = new RecordSourcePrinter(sink); - p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(102), new LongConstant(112)).prepareCursor(factory)); + p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(102), new LongConstant(112)).prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); final String expected = "2013-09-04T10:00:00.000Z\tTLW.L\t0.003675992833\t0.000000006044\t233699709\t984001343\tFast trading\tLXE\n" + "2013-09-04T10:00:00.000Z\tGKN.L\t0.000001392326\t0.000000010696\t1921077830\t83098719\tFast trading\tLXE\n" + @@ -91,7 +93,7 @@ public void testNoRows() throws Exception { StringSink sink = new StringSink(); RecordSourcePrinter p = new RecordSourcePrinter(sink); - p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(99997), new LongConstant(10)).prepareCursor(factory)); + p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(99997), new LongConstant(10)).prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); Assert.assertEquals("", sink.toString()); } @@ -103,7 +105,7 @@ public void testTopSource() throws Exception { StringSink sink = new StringSink(); RecordSourcePrinter p = new RecordSourcePrinter(sink); - p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(0), new LongConstant(10)).prepareCursor(factory)); + p.printCursor(new TopRecordSource(compiler.compileSource(factory, "quote"), new LongConstant(0), new LongConstant(10)).prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); final String expected = "2013-09-04T10:00:00.000Z\tBT-A.L\t0.000001189157\t1.050231933594\t1326447242\t948263339\tFast trading\tLXE\n" + "2013-09-04T10:00:00.000Z\tADM.L\t104.021850585938\t0.006688738358\t1575378703\t1436881714\tFast trading\tLXE\n" + diff --git a/core/src/test/java/com/questdb/ql/VirtualColumnTest.java b/core/src/test/java/com/questdb/ql/VirtualColumnTest.java index d3eaeef9b588..27ee11cc8a37 100644 --- a/core/src/test/java/com/questdb/ql/VirtualColumnTest.java +++ b/core/src/test/java/com/questdb/ql/VirtualColumnTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql; @@ -40,6 +41,7 @@ import com.questdb.io.RecordSourcePrinter; import com.questdb.io.sink.StringSink; import com.questdb.misc.Rnd; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.select.SelectedColumnsRecordSource; import com.questdb.ql.impl.virtual.VirtualColumnRecordSource; import com.questdb.ql.ops.VirtualColumn; @@ -83,7 +85,7 @@ public void testPlusDouble() throws Exception { add(plus); }}); - p.printCursor(src.prepareCursor(factory)); + p.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); final String expected = "VTJWCPSWHY\t-104.021850585938\t-91.521850585938\n" + "PEHNRXGZSX\t0.000020634160\t12.500020634160\n" + @@ -227,7 +229,7 @@ public void testSelectedColumns() throws Exception { add("plus"); }}); - p.printCursor(src.prepareCursor(factory)); + p.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); final String expected = "VTJWCPSWHY\t-91.521850585938\n" + "PEHNRXGZSX\t12.500020634160\n" + diff --git a/core/src/test/java/com/questdb/ql/impl/MultiIntervalPartitionSourceTest.java b/core/src/test/java/com/questdb/ql/impl/MultiIntervalPartitionSourceTest.java index 1f2b101b0653..ed703ef02bc7 100644 --- a/core/src/test/java/com/questdb/ql/impl/MultiIntervalPartitionSourceTest.java +++ b/core/src/test/java/com/questdb/ql/impl/MultiIntervalPartitionSourceTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql.impl; @@ -71,7 +72,7 @@ public void testIntervalMerge() throws Exception { ) ), new AllRowSource() - ).prepareCursor(factory) + ).prepareCursor(factory, NoOpCancellationHandler.INSTANCE) ); final String expected = "2014-03-10T07:00:00.000Z\tGKN.L\t290.000000000000\t320.000000000000\t1070060020\t627764827\tFast trading\tLXE\n" + diff --git a/core/src/test/java/com/questdb/ql/impl/NoRowidSource.java b/core/src/test/java/com/questdb/ql/impl/NoRowidSource.java index 427aedd08955..5bcecac17b60 100644 --- a/core/src/test/java/com/questdb/ql/impl/NoRowidSource.java +++ b/core/src/test/java/com/questdb/ql/impl/NoRowidSource.java @@ -38,6 +38,7 @@ import com.questdb.ex.JournalException; import com.questdb.factory.JournalReaderFactory; import com.questdb.factory.configuration.RecordMetadata; +import com.questdb.ql.CancellationHandler; import com.questdb.ql.RecordCursor; import com.questdb.ql.RecordSource; import com.questdb.ql.ops.Parameter; @@ -59,8 +60,8 @@ public Parameter getParam(CharSequence name) { @SuppressWarnings("unchecked") @Override - public RecordCursor prepareCursor(JournalReaderFactory factory) throws JournalException { - return delegate.prepareCursor(factory); + public RecordCursor prepareCursor(JournalReaderFactory factory, CancellationHandler cancellationHandler) throws JournalException { + return delegate.prepareCursor(factory, cancellationHandler); } @Override diff --git a/core/src/test/java/com/questdb/ql/impl/sort/ComparatorCompilerTest.java b/core/src/test/java/com/questdb/ql/impl/sort/ComparatorCompilerTest.java index a6bca3e4054a..613d1c3dfe44 100644 --- a/core/src/test/java/com/questdb/ql/impl/sort/ComparatorCompilerTest.java +++ b/core/src/test/java/com/questdb/ql/impl/sort/ComparatorCompilerTest.java @@ -1,24 +1,24 @@ /******************************************************************************* - * ___ _ ____ ____ - * / _ \ _ _ ___ ___| |_| _ \| __ ) - * | | | | | | |/ _ \/ __| __| | | | _ \ - * | |_| | |_| | __/\__ \ |_| |_| | |_) | - * \__\_\\__,_|\___||___/\__|____/|____/ - *

+ * ___ _ ____ ____ + * / _ \ _ _ ___ ___| |_| _ \| __ ) + * | | | | | | |/ _ \/ __| __| | | | _ \ + * | |_| | |_| | __/\__ \ |_| |_| | |_) | + * \__\_\\__,_|\___||___/\__|____/|____/ + * * Copyright (C) 2014-2016 Appsicle - *

+ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - *

+ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - *

+ * * As a special exception, the copyright holders give permission to link the * code of portions of this program with the OpenSSL library under certain * conditions as described in each individual source file and distribute @@ -30,6 +30,7 @@ * delete this exception statement from your version. If you delete this * exception statement from all source files in the program, then also delete * it in the license file. + * ******************************************************************************/ package com.questdb.ql.impl.sort; @@ -41,6 +42,7 @@ import com.questdb.factory.configuration.RecordColumnMetadata; import com.questdb.ql.RecordSource; import com.questdb.ql.StorageFacade; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.ops.AbstractVirtualColumn; import com.questdb.ql.parser.AbstractOptimiserTest; import com.questdb.std.IntList; @@ -107,7 +109,7 @@ public void testAllGetters() throws Exception { RBTreeSortedRecordSource map = new RBTreeSortedRecordSource(rs, rc, 1024 * 1024, 4 * 1024 * 1024); sink.clear(); - printer.printCursor(map.prepareCursor(factory)); + printer.printCursor(map.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals( "false\t13\t20.120000000000\t10.1500\t4\t9988908080988890\t1970-01-02T00:42:59.879Z\t902\tcomplexity made simple\tappsicle\n" + "true\t13\t20.120000000000\t10.1500\t4\t9988908080988890\t1970-01-02T00:42:59.879Z\t902\tcomplexity made simple\tquestdb\n", diff --git a/core/src/test/java/com/questdb/ql/parser/AbstractOptimiserTest.java b/core/src/test/java/com/questdb/ql/parser/AbstractOptimiserTest.java index 66e5606180cb..a32515531b5e 100644 --- a/core/src/test/java/com/questdb/ql/parser/AbstractOptimiserTest.java +++ b/core/src/test/java/com/questdb/ql/parser/AbstractOptimiserTest.java @@ -47,6 +47,7 @@ import com.questdb.model.configuration.ModelConfiguration; import com.questdb.net.http.ServerConfiguration; import com.questdb.ql.RecordSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.std.AssociativeCache; import com.questdb.test.tools.JournalTestFactory; import com.questdb.test.tools.TestUtils; @@ -84,7 +85,7 @@ protected void assertThat(String expected, String query, boolean header) throws } else { rs.reset(); } - printer.printCursor(rs.prepareCursor(factory), header); + printer.printCursor(rs.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), header); TestUtils.assertEquals(expected, sink); } diff --git a/core/src/test/java/com/questdb/ql/parser/JoinQueryTest.java b/core/src/test/java/com/questdb/ql/parser/JoinQueryTest.java index 8d00a58aecf3..ce349840d560 100644 --- a/core/src/test/java/com/questdb/ql/parser/JoinQueryTest.java +++ b/core/src/test/java/com/questdb/ql/parser/JoinQueryTest.java @@ -45,6 +45,7 @@ import com.questdb.misc.Dates; import com.questdb.misc.Rnd; import com.questdb.ql.RecordSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.ql.impl.NoRowidSource; import com.questdb.ql.impl.join.HashJoinRecordSource; import com.questdb.std.IntHashSet; @@ -646,7 +647,7 @@ public void testJoinNoRowid() throws Exception { 1024 * 1024 ); sink.clear(); - printer.printCursor(r.prepareCursor(factory)); + printer.printCursor(r.prepareCursor(factory, NoOpCancellationHandler.INSTANCE)); TestUtils.assertEquals(expected, sink); assertThat(expected, "customers c join orders o on c.customerId = o.customerId where customerName ~ 'PJFSREKEUNMKWOF'"); } diff --git a/core/src/test/java/com/questdb/ql/parser/SingleJournalQueryTest.java b/core/src/test/java/com/questdb/ql/parser/SingleJournalQueryTest.java index 58c66d3b6042..547eb46633b6 100644 --- a/core/src/test/java/com/questdb/ql/parser/SingleJournalQueryTest.java +++ b/core/src/test/java/com/questdb/ql/parser/SingleJournalQueryTest.java @@ -51,6 +51,7 @@ import com.questdb.model.Quote; import com.questdb.net.http.ServerConfiguration; import com.questdb.ql.RecordSource; +import com.questdb.ql.impl.NoOpCancellationHandler; import com.questdb.std.ObjHashSet; import com.questdb.test.tools.AbstractTest; import com.questdb.test.tools.TestUtils; @@ -2084,21 +2085,21 @@ public void testParamInLimit() throws Exception { sink.clear(); RecordSource src = compiler.compileSource(factory, "select id, z from tab limit :xyz"); src.getParam(":xyz").set(10L); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); TestUtils.assertEquals(expected, sink); // and one more time sink.clear(); src = compiler.compileSource(factory, "select id, z from tab limit :xyz"); src.getParam(":xyz").set(10L); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); TestUtils.assertEquals(expected, sink); // and now change parameter sink.clear(); src = compiler.compileSource(factory, "select id, z from tab limit :xyz"); src.getParam(":xyz").set(5L); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); final String expected2 = "YDVRVNGSTEQODRZ\t-99\n" + "RIIYMHOWKCDNZNL\t-397\n" + @@ -2127,14 +2128,14 @@ public void testParamInQuery() throws Exception { RecordSource src = compiler.compileSource(factory, "select id, z from tab where z > :min limit :lim"); src.getParam(":min").set(450); src.getParam(":lim").set(10L); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); sink.clear(); src = compiler.compileSource(factory, "select id, z from tab where :min < z limit :lim"); src.getParam(":min").set(450); src.getParam(":lim").set(10L); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); TestUtils.assertEquals(expected, sink); } @@ -2151,7 +2152,7 @@ public void testParamNotSet() throws Exception { createTabWithNaNs2(); sink.clear(); RecordSource src = compiler.compileSource(factory, "select id, z from tab where z > :min limit :lim"); - printer.printCursor(src.prepareCursor(factory), false); + printer.printCursor(src.prepareCursor(factory, NoOpCancellationHandler.INSTANCE), false); } @Test