/* * Copyright 2012 NGDATA nv * * 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.lilyproject.repository.api; import org.lilyproject.repository.api.filter.RecordFilter; /** * Defines the parameters of a scan to be performed over the records. * * <p>See {@link Repository#getScanner(RecordScan)}.</p> */ public class RecordScan { private RecordId startRecordId; private RecordId stopRecordId; private byte[] rawStartRecordId; private byte[] rawStopRecordId; private RecordFilter recordFilter; private ReturnFields returnFields; private int caching = -1; private boolean cacheBlocks = true; /** * @see #setStartRecordId(RecordId) */ public RecordId getStartRecordId() { return startRecordId; } /** * Sets the record ID where the scan should start. * * <p>If you don't set the start record ID, the scan will start at the very * first record. If you don't set a stop record ID either, then scan will * run until the last record. In such case, you are doing a full table scan. * Some filters (see {@link #setRecordFilter(RecordFilter)} are * also able to stop the scan early when certain conditions are reached, * see for example the {@link org.lilyproject.repository.api.filter.RecordIdPrefixFilter}.</p> * * <p>The start record ID does not have to be an existing record ID, the scan will * start from the first record which has a record ID greater than or equal to * this ID.</p> * * <p>It makes little sense to use this with UUID-based record ID's, except * if you would like to read all variants of a record. See also * {@link Repository#getVariants(RecordId)}, which only gives the ID's of the * variant records.</p> * * <p>To scan all rows starting with a common prefix, use the * {@link org.lilyproject.repository.api.filter.RecordIdPrefixFilter}</p> * * @param startRecordId record id to start on, inclusive * @see #setStopRecordId(RecordId) */ public void setStartRecordId(RecordId startRecordId) { this.startRecordId = startRecordId; } /** * @see #setStopRecordId(RecordId) */ public RecordId getStopRecordId() { return stopRecordId; } /** * Sets the record ID before which the scan should stop. * * <p>For more information, see {@link #setStartRecordId(RecordId)}.</p> * * @param stopRecordId record ID to stop on, exclusive (scan stops at last entry before this ID) */ public void setStopRecordId(RecordId stopRecordId) { this.stopRecordId = stopRecordId; } /** * <b>EXPERT ONLY!</b> * * @see #setRawStartRecordId(byte[]) */ public byte[] getRawStartRecordId() { return rawStartRecordId; } /** * <b>EXPERT ONLY!</b> Sets the start record ID as bytes. * * <p>If this is set, it takes precedence over {@link #setStartRecordId(RecordId)}.</p> * * <p>One case where this is used is for the MapReduce integration: the scans there * start/stop at the boundaries of a region, which can be defined as some * arbitrary byte sequence which is not necessarily a valid Lily record ID.</p> * * @see #setStartRecordId(RecordId) */ public void setRawStartRecordId(byte[] rawStartRecordId) { this.rawStartRecordId = rawStartRecordId; } /** * <b>EXPERT ONLY!</b> * * @see #setRawStopRecordId(byte[]) */ public byte[] getRawStopRecordId() { return rawStopRecordId; } /** * <b>EXPERT ONLY!</b> Sets the stop record ID as bytes. * * <p>If this is set, it takes precedence over {@link #setStopRecordId(RecordId)}.</p> * * @see #setStopRecordId(RecordId) */ public void setRawStopRecordId(byte[] rawStopRecordId) { this.rawStopRecordId = rawStopRecordId; } /** * @see #setRecordFilter(RecordFilter) */ public RecordFilter getRecordFilter() { return recordFilter; } /** * Sets a record filter. A record filter filters records server-side, without ever * returning them to the client. * * <p>There are various filter implementations available, check out the implementations * of {@link RecordFilter}.</p> * * <p>Note that filters do not work index-based: the scan will still run over every * record, evaluate the filter, and then decide to return the record or not.</p> * * <p>Multiple filters can be combined using * {@link org.lilyproject.repository.api.filter.RecordFilterList}.</p> */ public void setRecordFilter(RecordFilter recordFilter) { this.recordFilter = recordFilter; } /** * @see #setReturnFields(ReturnFields) */ public ReturnFields getReturnFields() { return returnFields; } /** * Sets the fields to return for each record. * * <p>By default, all fields of a record are returned. Limiting this to return only * the fields of interest can seriously speed up scan operations.</p> * * <p>You can either set {@link ReturnFields#ALL} and {@link ReturnFields#NONE} (if * you are only interested in record id and/or type), or a manual enumeration of * fields.</p> */ public void setReturnFields(ReturnFields returnFields) { this.returnFields = returnFields; } /** * @see #setCaching(int) */ public int getCaching() { return caching; } /** * Sets the number of records to be read in one go from the server. * * <p>By default caching is disabled, but it it is strongly recommended to enable it, * since otherwise each individual call to {@link RecordScanner#next()} will cause a * new request to be sent to the server.</p> */ public void setCaching(int caching) { this.caching = caching; } /** * @see #setCacheBlocks(boolean) */ public boolean getCacheBlocks() { return cacheBlocks; } /** * Enable or disable block caching. This sets whether the data loaded from disk by this scan * should be added to the server-side cache. By default this is true. It can be interesting * to disable this when you are doing a full table scan: otherwise this would in turn put * each loaded data block in the cache, possibly removing more frequently accessed data which * was already in there. */ public void setCacheBlocks(boolean cacheBlocks) { this.cacheBlocks = cacheBlocks; } }