Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 7662E200C2D for ; Sat, 18 Feb 2017 00:42:55 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 75026160B7E; Fri, 17 Feb 2017 23:42:55 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 18FBC160B6D for ; Sat, 18 Feb 2017 00:42:52 +0100 (CET) Received: (qmail 77103 invoked by uid 500); 17 Feb 2017 23:42:45 -0000 Mailing-List: contact commits-help@hbase.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@hbase.apache.org Delivered-To: mailing list commits@hbase.apache.org Received: (qmail 75051 invoked by uid 99); 17 Feb 2017 23:42:43 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 17 Feb 2017 23:42:43 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B4203E0082; Fri, 17 Feb 2017 23:42:43 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: stack@apache.org To: commits@hbase.apache.org Date: Fri, 17 Feb 2017 23:43:15 -0000 Message-Id: <31b0cd7d88cc4d68b6121bf4324ad5fe@git.apache.org> In-Reply-To: <1176559689b04079a4b2b0dbeb741878@git.apache.org> References: <1176559689b04079a4b2b0dbeb741878@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [33/52] [partial] hbase-site git commit: Published site at 7763dd6688254d37ad611f5d290db47c83cf93d3. archived-at: Fri, 17 Feb 2017 23:42:55 -0000 http://git-wip-us.apache.org/repos/asf/hbase-site/blob/ce958bce/apidocs/src-html/org/apache/hadoop/hbase/client/Result.html ---------------------------------------------------------------------- diff --git a/apidocs/src-html/org/apache/hadoop/hbase/client/Result.html b/apidocs/src-html/org/apache/hadoop/hbase/client/Result.html index c1efaa7..1a6b0c2 100644 --- a/apidocs/src-html/org/apache/hadoop/hbase/client/Result.html +++ b/apidocs/src-html/org/apache/hadoop/hbase/client/Result.html @@ -48,913 +48,927 @@ 040import org.apache.hadoop.hbase.KeyValueUtil; 041import org.apache.hadoop.hbase.classification.InterfaceAudience; 042import org.apache.hadoop.hbase.classification.InterfaceStability; -043import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; -044import org.apache.hadoop.hbase.util.Bytes; -045 -046/** -047 * Single row result of a {@link Get} or {@link Scan} query.<p> -048 * -049 * This class is <b>NOT THREAD SAFE</b>.<p> -050 * -051 * Convenience methods are available that return various {@link Map} -052 * structures and values directly.<p> -053 * -054 * To get a complete mapping of all cells in the Result, which can include -055 * multiple families and multiple versions, use {@link #getMap()}.<p> -056 * -057 * To get a mapping of each family to its columns (qualifiers and values), -058 * including only the latest version of each, use {@link #getNoVersionMap()}. -059 * -060 * To get a mapping of qualifiers to latest values for an individual family use -061 * {@link #getFamilyMap(byte[])}.<p> -062 * -063 * To get the latest value for a specific family and qualifier use -064 * {@link #getValue(byte[], byte[])}. -065 * -066 * A Result is backed by an array of {@link Cell} objects, each representing -067 * an HBase cell defined by the row, family, qualifier, timestamp, and value.<p> -068 * -069 * The underlying {@link Cell} objects can be accessed through the method {@link #listCells()}. -070 * This will create a List from the internal Cell []. Better is to exploit the fact that -071 * a new Result instance is a primed {@link CellScanner}; just call {@link #advance()} and -072 * {@link #current()} to iterate over Cells as you would any {@link CellScanner}. -073 * Call {@link #cellScanner()} to reset should you need to iterate the same Result over again -074 * ({@link CellScanner}s are one-shot). -075 * -076 * If you need to overwrite a Result with another Result instance -- as in the old 'mapred' -077 * RecordReader next invocations -- then create an empty Result with the null constructor and -078 * in then use {@link #copyFrom(Result)} -079 */ -080@InterfaceAudience.Public -081@InterfaceStability.Stable -082public class Result implements CellScannable, CellScanner { -083 private Cell[] cells; -084 private Boolean exists; // if the query was just to check existence. -085 private boolean stale = false; -086 -087 /** -088 * Partial results do not contain the full row's worth of cells. The result had to be returned in -089 * parts because the size of the cells in the row exceeded the RPC result size on the server. -090 * Partial results must be combined client side with results representing the remainder of the -091 * row's cells to form the complete result. Partial results and RPC result size allow us to avoid -092 * OOME on the server when servicing requests for large rows. The Scan configuration used to -093 * control the result size on the server is {@link Scan#setMaxResultSize(long)} and the default -094 * value can be seen here: {@link HConstants#DEFAULT_HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE} -095 */ -096 private boolean partial = false; -097 // We're not using java serialization. Transient here is just a marker to say -098 // that this is where we cache row if we're ever asked for it. -099 private transient byte [] row = null; -100 // Ditto for familyMap. It can be composed on fly from passed in kvs. -101 private transient NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> -102 familyMap = null; +043import org.apache.hadoop.hbase.util.Bytes; +044 +045/** +046 * Single row result of a {@link Get} or {@link Scan} query.<p> +047 * +048 * This class is <b>NOT THREAD SAFE</b>.<p> +049 * +050 * Convenience methods are available that return various {@link Map} +051 * structures and values directly.<p> +052 * +053 * To get a complete mapping of all cells in the Result, which can include +054 * multiple families and multiple versions, use {@link #getMap()}.<p> +055 * +056 * To get a mapping of each family to its columns (qualifiers and values), +057 * including only the latest version of each, use {@link #getNoVersionMap()}. +058 * +059 * To get a mapping of qualifiers to latest values for an individual family use +060 * {@link #getFamilyMap(byte[])}.<p> +061 * +062 * To get the latest value for a specific family and qualifier use +063 * {@link #getValue(byte[], byte[])}. +064 * +065 * A Result is backed by an array of {@link Cell} objects, each representing +066 * an HBase cell defined by the row, family, qualifier, timestamp, and value.<p> +067 * +068 * The underlying {@link Cell} objects can be accessed through the method {@link #listCells()}. +069 * This will create a List from the internal Cell []. Better is to exploit the fact that +070 * a new Result instance is a primed {@link CellScanner}; just call {@link #advance()} and +071 * {@link #current()} to iterate over Cells as you would any {@link CellScanner}. +072 * Call {@link #cellScanner()} to reset should you need to iterate the same Result over again +073 * ({@link CellScanner}s are one-shot). +074 * +075 * If you need to overwrite a Result with another Result instance -- as in the old 'mapred' +076 * RecordReader next invocations -- then create an empty Result with the null constructor and +077 * in then use {@link #copyFrom(Result)} +078 */ +079@InterfaceAudience.Public +080@InterfaceStability.Stable +081public class Result implements CellScannable, CellScanner { +082 private Cell[] cells; +083 private Boolean exists; // if the query was just to check existence. +084 private boolean stale = false; +085 +086 /** +087 * See {@link #mayHaveMoreCellsInRow()}. And please notice that, The client side implementation +088 * should also check for row key change to determine if a Result is the last one for a row. +089 */ +090 private boolean mayHaveMoreCellsInRow = false; +091 // We're not using java serialization. Transient here is just a marker to say +092 // that this is where we cache row if we're ever asked for it. +093 private transient byte [] row = null; +094 // Ditto for familyMap. It can be composed on fly from passed in kvs. +095 private transient NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> +096 familyMap = null; +097 +098 private static ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>(); +099 private static final int PAD_WIDTH = 128; +100 public static final Result EMPTY_RESULT = new Result(true); +101 +102 private final static int INITIAL_CELLSCANNER_INDEX = -1; 103 -104 private static ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>(); -105 private static final int PAD_WIDTH = 128; -106 public static final Result EMPTY_RESULT = new Result(true); -107 -108 private final static int INITIAL_CELLSCANNER_INDEX = -1; +104 /** +105 * Index for where we are when Result is acting as a {@link CellScanner}. +106 */ +107 private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX; +108 private RegionLoadStats stats; 109 -110 /** -111 * Index for where we are when Result is acting as a {@link CellScanner}. -112 */ -113 private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX; -114 private RegionLoadStats stats; -115 -116 private final boolean readonly; -117 -118 /** -119 * Creates an empty Result w/ no KeyValue payload; returns null if you call {@link #rawCells()}. -120 * Use this to represent no results if {@code null} won't do or in old 'mapred' as opposed -121 * to 'mapreduce' package MapReduce where you need to overwrite a Result instance with a -122 * {@link #copyFrom(Result)} call. -123 */ -124 public Result() { -125 this(false); -126 } -127 -128 /** -129 * Allows to construct special purpose immutable Result objects, -130 * such as EMPTY_RESULT. -131 * @param readonly whether this Result instance is readonly -132 */ -133 private Result(boolean readonly) { -134 this.readonly = readonly; -135 } -136 -137 /** -138 * Instantiate a Result with the specified List of KeyValues. -139 * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted. -140 * @param cells List of cells -141 */ -142 public static Result create(List<Cell> cells) { -143 return create(cells, null); -144 } -145 -146 public static Result create(List<Cell> cells, Boolean exists) { -147 return create(cells, exists, false); -148 } -149 -150 public static Result create(List<Cell> cells, Boolean exists, boolean stale) { -151 return create(cells, exists, stale, false); -152 } -153 -154 public static Result create(List<Cell> cells, Boolean exists, boolean stale, boolean partial) { -155 if (exists != null){ -156 return new Result(null, exists, stale, partial); -157 } -158 return new Result(cells.toArray(new Cell[cells.size()]), null, stale, partial); -159 } -160 -161 /** -162 * Instantiate a Result with the specified array of KeyValues. -163 * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted. -164 * @param cells array of cells -165 */ -166 public static Result create(Cell[] cells) { -167 return create(cells, null, false); -168 } -169 -170 public static Result create(Cell[] cells, Boolean exists, boolean stale) { -171 return create(cells, exists, stale, false); -172 } -173 -174 public static Result create(Cell[] cells, Boolean exists, boolean stale, boolean partial) { -175 if (exists != null){ -176 return new Result(null, exists, stale, partial); -177 } -178 return new Result(cells, null, stale, partial); -179 } -180 -181 /** Private ctor. Use {@link #create(Cell[])}. */ -182 private Result(Cell[] cells, Boolean exists, boolean stale, boolean partial) { -183 this.cells = cells; -184 this.exists = exists; -185 this.stale = stale; -186 this.partial = partial; -187 this.readonly = false; -188 } -189 -190 /** -191 * Method for retrieving the row key that corresponds to -192 * the row from which this Result was created. -193 * @return row -194 */ -195 public byte [] getRow() { -196 if (this.row == null) { -197 this.row = (this.cells == null || this.cells.length == 0) ? -198 null : -199 CellUtil.cloneRow(this.cells[0]); -200 } -201 return this.row; -202 } -203 -204 /** -205 * Return the array of Cells backing this Result instance. -206 * -207 * The array is sorted from smallest -&gt; largest using the -208 * {@link CellComparator#COMPARATOR}. -209 * -210 * The array only contains what your Get or Scan specifies and no more. -211 * For example if you request column "A" 1 version you will have at most 1 -212 * Cell in the array. If you request column "A" with 2 version you will -213 * have at most 2 Cells, with the first one being the newer timestamp and -214 * the second being the older timestamp (this is the sort order defined by -215 * {@link CellComparator#COMPARATOR}). If columns don't exist, they won't be -216 * present in the result. Therefore if you ask for 1 version all columns, -217 * it is safe to iterate over this array and expect to see 1 Cell for -218 * each column and no more. -219 * -220 * This API is faster than using getFamilyMap() and getMap() -221 * -222 * @return array of Cells; can be null if nothing in the result -223 */ -224 public Cell[] rawCells() { -225 return cells; -226 } -227 -228 /** -229 * Create a sorted list of the Cell's in this result. -230 * -231 * Since HBase 0.20.5 this is equivalent to raw(). -232 * -233 * @return sorted List of Cells; can be null if no cells in the result -234 */ -235 public List<Cell> listCells() { -236 return isEmpty()? null: Arrays.asList(rawCells()); -237 } -238 -239 /** -240 * Return the Cells for the specific column. The Cells are sorted in -241 * the {@link CellComparator#COMPARATOR} order. That implies the first entry in -242 * the list is the most recent column. If the query (Scan or Get) only -243 * requested 1 version the list will contain at most 1 entry. If the column -244 * did not exist in the result set (either the column does not exist -245 * or the column was not selected in the query) the list will be empty. -246 * -247 * Also see getColumnLatest which returns just a Cell -248 * -249 * @param family the family -250 * @param qualifier -251 * @return a list of Cells for this column or empty list if the column -252 * did not exist in the result set -253 */ -254 public List<Cell> getColumnCells(byte [] family, byte [] qualifier) { -255 List<Cell> result = new ArrayList<Cell>(); -256 -257 Cell [] kvs = rawCells(); -258 -259 if (kvs == null || kvs.length == 0) { -260 return result; -261 } -262 int pos = binarySearch(kvs, family, qualifier); -263 if (pos == -1) { -264 return result; // cant find it -265 } -266 -267 for (int i = pos; i < kvs.length; i++) { -268 if (CellUtil.matchingColumn(kvs[i], family,qualifier)) { -269 result.add(kvs[i]); -270 } else { -271 break; -272 } -273 } -274 -275 return result; -276 } -277 -278 private byte[] notNullBytes(final byte[] bytes) { -279 if (bytes == null) { -280 return HConstants.EMPTY_BYTE_ARRAY; -281 } else { -282 return bytes; -283 } -284 } -285 -286 protected int binarySearch(final Cell [] kvs, -287 final byte [] family, -288 final byte [] qualifier) { -289 byte[] familyNotNull = notNullBytes(family); -290 byte[] qualifierNotNull = notNullBytes(qualifier); -291 Cell searchTerm = -292 CellUtil.createFirstOnRow(kvs[0].getRowArray(), -293 kvs[0].getRowOffset(), kvs[0].getRowLength(), -294 familyNotNull, 0, (byte)familyNotNull.length, -295 qualifierNotNull, 0, qualifierNotNull.length); -296 -297 // pos === ( -(insertion point) - 1) -298 int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR); -299 // never will exact match -300 if (pos < 0) { -301 pos = (pos+1) * -1; -302 // pos is now insertion point -303 } -304 if (pos == kvs.length) { -305 return -1; // doesn't exist -306 } -307 return pos; -308 } -309 -310 /** -311 * Searches for the latest value for the specified column. -312 * -313 * @param kvs the array to search -314 * @param family family name -315 * @param foffset family offset -316 * @param flength family length -317 * @param qualifier column qualifier -318 * @param qoffset qualifier offset -319 * @param qlength qualifier length -320 * -321 * @return the index where the value was found, or -1 otherwise -322 */ -323 protected int binarySearch(final Cell [] kvs, -324 final byte [] family, final int foffset, final int flength, -325 final byte [] qualifier, final int qoffset, final int qlength) { -326 -327 double keyValueSize = (double) -328 KeyValue.getKeyValueDataStructureSize(kvs[0].getRowLength(), flength, qlength, 0); -329 -330 byte[] buffer = localBuffer.get(); -331 if (buffer == null || keyValueSize > buffer.length) { -332 // pad to the smallest multiple of the pad width -333 buffer = new byte[(int) Math.ceil(keyValueSize / PAD_WIDTH) * PAD_WIDTH]; -334 localBuffer.set(buffer); -335 } +110 private final boolean readonly; +111 +112 /** +113 * Creates an empty Result w/ no KeyValue payload; returns null if you call {@link #rawCells()}. +114 * Use this to represent no results if {@code null} won't do or in old 'mapred' as opposed +115 * to 'mapreduce' package MapReduce where you need to overwrite a Result instance with a +116 * {@link #copyFrom(Result)} call. +117 */ +118 public Result() { +119 this(false); +120 } +121 +122 /** +123 * Allows to construct special purpose immutable Result objects, +124 * such as EMPTY_RESULT. +125 * @param readonly whether this Result instance is readonly +126 */ +127 private Result(boolean readonly) { +128 this.readonly = readonly; +129 } +130 +131 /** +132 * Instantiate a Result with the specified List of KeyValues. +133 * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted. +134 * @param cells List of cells +135 */ +136 public static Result create(List<Cell> cells) { +137 return create(cells, null); +138 } +139 +140 public static Result create(List<Cell> cells, Boolean exists) { +141 return create(cells, exists, false); +142 } +143 +144 public static Result create(List<Cell> cells, Boolean exists, boolean stale) { +145 return create(cells, exists, stale, false); +146 } +147 +148 public static Result create(List<Cell> cells, Boolean exists, boolean stale, boolean partial) { +149 if (exists != null){ +150 return new Result(null, exists, stale, partial); +151 } +152 return new Result(cells.toArray(new Cell[cells.size()]), null, stale, partial); +153 } +154 +155 /** +156 * Instantiate a Result with the specified array of KeyValues. +157 * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted. +158 * @param cells array of cells +159 */ +160 public static Result create(Cell[] cells) { +161 return create(cells, null, false); +162 } +163 +164 public static Result create(Cell[] cells, Boolean exists, boolean stale) { +165 return create(cells, exists, stale, false); +166 } +167 +168 public static Result create(Cell[] cells, Boolean exists, boolean stale, +169 boolean mayHaveMoreCellsInRow) { +170 if (exists != null) { +171 return new Result(null, exists, stale, mayHaveMoreCellsInRow); +172 } +173 return new Result(cells, null, stale, mayHaveMoreCellsInRow); +174 } +175 +176 /** Private ctor. Use {@link #create(Cell[])}. */ +177 private Result(Cell[] cells, Boolean exists, boolean stale, boolean mayHaveMoreCellsInRow) { +178 this.cells = cells; +179 this.exists = exists; +180 this.stale = stale; +181 this.mayHaveMoreCellsInRow = mayHaveMoreCellsInRow; +182 this.readonly = false; +183 } +184 +185 /** +186 * Method for retrieving the row key that corresponds to +187 * the row from which this Result was created. +188 * @return row +189 */ +190 public byte [] getRow() { +191 if (this.row == null) { +192 this.row = (this.cells == null || this.cells.length == 0) ? +193 null : +194 CellUtil.cloneRow(this.cells[0]); +195 } +196 return this.row; +197 } +198 +199 /** +200 * Return the array of Cells backing this Result instance. +201 * +202 * The array is sorted from smallest -&gt; largest using the +203 * {@link CellComparator#COMPARATOR}. +204 * +205 * The array only contains what your Get or Scan specifies and no more. +206 * For example if you request column "A" 1 version you will have at most 1 +207 * Cell in the array. If you request column "A" with 2 version you will +208 * have at most 2 Cells, with the first one being the newer timestamp and +209 * the second being the older timestamp (this is the sort order defined by +210 * {@link CellComparator#COMPARATOR}). If columns don't exist, they won't be +211 * present in the result. Therefore if you ask for 1 version all columns, +212 * it is safe to iterate over this array and expect to see 1 Cell for +213 * each column and no more. +214 * +215 * This API is faster than using getFamilyMap() and getMap() +216 * +217 * @return array of Cells; can be null if nothing in the result +218 */ +219 public Cell[] rawCells() { +220 return cells; +221 } +222 +223 /** +224 * Create a sorted list of the Cell's in this result. +225 * +226 * Since HBase 0.20.5 this is equivalent to raw(). +227 * +228 * @return sorted List of Cells; can be null if no cells in the result +229 */ +230 public List<Cell> listCells() { +231 return isEmpty()? null: Arrays.asList(rawCells()); +232 } +233 +234 /** +235 * Return the Cells for the specific column. The Cells are sorted in +236 * the {@link CellComparator#COMPARATOR} order. That implies the first entry in +237 * the list is the most recent column. If the query (Scan or Get) only +238 * requested 1 version the list will contain at most 1 entry. If the column +239 * did not exist in the result set (either the column does not exist +240 * or the column was not selected in the query) the list will be empty. +241 * +242 * Also see getColumnLatest which returns just a Cell +243 * +244 * @param family the family +245 * @param qualifier +246 * @return a list of Cells for this column or empty list if the column +247 * did not exist in the result set +248 */ +249 public List<Cell> getColumnCells(byte [] family, byte [] qualifier) { +250 List<Cell> result = new ArrayList<Cell>(); +251 +252 Cell [] kvs = rawCells(); +253 +254 if (kvs == null || kvs.length == 0) { +255 return result; +256 } +257 int pos = binarySearch(kvs, family, qualifier); +258 if (pos == -1) { +259 return result; // cant find it +260 } +261 +262 for (int i = pos; i < kvs.length; i++) { +263 if (CellUtil.matchingColumn(kvs[i], family,qualifier)) { +264 result.add(kvs[i]); +265 } else { +266 break; +267 } +268 } +269 +270 return result; +271 } +272 +273 private byte[] notNullBytes(final byte[] bytes) { +274 if (bytes == null) { +275 return HConstants.EMPTY_BYTE_ARRAY; +276 } else { +277 return bytes; +278 } +279 } +280 +281 protected int binarySearch(final Cell [] kvs, +282 final byte [] family, +283 final byte [] qualifier) { +284 byte[] familyNotNull = notNullBytes(family); +285 byte[] qualifierNotNull = notNullBytes(qualifier); +286 Cell searchTerm = +287 CellUtil.createFirstOnRow(kvs[0].getRowArray(), +288 kvs[0].getRowOffset(), kvs[0].getRowLength(), +289 familyNotNull, 0, (byte)familyNotNull.length, +290 qualifierNotNull, 0, qualifierNotNull.length); +291 +292 // pos === ( -(insertion point) - 1) +293 int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR); +294 // never will exact match +295 if (pos < 0) { +296 pos = (pos+1) * -1; +297 // pos is now insertion point +298 } +299 if (pos == kvs.length) { +300 return -1; // doesn't exist +301 } +302 return pos; +303 } +304 +305 /** +306 * Searches for the latest value for the specified column. +307 * +308 * @param kvs the array to search +309 * @param family family name +310 * @param foffset family offset +311 * @param flength family length +312 * @param qualifier column qualifier +313 * @param qoffset qualifier offset +314 * @param qlength qualifier length +315 * +316 * @return the index where the value was found, or -1 otherwise +317 */ +318 protected int binarySearch(final Cell [] kvs, +319 final byte [] family, final int foffset, final int flength, +320 final byte [] qualifier, final int qoffset, final int qlength) { +321 +322 double keyValueSize = (double) +323 KeyValue.getKeyValueDataStructureSize(kvs[0].getRowLength(), flength, qlength, 0); +324 +325 byte[] buffer = localBuffer.get(); +326 if (buffer == null || keyValueSize > buffer.length) { +327 // pad to the smallest multiple of the pad width +328 buffer = new byte[(int) Math.ceil(keyValueSize / PAD_WIDTH) * PAD_WIDTH]; +329 localBuffer.set(buffer); +330 } +331 +332 Cell searchTerm = KeyValueUtil.createFirstOnRow(buffer, 0, +333 kvs[0].getRowArray(), kvs[0].getRowOffset(), kvs[0].getRowLength(), +334 family, foffset, flength, +335 qualifier, qoffset, qlength); 336 -337 Cell searchTerm = KeyValueUtil.createFirstOnRow(buffer, 0, -338 kvs[0].getRowArray(), kvs[0].getRowOffset(), kvs[0].getRowLength(), -339 family, foffset, flength, -340 qualifier, qoffset, qlength); -341 -342 // pos === ( -(insertion point) - 1) -343 int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR); -344 // never will exact match -345 if (pos < 0) { -346 pos = (pos+1) * -1; -347 // pos is now insertion point -348 } -349 if (pos == kvs.length) { -350 return -1; // doesn't exist -351 } -352 return pos; -353 } -354 -355 /** -356 * The Cell for the most recent timestamp for a given column. -357 * -358 * @param family -359 * @param qualifier -360 * -361 * @return the Cell for the column, or null if no value exists in the row or none have been -362 * selected in the query (Get/Scan) -363 */ -364 public Cell getColumnLatestCell(byte [] family, byte [] qualifier) { -365 Cell [] kvs = rawCells(); // side effect possibly. -366 if (kvs == null || kvs.length == 0) { -367 return null; -368 } -369 int pos = binarySearch(kvs, family, qualifier); -370 if (pos == -1) { -371 return null; -372 } -373 if (CellUtil.matchingColumn(kvs[pos], family, qualifier)) { -374 return kvs[pos]; -375 } -376 return null; -377 } -378 -379 /** -380 * The Cell for the most recent timestamp for a given column. -381 * -382 * @param family family name -383 * @param foffset family offset -384 * @param flength family length -385 * @param qualifier column qualifier -386 * @param qoffset qualifier offset -387 * @param qlength qualifier length -388 * -389 * @return the Cell for the column, or null if no value exists in the row or none have been -390 * selected in the query (Get/Scan) -391 */ -392 public Cell getColumnLatestCell(byte [] family, int foffset, int flength, -393 byte [] qualifier, int qoffset, int qlength) { -394 -395 Cell [] kvs = rawCells(); // side effect possibly. -396 if (kvs == null || kvs.length == 0) { -397 return null; -398 } -399 int pos = binarySearch(kvs, family, foffset, flength, qualifier, qoffset, qlength); -400 if (pos == -1) { -401 return null; -402 } -403 if (CellUtil.matchingColumn(kvs[pos], family, foffset, flength, qualifier, qoffset, qlength)) { -404 return kvs[pos]; -405 } -406 return null; -407 } -408 -409 /** -410 * Get the latest version of the specified column. -411 * Note: this call clones the value content of the hosting Cell. See -412 * {@link #getValueAsByteBuffer(byte[], byte[])}, etc., or {@link #listCells()} if you would -413 * avoid the cloning. -414 * @param family family name -415 * @param qualifier column qualifier -416 * @return value of latest version of column, null if none found -417 */ -418 public byte[] getValue(byte [] family, byte [] qualifier) { -419 Cell kv = getColumnLatestCell(family, qualifier); -420 if (kv == null) { -421 return null; -422 } -423 return CellUtil.cloneValue(kv); -424 } -425 -426 /** -427 * Returns the value wrapped in a new <code>ByteBuffer</code>. -428 * -429 * @param family family name -430 * @param qualifier column qualifier -431 * -432 * @return the latest version of the column, or <code>null</code> if none found -433 */ -434 public ByteBuffer getValueAsByteBuffer(byte [] family, byte [] qualifier) { -435 -436 Cell kv = getColumnLatestCell(family, 0, family.length, qualifier, 0, qualifier.length); -437 -438 if (kv == null) { -439 return null; -440 } -441 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()). -442 asReadOnlyBuffer(); -443 } -444 -445 /** -446 * Returns the value wrapped in a new <code>ByteBuffer</code>. -447 * -448 * @param family family name -449 * @param foffset family offset -450 * @param flength family length -451 * @param qualifier column qualifier -452 * @param qoffset qualifier offset -453 * @param qlength qualifier length -454 * -455 * @return the latest version of the column, or <code>null</code> if none found -456 */ -457 public ByteBuffer getValueAsByteBuffer(byte [] family, int foffset, int flength, -458 byte [] qualifier, int qoffset, int qlength) { -459 -460 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength); -461 -462 if (kv == null) { -463 return null; -464 } -465 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()). -466 asReadOnlyBuffer(); -467 } -468 -469 /** -470 * Loads the latest version of the specified column into the provided <code>ByteBuffer</code>. -471 * <p> -472 * Does not clear or flip the buffer. -473 * -474 * @param family family name -475 * @param qualifier column qualifier -476 * @param dst the buffer where to write the value -477 * -478 * @return <code>true</code> if a value was found, <code>false</code> otherwise -479 * -480 * @throws BufferOverflowException there is insufficient space remaining in the buffer -481 */ -482 public boolean loadValue(byte [] family, byte [] qualifier, ByteBuffer dst) -483 throws BufferOverflowException { -484 return loadValue(family, 0, family.length, qualifier, 0, qualifier.length, dst); -485 } -486 -487 /** -488 * Loads the latest version of the specified column into the provided <code>ByteBuffer</code>. -489 * <p> -490 * Does not clear or flip the buffer. -491 * -492 * @param family family name -493 * @param foffset family offset -494 * @param flength family length -495 * @param qualifier column qualifier -496 * @param qoffset qualifier offset -497 * @param qlength qualifier length -498 * @param dst the buffer where to write the value -499 * -500 * @return <code>true</code> if a value was found, <code>false</code> otherwise -501 * -502 * @throws BufferOverflowException there is insufficient space remaining in the buffer -503 */ -504 public boolean loadValue(byte [] family, int foffset, int flength, -505 byte [] qualifier, int qoffset, int qlength, ByteBuffer dst) -506 throws BufferOverflowException { -507 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength); -508 -509 if (kv == null) { -510 return false; -511 } -512 dst.put(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()); -513 return true; -514 } -515 -516 /** -517 * Checks if the specified column contains a non-empty value (not a zero-length byte array). -518 * -519 * @param family family name -520 * @param qualifier column qualifier -521 * -522 * @return whether or not a latest value exists and is not empty -523 */ -524 public boolean containsNonEmptyColumn(byte [] family, byte [] qualifier) { -525 -526 return containsNonEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length); -527 } -528 -529 /** -530 * Checks if the specified column contains a non-empty value (not a zero-length byte array). -531 * -532 * @param family family name -533 * @param foffset family offset -534 * @param flength family length -535 * @param qualifier column qualifier -536 * @param qoffset qualifier offset -537 * @param qlength qualifier length -538 * -539 * @return whether or not a latest value exists and is not empty -540 */ -541 public boolean containsNonEmptyColumn(byte [] family, int foffset, int flength, -542 byte [] qualifier, int qoffset, int qlength) { +337 // pos === ( -(insertion point) - 1) +338 int pos = Arrays.binarySearch(kvs, searchTerm, CellComparator.COMPARATOR); +339 // never will exact match +340 if (pos < 0) { +341 pos = (pos+1) * -1; +342 // pos is now insertion point +343 } +344 if (pos == kvs.length) { +345 return -1; // doesn't exist +346 } +347 return pos; +348 } +349 +350 /** +351 * The Cell for the most recent timestamp for a given column. +352 * +353 * @param family +354 * @param qualifier +355 * +356 * @return the Cell for the column, or null if no value exists in the row or none have been +357 * selected in the query (Get/Scan) +358 */ +359 public Cell getColumnLatestCell(byte [] family, byte [] qualifier) { +360 Cell [] kvs = rawCells(); // side effect possibly. +361 if (kvs == null || kvs.length == 0) { +362 return null; +363 } +364 int pos = binarySearch(kvs, family, qualifier); +365 if (pos == -1) { +366 return null; +367 } +368 if (CellUtil.matchingColumn(kvs[pos], family, qualifier)) { +369 return kvs[pos]; +370 } +371 return null; +372 } +373 +374 /** +375 * The Cell for the most recent timestamp for a given column. +376 * +377 * @param family family name +378 * @param foffset family offset +379 * @param flength family length +380 * @param qualifier column qualifier +381 * @param qoffset qualifier offset +382 * @param qlength qualifier length +383 * +384 * @return the Cell for the column, or null if no value exists in the row or none have been +385 * selected in the query (Get/Scan) +386 */ +387 public Cell getColumnLatestCell(byte [] family, int foffset, int flength, +388 byte [] qualifier, int qoffset, int qlength) { +389 +390 Cell [] kvs = rawCells(); // side effect possibly. +391 if (kvs == null || kvs.length == 0) { +392 return null; +393 } +394 int pos = binarySearch(kvs, family, foffset, flength, qualifier, qoffset, qlength); +395 if (pos == -1) { +396 return null; +397 } +398 if (CellUtil.matchingColumn(kvs[pos], family, foffset, flength, qualifier, qoffset, qlength)) { +399 return kvs[pos]; +400 } +401 return null; +402 } +403 +404 /** +405 * Get the latest version of the specified column. +406 * Note: this call clones the value content of the hosting Cell. See +407 * {@link #getValueAsByteBuffer(byte[], byte[])}, etc., or {@link #listCells()} if you would +408 * avoid the cloning. +409 * @param family family name +410 * @param qualifier column qualifier +411 * @return value of latest version of column, null if none found +412 */ +413 public byte[] getValue(byte [] family, byte [] qualifier) { +414 Cell kv = getColumnLatestCell(family, qualifier); +415 if (kv == null) { +416 return null; +417 } +418 return CellUtil.cloneValue(kv); +419 } +420 +421 /** +422 * Returns the value wrapped in a new <code>ByteBuffer</code>. +423 * +424 * @param family family name +425 * @param qualifier column qualifier +426 * +427 * @return the latest version of the column, or <code>null</code> if none found +428 */ +429 public ByteBuffer getValueAsByteBuffer(byte [] family, byte [] qualifier) { +430 +431 Cell kv = getColumnLatestCell(family, 0, family.length, qualifier, 0, qualifier.length); +432 +433 if (kv == null) { +434 return null; +435 } +436 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()). +437 asReadOnlyBuffer(); +438 } +439 +440 /** +441 * Returns the value wrapped in a new <code>ByteBuffer</code>. +442 * +443 * @param family family name +444 * @param foffset family offset +445 * @param flength family length +446 * @param qualifier column qualifier +447 * @param qoffset qualifier offset +448 * @param qlength qualifier length +449 * +450 * @return the latest version of the column, or <code>null</code> if none found +451 */ +452 public ByteBuffer getValueAsByteBuffer(byte [] family, int foffset, int flength, +453 byte [] qualifier, int qoffset, int qlength) { +454 +455 Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength); +456 +457 if (kv == null) { +458 return null; +459 } +460 return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()). +461 asReadOnlyBuffer(); +462 } +463 +464 /** +465 * Loads the latest version of the specified column into the provided