/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.jena.tdb.base.recordbuffer; import static org.apache.jena.atlas.lib.Alg.decodeIndex ; import java.util.Iterator; import java.util.NoSuchElementException; import org.apache.jena.atlas.lib.Closeable ; import org.apache.jena.tdb.base.StorageException ; import org.apache.jena.tdb.base.block.BlockException ; import org.apache.jena.tdb.base.record.Record ; final public class RecordRangeIterator implements Iterator<Record>, Closeable { /** Iterate over a range of fromRec (inclusive) to toRec (exclusive) */ public static Iterator<Record> iterator(int pageId, Record fromRec, Record toRec, RecordBufferPageMgr pageMgr) { if ( ! pageMgr.valid(pageId) ) { String msg = "RecordRangeIterator.iterator -- No such block (pageId="+pageId+", fromRec="+fromRec+", toRec="+toRec+ ")" ; System.err.println(msg) ; System.exit(0) ; throw new BlockException(msg) ; } return new RecordRangeIterator(pageId, fromRec, toRec, pageMgr) ; } private RecordBufferPage currentPage ; // Set null when finished. private int currentIdx ; private Record slot = null ; private final RecordBufferPageMgr pageMgr ; private final Record maxRec ; private final Record minRec ; private long countRecords = 0 ; private long countBlocks = 0 ; private RecordRangeIterator(int id, Record fromRec, Record toRec, RecordBufferPageMgr pageMgr) { currentIdx = 0 ; this.pageMgr = pageMgr; this.minRec = fromRec ; this.maxRec = toRec ; if ( toRec != null && fromRec != null && Record.keyLE(toRec, fromRec) ) { currentPage = null ; return ; } pageMgr.getBlockMgr().beginIterator(this) ; currentPage = pageMgr.getReadIterator(id) ; if ( currentPage.getCount() == 0 ) { // Empty page. close() ; return ; } if ( fromRec != null ) { currentIdx = currentPage.getRecordBuffer().find(fromRec) ; if ( currentIdx < 0 ) currentIdx = decodeIndex(currentIdx) ; } } @Override public boolean hasNext() { if ( slot != null ) return true ; if ( currentPage == null ) return false ; // Set slot. while ( currentIdx >= currentPage.getCount() ) { // Move to next. int link = currentPage.getLink() ; if ( link < 0 ) { close() ; return false ; } if ( currentPage != null ) pageMgr.release(currentPage) ; RecordBufferPage nextPage = pageMgr.getReadIterator(link) ; // Check currentPage -> nextPage is strictly increasing keys. Record r1 = currentPage.getRecordBuffer().getHigh() ; Record r2 = nextPage.getRecordBuffer().getLow() ; if ( Record.keyGE(r1, r2) ) throw new StorageException("RecordRangeIterator: records not strictly increasing: "+r1+" // "+r2) ; currentPage = nextPage ; countBlocks++ ; currentIdx = 0 ; } slot = currentPage.getRecordBuffer().get(currentIdx) ; currentIdx++ ; if ( maxRec != null && Record.keyGE(slot, maxRec) ) { close() ; return false ; } if ( slot == null ) { close() ; return false ; } countRecords++ ; return true ; } @Override public void close() { if (currentPage != null ) pageMgr.release(currentPage) ; currentPage = null ; currentIdx = -99 ; slot = null ; pageMgr.getBlockMgr().endIterator(this) ; } @Override public Record next() { if ( ! hasNext() ) throw new NoSuchElementException() ; Record x = slot ; slot = null ; return x ; } @Override public void remove() { throw new UnsupportedOperationException("remove") ; } final public long getCountRecords() { return countRecords ; } final public long getCountBlocks() { return countBlocks ; } }