/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.addthis.hydra.query.aggregate; import javax.annotation.Nullable; import java.io.IOException; import com.addthis.bundle.channel.DataChannelError; import com.addthis.bundle.core.Bundle; public class QueryTaskSource { protected final QueryTaskSourceOption[] options; protected int lines = 0; protected long endTime = 0; protected TaskChannelReader dataChannelReader; public QueryTaskSource(QueryTaskSourceOption[] options) { this.options = options; } public boolean oneHasResponded() { return dataChannelReader != null; } public boolean complete() { if (options.length == 0) { return true; } if (endTime > 0) { return true; } if (oneHasResponded() && dataChannelReader.isClosed()) { eagerComplete(); return true; } return false; } private void eagerComplete() { endTime = System.currentTimeMillis(); // eagerly free up resources that are no longer needed -- especially any worker leases cancelAllActiveOptions("task is already complete"); } public Bundle next() throws IOException, DataChannelError, InterruptedException { if (dataChannelReader == null) { if (!checkForReadyOption()) { return null; } } Bundle bundle = dataChannelReader.read(); if (bundle != null) { lines++; } else if (dataChannelReader.isClosed()) { eagerComplete(); } return bundle; } /** Whether this task has any currently active sources. This may be false either if no option was ever * activated or if this task is complete. */ public boolean hasNoActiveSources() { for (QueryTaskSourceOption option : options) { if (option.isActive()) { return false; } } return true; } public void cancelAllActiveOptions(String message) { for (QueryTaskSourceOption option : options) { if (option.isActive()) { option.cancel(message); } } } public QueryTaskSourceOption getSelectedSource() { if (oneHasResponded()) { return dataChannelReader.sourceOption; } return null; } public void reset() { cancelAllActiveOptions("resetting task source"); lines = 0; dataChannelReader = null; } private void createReader(QueryTaskSourceOption readySourceOption) { dataChannelReader = new TaskChannelReader(readySourceOption); } @Nullable private QueryTaskSourceOption getReadyOption() { for (QueryTaskSourceOption option : options) { if (option.isReady()) { return option; } } return null; } private void cancelOtherActiveOptions(QueryTaskSourceOption selectedOption) { for (QueryTaskSourceOption option : options) { if ((option != selectedOption) && option.isActive()) { option.cancel("Another source option responded first"); } } } private boolean checkForReadyOption() { QueryTaskSourceOption readyOption = getReadyOption(); if (readyOption != null) { cancelOtherActiveOptions(readyOption); createReader(readyOption); return true; } return false; } }