View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.client;
21  
22  import java.io.IOException;
23  import java.nio.BufferOverflowException;
24  import java.nio.ByteBuffer;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Collections;
28  import java.util.Comparator;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.NavigableMap;
33  import java.util.NoSuchElementException;
34  import java.util.TreeMap;
35  
36  import org.apache.hadoop.hbase.Cell;
37  import org.apache.hadoop.hbase.CellScannable;
38  import org.apache.hadoop.hbase.CellScanner;
39  import org.apache.hadoop.hbase.CellUtil;
40  import org.apache.hadoop.hbase.KeyValue;
41  import org.apache.hadoop.hbase.KeyValueUtil;
42  import org.apache.hadoop.hbase.classification.InterfaceAudience;
43  import org.apache.hadoop.hbase.classification.InterfaceStability;
44  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
45  import org.apache.hadoop.hbase.util.Bytes;
46  
47  /**
48   * Single row result of a {@link Get} or {@link Scan} query.<p>
49   *
50   * This class is <b>NOT THREAD SAFE</b>.<p>
51   *
52   * Convenience methods are available that return various {@link Map}
53   * structures and values directly.<p>
54   *
55   * To get a complete mapping of all cells in the Result, which can include
56   * multiple families and multiple versions, use {@link #getMap()}.<p>
57   *
58   * To get a mapping of each family to its columns (qualifiers and values),
59   * including only the latest version of each, use {@link #getNoVersionMap()}.
60   *
61   * To get a mapping of qualifiers to latest values for an individual family use
62   * {@link #getFamilyMap(byte[])}.<p>
63   *
64   * To get the latest value for a specific family and qualifier use {@link #getValue(byte[], byte[])}.
65   *
66   * A Result is backed by an array of {@link Cell} objects, each representing
67   * an HBase cell defined by the row, family, qualifier, timestamp, and value.<p>
68   *
69   * The underlying {@link Cell} objects can be accessed through the method {@link #listCells()}.
70   * This will create a List from the internal Cell []. Better is to exploit the fact that
71   * a new Result instance is a primed {@link CellScanner}; just call {@link #advance()} and
72   * {@link #current()} to iterate over Cells as you would any {@link CellScanner}.
73   * Call {@link #cellScanner()} to reset should you need to iterate the same Result over again
74   * ({@link CellScanner}s are one-shot).
75   *
76   * If you need to overwrite a Result with another Result instance -- as in the old 'mapred'
77   * RecordReader next invocations -- then create an empty Result with the null constructor and
78   * in then use {@link #copyFrom(Result)}
79   */
80  @InterfaceAudience.Public
81  @InterfaceStability.Stable
82  public class Result implements CellScannable, CellScanner {
83    private Cell[] cells;
84    private Boolean exists; // if the query was just to check existence.
85    private boolean stale = false;
86  
87    /**
88     * See {@link #mayHaveMoreCellsInRow()}.
89     */
90    private boolean mayHaveMoreCellsInRow = false;
91    // We're not using java serialization.  Transient here is just a marker to say
92    // that this is where we cache row if we're ever asked for it.
93    private transient byte [] row = null;
94    // Ditto for familyMap.  It can be composed on fly from passed in kvs.
95    private transient NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> familyMap = null;
96  
97    private static ThreadLocal<byte[]> localBuffer = new ThreadLocal<byte[]>();
98    private static final int PAD_WIDTH = 128;
99    public static final Result EMPTY_RESULT = new Result(true);
100 
101   private final static int INITIAL_CELLSCANNER_INDEX = -1;
102 
103   /**
104    * Index for where we are when Result is acting as a {@link CellScanner}.
105    */
106   private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
107   private ClientProtos.RegionLoadStats stats;
108 
109   private final boolean readonly;
110 
111   private Cursor cursor = null;
112 
113   /**
114    * Creates an empty Result w/ no KeyValue payload; returns null if you call {@link #rawCells()}.
115    * Use this to represent no results if <code>null</code> won't do or in old 'mapred' as oppposed to 'mapreduce' package
116    * MapReduce where you need to overwrite a Result
117    * instance with a {@link #copyFrom(Result)} call.
118    */
119   public Result() {
120     this(false);
121   }
122 
123   /**
124    * Allows to construct special purpose immutable Result objects,
125    * such as EMPTY_RESULT.
126    * @param readonly whether this Result instance is readonly
127    */
128   private Result(boolean readonly) {
129     this.readonly = readonly;
130   }
131 
132   /**
133    * @deprecated Use {@link #create(List)} instead.
134    */
135   @Deprecated
136   public Result(KeyValue [] cells) {
137     this(cells, null, false, false);
138   }
139 
140   /**
141    * @deprecated Use {@link #create(List)} instead.
142    */
143   @Deprecated
144   public Result(List<KeyValue> kvs) {
145     // TODO: Here we presume the passed in Cells are KVs.  One day this won't always be so.
146     this(kvs.toArray(new Cell[kvs.size()]), null, false, false);
147   }
148 
149   /**
150    * Instantiate a Result with the specified List of KeyValues.
151    * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted.
152    * @param cells List of cells
153    */
154   public static Result create(List<Cell> cells) {
155     return create(cells, null);
156   }
157 
158   public static Result create(List<Cell> cells, Boolean exists) {
159     return create(cells, exists, false);
160   }
161 
162   public static Result create(List<Cell> cells, Boolean exists, boolean stale) {
163     return create(cells, exists, stale, false);
164   }
165 
166   public static Result create(List<Cell> cells, Boolean exists, boolean stale, boolean partial) {
167     if (exists != null){
168       return new Result(null, exists, stale, partial);
169     }
170     return new Result(cells.toArray(new Cell[cells.size()]), null, stale, partial);
171   }
172 
173   /**
174    * Instantiate a Result with the specified array of KeyValues.
175    * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted.
176    * @param cells array of cells
177    */
178   public static Result create(Cell[] cells) {
179     return create(cells, null, false);
180   }
181 
182   public static Result create(Cell[] cells, Boolean exists, boolean stale) {
183     return create(cells, exists, stale, false);
184   }
185 
186   public static Result create(Cell[] cells, Boolean exists, boolean stale,
187       boolean mayHaveMoreCellsInRow) {
188     if (exists != null) {
189       return new Result(null, exists, stale, mayHaveMoreCellsInRow);
190     }
191     return new Result(cells, null, stale, mayHaveMoreCellsInRow);
192   }
193 
194   public static Result createCursorResult(Cursor cursor) {
195     return new Result(cursor);
196   }
197 
198   private Result(Cursor cursor) {
199     this.cursor = cursor;
200     this.readonly = false;
201   }
202 
203   /** Private ctor. Use {@link #create(Cell[])}. */
204   private Result(Cell[] cells, Boolean exists, boolean stale, boolean mayHaveMoreCellsInRow) {
205     this.cells = cells;
206     this.exists = exists;
207     this.stale = stale;
208     this.mayHaveMoreCellsInRow = mayHaveMoreCellsInRow;
209     this.readonly = false;
210   }
211 
212   /**
213    * Method for retrieving the row key that corresponds to
214    * the row from which this Result was created.
215    * @return row
216    */
217   public byte [] getRow() {
218     if (this.row == null) {
219       this.row = this.cells == null || this.cells.length == 0? null: CellUtil.cloneRow(this.cells[0]);
220     }
221     return this.row;
222   }
223 
224   /**
225    * Return the array of Cells backing this Result instance.
226    *
227    * The array is sorted from smallest -&gt; largest using the
228    * {@link KeyValue#COMPARATOR}.
229    *
230    * The array only contains what your Get or Scan specifies and no more.
231    * For example if you request column "A" 1 version you will have at most 1
232    * Cell in the array. If you request column "A" with 2 version you will
233    * have at most 2 Cells, with the first one being the newer timestamp and
234    * the second being the older timestamp (this is the sort order defined by
235    * {@link KeyValue#COMPARATOR}).  If columns don't exist, they won't be
236    * present in the result. Therefore if you ask for 1 version all columns,
237    * it is safe to iterate over this array and expect to see 1 Cell for
238    * each column and no more.
239    *
240    * This API is faster than using getFamilyMap() and getMap()
241    *
242    * @return array of Cells; can be null if nothing in the result
243    */
244   public Cell[] rawCells() {
245     return cells;
246   }
247 
248   /**
249    * Return an cells of a Result as an array of KeyValues
250    *
251    * WARNING do not use, expensive.  This does an arraycopy of the cell[]'s value.
252    *
253    * Added to ease transition from  0.94 -&gt; 0.96.
254    *
255    * @deprecated as of 0.96, use {@link #rawCells()}
256    * @return array of KeyValues, empty array if nothing in result.
257    */
258   @Deprecated
259   public KeyValue[] raw() {
260     KeyValue[] kvs = new KeyValue[cells.length];
261     for (int i = 0 ; i < kvs.length; i++) {
262       kvs[i] = KeyValueUtil.ensureKeyValue(cells[i]);
263     }
264     return kvs;
265   }
266 
267   /**
268    * Create a sorted list of the Cell's in this result.
269    *
270    * Since HBase 0.20.5 this is equivalent to raw().
271    *
272    * @return sorted List of Cells; can be null if no cells in the result
273    */
274   public List<Cell> listCells() {
275     return isEmpty()? null: Arrays.asList(rawCells());
276   }
277 
278   /**
279    * Return an cells of a Result as an array of KeyValues
280    *
281    * WARNING do not use, expensive.  This does  an arraycopy of the cell[]'s value.
282    *
283    * Added to ease transition from  0.94 -&gt; 0.96.
284    *
285    * @deprecated as of 0.96, use {@link #listCells()}
286    * @return all sorted List of KeyValues; can be null if no cells in the result
287    */
288   @Deprecated
289   public List<KeyValue> list() {
290     return isEmpty() ? null : Arrays.asList(raw());
291   }
292 
293   /**
294    * @deprecated Use {@link #getColumnCells(byte[], byte[])} instead.
295    */
296   @Deprecated
297   public List<KeyValue> getColumn(byte [] family, byte [] qualifier) {
298     return KeyValueUtil.ensureKeyValues(getColumnCells(family, qualifier));
299   }
300 
301   /**
302    * Return the Cells for the specific column.  The Cells are sorted in
303    * the {@link KeyValue#COMPARATOR} order.  That implies the first entry in
304    * the list is the most recent column.  If the query (Scan or Get) only
305    * requested 1 version the list will contain at most 1 entry.  If the column
306    * did not exist in the result set (either the column does not exist
307    * or the column was not selected in the query) the list will be empty.
308    *
309    * Also see getColumnLatest which returns just a Cell
310    *
311    * @param family the family
312    * @param qualifier
313    * @return a list of Cells for this column or empty list if the column
314    * did not exist in the result set
315    */
316   public List<Cell> getColumnCells(byte [] family, byte [] qualifier) {
317     List<Cell> result = new ArrayList<Cell>();
318 
319     Cell [] kvs = rawCells();
320 
321     if (kvs == null || kvs.length == 0) {
322       return result;
323     }
324     int pos = binarySearch(kvs, family, qualifier);
325     if (pos == -1) {
326       return result; // cant find it
327     }
328 
329     for (int i = pos ; i < kvs.length ; i++ ) {
330       if (CellUtil.matchingColumn(kvs[i], family,qualifier)) {
331         result.add(kvs[i]);
332       } else {
333         break;
334       }
335     }
336 
337     return result;
338   }
339 
340   protected int binarySearch(final Cell [] kvs,
341                              final byte [] family,
342                              final byte [] qualifier) {
343     Cell searchTerm =
344         KeyValueUtil.createFirstOnRow(CellUtil.cloneRow(kvs[0]),
345             family, qualifier);
346 
347     // pos === ( -(insertion point) - 1)
348     int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
349     // never will exact match
350     if (pos < 0) {
351       pos = (pos+1) * -1;
352       // pos is now insertion point
353     }
354     if (pos == kvs.length) {
355       return -1; // doesn't exist
356     }
357     return pos;
358   }
359 
360   /**
361    * Searches for the latest value for the specified column.
362    *
363    * @param kvs the array to search
364    * @param family family name
365    * @param foffset family offset
366    * @param flength family length
367    * @param qualifier column qualifier
368    * @param qoffset qualifier offset
369    * @param qlength qualifier length
370    *
371    * @return the index where the value was found, or -1 otherwise
372    */
373   protected int binarySearch(final Cell [] kvs,
374       final byte [] family, final int foffset, final int flength,
375       final byte [] qualifier, final int qoffset, final int qlength) {
376 
377     double keyValueSize = (double)
378         KeyValue.getKeyValueDataStructureSize(kvs[0].getRowLength(), flength, qlength, 0);
379 
380     byte[] buffer = localBuffer.get();
381     if (buffer == null || keyValueSize > buffer.length) {
382       // pad to the smallest multiple of the pad width
383       buffer = new byte[(int) Math.ceil(keyValueSize / PAD_WIDTH) * PAD_WIDTH];
384       localBuffer.set(buffer);
385     }
386 
387     Cell searchTerm = KeyValueUtil.createFirstOnRow(buffer, 0,
388         kvs[0].getRowArray(), kvs[0].getRowOffset(), kvs[0].getRowLength(),
389         family, foffset, flength,
390         qualifier, qoffset, qlength);
391 
392     // pos === ( -(insertion point) - 1)
393     int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
394     // never will exact match
395     if (pos < 0) {
396       pos = (pos+1) * -1;
397       // pos is now insertion point
398     }
399     if (pos == kvs.length) {
400       return -1; // doesn't exist
401     }
402     return pos;
403   }
404 
405   /**
406    * @deprecated Use {@link #getColumnLatestCell(byte[], byte[])} instead.
407    */
408   @Deprecated
409   public KeyValue getColumnLatest(byte [] family, byte [] qualifier) {
410     return KeyValueUtil.ensureKeyValue(getColumnLatestCell(family, qualifier));
411   }
412 
413   /**
414    * The Cell for the most recent timestamp for a given column.
415    *
416    * @param family
417    * @param qualifier
418    *
419    * @return the Cell for the column, or null if no value exists in the row or none have been
420    * selected in the query (Get/Scan)
421    */
422   public Cell getColumnLatestCell(byte [] family, byte [] qualifier) {
423     Cell [] kvs = rawCells(); // side effect possibly.
424     if (kvs == null || kvs.length == 0) {
425       return null;
426     }
427     int pos = binarySearch(kvs, family, qualifier);
428     if (pos == -1) {
429       return null;
430     }
431     if (CellUtil.matchingColumn(kvs[pos], family, qualifier)) {
432       return kvs[pos];
433     }
434     return null;
435   }
436 
437   /**
438    * @deprecated Use {@link #getColumnLatestCell(byte[], int, int, byte[], int, int)} instead.
439    */
440   @Deprecated
441   public KeyValue getColumnLatest(byte [] family, int foffset, int flength,
442       byte [] qualifier, int qoffset, int qlength) {
443     return KeyValueUtil.ensureKeyValue(
444         getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength));
445   }
446 
447   /**
448    * The Cell for the most recent timestamp for a given column.
449    *
450    * @param family family name
451    * @param foffset family offset
452    * @param flength family length
453    * @param qualifier column qualifier
454    * @param qoffset qualifier offset
455    * @param qlength qualifier length
456    *
457    * @return the Cell for the column, or null if no value exists in the row or none have been
458    * selected in the query (Get/Scan)
459    */
460   public Cell getColumnLatestCell(byte [] family, int foffset, int flength,
461       byte [] qualifier, int qoffset, int qlength) {
462 
463     Cell [] kvs = rawCells(); // side effect possibly.
464     if (kvs == null || kvs.length == 0) {
465       return null;
466     }
467     int pos = binarySearch(kvs, family, foffset, flength, qualifier, qoffset, qlength);
468     if (pos == -1) {
469       return null;
470     }
471     if (CellUtil.matchingColumn(kvs[pos], family, foffset, flength, qualifier, qoffset, qlength)) {
472       return kvs[pos];
473     }
474     return null;
475   }
476 
477   /**
478    * Get the latest version of the specified column.
479    * Note: this call clones the value content of the hosting Cell. See
480    * {@link #getValueAsByteBuffer(byte[], byte[])}, etc., or {@link #listCells()} if you would
481    * avoid the cloning.
482    * @param family family name
483    * @param qualifier column qualifier
484    * @return value of latest version of column, null if none found
485    */
486   public byte[] getValue(byte [] family, byte [] qualifier) {
487     Cell kv = getColumnLatestCell(family, qualifier);
488     if (kv == null) {
489       return null;
490     }
491     return CellUtil.cloneValue(kv);
492   }
493 
494   /**
495    * Returns the value wrapped in a new <code>ByteBuffer</code>.
496    *
497    * @param family family name
498    * @param qualifier column qualifier
499    *
500    * @return the latest version of the column, or <code>null</code> if none found
501    */
502   public ByteBuffer getValueAsByteBuffer(byte [] family, byte [] qualifier) {
503 
504     Cell kv = getColumnLatestCell(family, 0, family.length, qualifier, 0, qualifier.length);
505 
506     if (kv == null) {
507       return null;
508     }
509     return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()).
510       asReadOnlyBuffer();
511   }
512 
513   /**
514    * Returns the value wrapped in a new <code>ByteBuffer</code>.
515    *
516    * @param family family name
517    * @param foffset family offset
518    * @param flength family length
519    * @param qualifier column qualifier
520    * @param qoffset qualifier offset
521    * @param qlength qualifier length
522    *
523    * @return the latest version of the column, or <code>null</code> if none found
524    */
525   public ByteBuffer getValueAsByteBuffer(byte [] family, int foffset, int flength,
526       byte [] qualifier, int qoffset, int qlength) {
527 
528     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
529 
530     if (kv == null) {
531       return null;
532     }
533     return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength()).
534       asReadOnlyBuffer();
535   }
536 
537   /**
538    * Loads the latest version of the specified column into the provided <code>ByteBuffer</code>.
539    * <p>
540    * Does not clear or flip the buffer.
541    *
542    * @param family family name
543    * @param qualifier column qualifier
544    * @param dst the buffer where to write the value
545    *
546    * @return <code>true</code> if a value was found, <code>false</code> otherwise
547    *
548    * @throws BufferOverflowException there is insufficient space remaining in the buffer
549    */
550   public boolean loadValue(byte [] family, byte [] qualifier, ByteBuffer dst)
551           throws BufferOverflowException {
552     return loadValue(family, 0, family.length, qualifier, 0, qualifier.length, dst);
553   }
554 
555   /**
556    * Loads the latest version of the specified column into the provided <code>ByteBuffer</code>.
557    * <p>
558    * Does not clear or flip the buffer.
559    *
560    * @param family family name
561    * @param foffset family offset
562    * @param flength family length
563    * @param qualifier column qualifier
564    * @param qoffset qualifier offset
565    * @param qlength qualifier length
566    * @param dst the buffer where to write the value
567    *
568    * @return <code>true</code> if a value was found, <code>false</code> otherwise
569    *
570    * @throws BufferOverflowException there is insufficient space remaining in the buffer
571    */
572   public boolean loadValue(byte [] family, int foffset, int flength,
573       byte [] qualifier, int qoffset, int qlength, ByteBuffer dst)
574           throws BufferOverflowException {
575     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
576 
577     if (kv == null) {
578       return false;
579     }
580     dst.put(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
581     return true;
582   }
583 
584   /**
585    * Checks if the specified column contains a non-empty value (not a zero-length byte array).
586    *
587    * @param family family name
588    * @param qualifier column qualifier
589    *
590    * @return whether or not a latest value exists and is not empty
591    */
592   public boolean containsNonEmptyColumn(byte [] family, byte [] qualifier) {
593 
594     return containsNonEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
595   }
596 
597   /**
598    * Checks if the specified column contains a non-empty value (not a zero-length byte array).
599    *
600    * @param family family name
601    * @param foffset family offset
602    * @param flength family length
603    * @param qualifier column qualifier
604    * @param qoffset qualifier offset
605    * @param qlength qualifier length
606    *
607    * @return whether or not a latest value exists and is not empty
608    */
609   public boolean containsNonEmptyColumn(byte [] family, int foffset, int flength,
610       byte [] qualifier, int qoffset, int qlength) {
611 
612     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
613 
614     return (kv != null) && (kv.getValueLength() > 0);
615   }
616 
617   /**
618    * Checks if the specified column contains an empty value (a zero-length byte array).
619    *
620    * @param family family name
621    * @param qualifier column qualifier
622    *
623    * @return whether or not a latest value exists and is empty
624    */
625   public boolean containsEmptyColumn(byte [] family, byte [] qualifier) {
626 
627     return containsEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
628   }
629 
630   /**
631    * Checks if the specified column contains an empty value (a zero-length byte array).
632    *
633    * @param family family name
634    * @param foffset family offset
635    * @param flength family length
636    * @param qualifier column qualifier
637    * @param qoffset qualifier offset
638    * @param qlength qualifier length
639    *
640    * @return whether or not a latest value exists and is empty
641    */
642   public boolean containsEmptyColumn(byte [] family, int foffset, int flength,
643       byte [] qualifier, int qoffset, int qlength) {
644     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
645 
646     return (kv != null) && (kv.getValueLength() == 0);
647   }
648 
649   /**
650    * Checks for existence of a value for the specified column (empty or not).
651    *
652    * @param family family name
653    * @param qualifier column qualifier
654    *
655    * @return true if at least one value exists in the result, false if not
656    */
657   public boolean containsColumn(byte [] family, byte [] qualifier) {
658     Cell kv = getColumnLatestCell(family, qualifier);
659     return kv != null;
660   }
661 
662   /**
663    * Checks for existence of a value for the specified column (empty or not).
664    *
665    * @param family family name
666    * @param foffset family offset
667    * @param flength family length
668    * @param qualifier column qualifier
669    * @param qoffset qualifier offset
670    * @param qlength qualifier length
671    *
672    * @return true if at least one value exists in the result, false if not
673    */
674   public boolean containsColumn(byte [] family, int foffset, int flength,
675       byte [] qualifier, int qoffset, int qlength) {
676 
677     return getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength) != null;
678   }
679 
680   /**
681    * Map of families to all versions of its qualifiers and values.
682    * <p>
683    * Returns a three level Map of the form:
684    * <code>Map&amp;family,Map&lt;qualifier,Map&lt;timestamp,value&gt;&gt;&gt;</code>
685    * <p>
686    * Note: All other map returning methods make use of this map internally.
687    * @return map from families to qualifiers to versions
688    */
689   public NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> getMap() {
690     if (this.familyMap != null) {
691       return this.familyMap;
692     }
693     if(isEmpty()) {
694       return null;
695     }
696     this.familyMap = new TreeMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>(Bytes.BYTES_COMPARATOR);
697     for(Cell kv : this.cells) {
698       byte [] family = CellUtil.cloneFamily(kv);
699       NavigableMap<byte[], NavigableMap<Long, byte[]>> columnMap =
700         familyMap.get(family);
701       if(columnMap == null) {
702         columnMap = new TreeMap<byte[], NavigableMap<Long, byte[]>>
703           (Bytes.BYTES_COMPARATOR);
704         familyMap.put(family, columnMap);
705       }
706       byte [] qualifier = CellUtil.cloneQualifier(kv);
707       NavigableMap<Long, byte[]> versionMap = columnMap.get(qualifier);
708       if(versionMap == null) {
709         versionMap = new TreeMap<Long, byte[]>(new Comparator<Long>() {
710           @Override
711           public int compare(Long l1, Long l2) {
712             return l2.compareTo(l1);
713           }
714         });
715         columnMap.put(qualifier, versionMap);
716       }
717       Long timestamp = kv.getTimestamp();
718       byte [] value = CellUtil.cloneValue(kv);
719 
720       versionMap.put(timestamp, value);
721     }
722     return this.familyMap;
723   }
724 
725   /**
726    * Map of families to their most recent qualifiers and values.
727    * <p>
728    * Returns a two level Map of the form: <code>Map&amp;family,Map&lt;qualifier,value&gt;&gt;</code>
729    * <p>
730    * The most recent version of each qualifier will be used.
731    * @return map from families to qualifiers and value
732    */
733   public NavigableMap<byte[], NavigableMap<byte[], byte[]>> getNoVersionMap() {
734     if(this.familyMap == null) {
735       getMap();
736     }
737     if(isEmpty()) {
738       return null;
739     }
740     NavigableMap<byte[], NavigableMap<byte[], byte[]>> returnMap =
741       new TreeMap<byte[], NavigableMap<byte[], byte[]>>(Bytes.BYTES_COMPARATOR);
742     for(Map.Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>
743       familyEntry : familyMap.entrySet()) {
744       NavigableMap<byte[], byte[]> qualifierMap =
745         new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
746       for(Map.Entry<byte[], NavigableMap<Long, byte[]>> qualifierEntry :
747         familyEntry.getValue().entrySet()) {
748         byte [] value =
749           qualifierEntry.getValue().get(qualifierEntry.getValue().firstKey());
750         qualifierMap.put(qualifierEntry.getKey(), value);
751       }
752       returnMap.put(familyEntry.getKey(), qualifierMap);
753     }
754     return returnMap;
755   }
756 
757   /**
758    * Map of qualifiers to values.
759    * <p>
760    * Returns a Map of the form: <code>Map&lt;qualifier,value&gt;</code>
761    * @param family column family to get
762    * @return map of qualifiers to values
763    */
764   public NavigableMap<byte[], byte[]> getFamilyMap(byte [] family) {
765     if(this.familyMap == null) {
766       getMap();
767     }
768     if(isEmpty()) {
769       return null;
770     }
771     NavigableMap<byte[], byte[]> returnMap =
772       new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
773     NavigableMap<byte[], NavigableMap<Long, byte[]>> qualifierMap =
774       familyMap.get(family);
775     if(qualifierMap == null) {
776       return returnMap;
777     }
778     for(Map.Entry<byte[], NavigableMap<Long, byte[]>> entry :
779       qualifierMap.entrySet()) {
780       byte [] value =
781         entry.getValue().get(entry.getValue().firstKey());
782       returnMap.put(entry.getKey(), value);
783     }
784     return returnMap;
785   }
786 
787   /**
788    * Returns the value of the first column in the Result.
789    * @return value of the first column
790    */
791   public byte [] value() {
792     if (isEmpty()) {
793       return null;
794     }
795     return CellUtil.cloneValue(cells[0]);
796   }
797 
798   /**
799    * Check if the underlying Cell [] is empty or not
800    * @return true if empty
801    */
802   public boolean isEmpty() {
803     return this.cells == null || this.cells.length == 0;
804   }
805 
806   /**
807    * @return the size of the underlying Cell []
808    */
809   public int size() {
810     return this.cells == null? 0: this.cells.length;
811   }
812 
813   /**
814    * @return String
815    */
816   @Override
817   public String toString() {
818     StringBuilder sb = new StringBuilder();
819     sb.append("keyvalues=");
820     if(isEmpty()) {
821       sb.append("NONE");
822       return sb.toString();
823     }
824     sb.append("{");
825     boolean moreThanOne = false;
826     for(Cell kv : this.cells) {
827       if(moreThanOne) {
828         sb.append(", ");
829       } else {
830         moreThanOne = true;
831       }
832       sb.append(kv.toString());
833     }
834     sb.append("}");
835     return sb.toString();
836   }
837 
838   /**
839    * Does a deep comparison of two Results, down to the byte arrays.
840    * @param res1 first result to compare
841    * @param res2 second result to compare
842    * @throws Exception Every difference is throwing an exception
843    */
844   public static void compareResults(Result res1, Result res2)
845       throws Exception {
846     if (res2 == null) {
847       throw new Exception("There wasn't enough rows, we stopped at "
848           + Bytes.toStringBinary(res1.getRow()));
849     }
850     if (res1.size() != res2.size()) {
851       throw new Exception("This row doesn't have the same number of KVs: "
852           + res1.toString() + " compared to " + res2.toString());
853     }
854     Cell[] ourKVs = res1.rawCells();
855     Cell[] replicatedKVs = res2.rawCells();
856     for (int i = 0; i < res1.size(); i++) {
857       if (!ourKVs[i].equals(replicatedKVs[i]) ||
858           !CellUtil.matchingValue(ourKVs[i], replicatedKVs[i]) ||
859           !CellUtil.matchingTags(ourKVs[i], replicatedKVs[i])) {
860         throw new Exception("This result was different: "
861             + res1.toString() + " compared to " + res2.toString());
862       }
863     }
864   }
865 
866   /**
867    * Forms a single result from the partial results in the partialResults list. This method is
868    * useful for reconstructing partial results on the client side.
869    * @param partialResults list of partial results
870    * @return The complete result that is formed by combining all of the partial results together
871    * @throws IOException A complete result cannot be formed because the results in the partial list
872    *           come from different rows
873    * @deprecated
874    */
875   @Deprecated
876   public static Result createCompleteResult(List<Result> partialResults)
877       throws IOException {
878     return createCompleteResult((Iterable<Result>)partialResults);
879   }
880 
881   /**
882    * Forms a single result from the partial results in the partialResults list. This method is
883    * useful for reconstructing partial results on the client side.
884    * @param partialResults iterable of partial results
885    * @return The complete result that is formed by combining all of the partial results together
886    * @throws IOException A complete result cannot be formed because the results in the partial list
887    *           come from different rows
888    */
889   public static Result createCompleteResult(Iterable<Result> partialResults)
890       throws IOException {
891     if (partialResults == null) {
892       return Result.create(Collections.<Cell> emptyList(), null, false);
893     }
894     List<Cell> cells = new ArrayList<>();
895     boolean stale = false;
896     byte[] prevRow = null;
897     byte[] currentRow = null;
898     for (Iterator<Result> iter = partialResults.iterator(); iter.hasNext();) {
899       Result r = iter.next();
900       currentRow = r.getRow();
901       if (prevRow != null && !Bytes.equals(prevRow, currentRow)) {
902         throw new IOException(
903             "Cannot form complete result. Rows of partial results do not match." +
904                 " Partial Results: " + partialResults);
905       }
906       // Ensure that all Results except the last one are marked as partials. The last result
907       // may not be marked as a partial because Results are only marked as partials when
908       // the scan on the server side must be stopped due to reaching the maxResultSize.
909       // Visualizing it makes it easier to understand:
910       // maxResultSize: 2 cells
911       // (-x-) represents cell number x in a row
912       // Example: row1: -1- -2- -3- -4- -5- (5 cells total)
913       // How row1 will be returned by the server as partial Results:
914       // Result1: -1- -2- (2 cells, size limit reached, mark as partial)
915       // Result2: -3- -4- (2 cells, size limit reached, mark as partial)
916       // Result3: -5- (1 cell, size limit NOT reached, NOT marked as partial)
917       if (iter.hasNext() && !r.mayHaveMoreCellsInRow()) {
918         throw new IOException("Cannot form complete result. Result is missing partial flag. " +
919             "Partial Results: " + partialResults);
920       }
921       prevRow = currentRow;
922       stale = stale || r.isStale();
923       for (Cell c : r.rawCells()) {
924         cells.add(c);
925       }
926     }
927 
928     return Result.create(cells, null, stale);
929   }
930 
931   /**
932    * Get total size of raw cells
933    * @param result
934    * @return Total size.
935    */
936   public static long getTotalSizeOfCells(Result result) {
937     long size = 0;
938     if (result.isEmpty()) {
939       return size;
940     }
941     for (Cell c : result.rawCells()) {
942       size += CellUtil.estimatedHeapSizeOf(c);
943     }
944     return size;
945   }
946 
947   /**
948    * Copy another Result into this one. Needed for the old Mapred framework
949    * @throws UnsupportedOperationException if invoked on instance of EMPTY_RESULT
950    * (which is supposed to be immutable).
951    * @param other
952    */
953   public void copyFrom(Result other) {
954     checkReadonly();
955     this.row = null;
956     this.familyMap = null;
957     this.cells = other.cells;
958   }
959 
960   @Override
961   public CellScanner cellScanner() {
962     // Reset
963     this.cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
964     return this;
965   }
966 
967   @Override
968   public Cell current() {
969     if (isEmpty()
970             || cellScannerIndex == INITIAL_CELLSCANNER_INDEX
971             || cellScannerIndex >= cells.length)
972       return null;
973     return this.cells[cellScannerIndex];
974   }
975 
976   @Override
977   public boolean advance() {
978     if (isEmpty()) {
979       return false;
980     }
981     cellScannerIndex++;
982     if (cellScannerIndex < this.cells.length) {
983       return true;
984     } else if (cellScannerIndex == this.cells.length) {
985       return false;
986     }
987     throw new NoSuchElementException("Cannot advance beyond the last cell");
988   }
989 
990   public Boolean getExists() {
991     return exists;
992   }
993 
994   public void setExists(Boolean exists) {
995     checkReadonly();
996     this.exists = exists;
997   }
998 
999   /**
1000    * Whether or not the results are coming from possibly stale data. Stale results
1001    * might be returned if {@link Consistency} is not STRONG for the query.
1002    * @return Whether or not the results are coming from possibly stale data.
1003    */
1004   public boolean isStale() {
1005     return stale;
1006   }
1007 
1008   /**
1009    * @deprecated the word 'partial' ambiguous, use {@link #mayHaveMoreCellsInRow()} instead.
1010    *             Deprecated since 1.4.0.
1011    * @see #mayHaveMoreCellsInRow()
1012    */
1013   @Deprecated
1014   public boolean isPartial() {
1015     return mayHaveMoreCellsInRow;
1016   }
1017 
1018   /**
1019    * For scanning large rows, the RS may choose to return the cells chunk by chunk to prevent OOM
1020    * or timeout. This flag is used to tell you if the current Result is the last one of the current
1021    * row. False means this Result is the last one. True means there MAY be more cells belonging to
1022    * the current row.
1023    * If you don't use {@link Scan#setAllowPartialResults(boolean)} or {@link Scan#setBatch(int)},
1024    * this method will always return false because the Result must contains all cells in one Row.
1025    */
1026   public boolean mayHaveMoreCellsInRow() {
1027     return mayHaveMoreCellsInRow;
1028   }
1029 
1030   /**
1031    * Add load information about the region to the information about the result
1032    * @param loadStats statistics about the current region from which this was returned
1033    * @deprecated use {@link #setStatistics(ClientProtos.RegionLoadStats)} instead
1034    * @throws UnsupportedOperationException if invoked on instance of EMPTY_RESULT
1035    * (which is supposed to be immutable).
1036    */
1037   @InterfaceAudience.Private
1038   @Deprecated
1039   public void addResults(ClientProtos.RegionLoadStats loadStats) {
1040     checkReadonly();
1041     this.stats = loadStats;
1042   }
1043 
1044   /**
1045    * Set load information about the region to the information about the result
1046    * @param loadStats statistics about the current region from which this was returned
1047    */
1048   @InterfaceAudience.Private
1049   @Deprecated
1050   public void setStatistics(ClientProtos.RegionLoadStats loadStats) {
1051     this.stats = loadStats;
1052   }
1053 
1054   /**
1055    * @return the associated statistics about the region from which this was returned. Can be
1056    * <tt>null</tt> if stats are disabled.
1057    */
1058   @Deprecated
1059   public ClientProtos.RegionLoadStats getStats() {
1060     return stats;
1061   }
1062 
1063   /**
1064    * All methods modifying state of Result object must call this method
1065    * to ensure that special purpose immutable Results can't be accidentally modified.
1066    */
1067   private void checkReadonly() {
1068     if (readonly == true) {
1069       throw new UnsupportedOperationException("Attempting to modify readonly EMPTY_RESULT!");
1070     }
1071   }
1072 
1073   /**
1074    * Return true if this Result is a cursor to tell users where the server has scanned.
1075    * In this Result the only meaningful method is {@link #getCursor()}.
1076    *
1077    * {@code
1078    *  while (r = scanner.next() && r != null) {
1079    *    if(r.isCursor()){
1080    *    // scanning is not end, it is a cursor, save its row key and close scanner if you want, or
1081    *    // just continue the loop to call next().
1082    *    } else {
1083    *    // just like before
1084    *    }
1085    *  }
1086    *  // scanning is end
1087    *
1088    * }
1089    * {@link Scan#setNeedCursorResult(boolean)}
1090    * {@link Cursor}
1091    * {@link #getCursor()}
1092    */
1093   public boolean isCursor() {
1094     return cursor != null ;
1095   }
1096 
1097   /**
1098    * Return the cursor if this Result is a cursor result.
1099    * {@link Scan#setNeedCursorResult(boolean)}
1100    * {@link Cursor}
1101    * {@link #isCursor()}
1102    */
1103   public Cursor getCursor(){
1104     return cursor;
1105   }
1106 }