/* * Copyright 2013 Future Systems * * 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 org.krakenapps.logstorage.engine; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.NoSuchElementException; import org.krakenapps.logstorage.LogIndexCursor; import org.krakenapps.logstorage.LogIndexItem; import org.krakenapps.logstorage.LogIndexQuery; import org.krakenapps.logstorage.LogIndexer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @since 0.9 * @author xeraph */ class MergedIndexCursor implements LogIndexCursor { private final Logger logger = LoggerFactory.getLogger(MergedIndexCursor.class); private LogIndexer indexer; private LogIndexQuery query; private List<IndexCursorItem> items; private File indexBaseDir; /** * from 0 to (items.size - 1) */ private int currentIndex; private IndexCursorImpl currentCursor; public MergedIndexCursor(LogIndexer indexer, LogIndexQuery query, List<IndexCursorItem> items, File indexBaseDir) throws IOException { this.indexer = indexer; this.query = query; this.items = items; this.indexBaseDir = indexBaseDir; if (!items.isEmpty()) load(0); } private boolean loadNext() throws IOException { if (currentCursor != null) { currentCursor.close(); currentCursor = null; } if (currentIndex >= items.size() - 1) return false; load(++currentIndex); return true; } private void load(int index) throws IOException { IndexCursorItem item = items.get(index); List<Date> totalDays = indexer.getIndexedDays(item.tableName, item.indexName); // index can be dropped while iterating if (totalDays == null) throw new IOException("table [" + item.tableName + "] index [" + item.indexName + "] is dropped"); List<Date> filtered = DateUtil.filt(totalDays, query.getMinDay(), query.getMaxDay()); DateUtil.sortByDesc(filtered); currentCursor = new IndexCursorImpl(item.indexId, item.tableId, item.tableName, filtered, query.getTerm(), indexBaseDir, item.buffer.iterator()); } @Override public boolean hasNext() { if (currentIndex >= items.size()) return false; if (currentCursor == null) return false; if (currentCursor.hasNext()) return true; while (true) { try { boolean ret = loadNext(); if (!ret) return false; if (currentCursor.hasNext()) return true; } catch (IOException e) { logger.warn("kraken logstorage: cannot fetch next index from merged cursor, skipping", e); } } } @Override public LogIndexItem next() { if (!hasNext()) throw new NoSuchElementException(); return currentCursor.next(); } @Override public void remove() { throw new UnsupportedOperationException("not allowed action"); } @Override public void skip(long offset) { throw new UnsupportedOperationException("not implemented yet"); } @Override public void close() { if (currentCursor != null) currentCursor.close(); } }