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.nio.BufferOverflowException;
23  import java.nio.ByteBuffer;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Comparator;
27  import java.util.List;
28  import java.util.Map;
29  import java.util.NavigableMap;
30  import java.util.TreeMap;
31  
32  import org.apache.hadoop.classification.InterfaceAudience;
33  import org.apache.hadoop.classification.InterfaceStability;
34  import org.apache.hadoop.hbase.Cell;
35  import org.apache.hadoop.hbase.CellScannable;
36  import org.apache.hadoop.hbase.CellScanner;
37  import org.apache.hadoop.hbase.CellUtil;
38  import org.apache.hadoop.hbase.KeyValue;
39  import org.apache.hadoop.hbase.KeyValueUtil;
40  import org.apache.hadoop.hbase.util.Bytes;
41  
42  /**
43   * Single row result of a {@link Get} or {@link Scan} query.<p>
44   *
45   * This class is <b>NOT THREAD SAFE</b>.<p>
46   *
47   * Convenience methods are available that return various {@link Map}
48   * structures and values directly.<p>
49   *
50   * To get a complete mapping of all cells in the Result, which can include
51   * multiple families and multiple versions, use {@link #getMap()}.<p>
52   *
53   * To get a mapping of each family to its columns (qualifiers and values),
54   * including only the latest version of each, use {@link #getNoVersionMap()}.
55   *
56   * To get a mapping of qualifiers to latest values for an individual family use
57   * {@link #getFamilyMap(byte[])}.<p>
58   *
59   * To get the latest value for a specific family and qualifier use {@link #getValue(byte[], byte[])}.
60   *
61   * A Result is backed by an array of {@link Cell} objects, each representing
62   * an HBase cell defined by the row, family, qualifier, timestamp, and value.<p>
63   *
64   * The underlying {@link Cell} objects can be accessed through the method {@link #listCells()}.
65   * This will create a List from the internal Cell []. Better is to exploit the fact that
66   * a new Result instance is a primed {@link CellScanner}; just call {@link #advance()} and
67   * {@link #current()} to iterate over Cells as you would any {@link CellScanner}.
68   * Call {@link #cellScanner()} to reset should you need to iterate the same Result over again
69   * ({@link CellScanner}s are one-shot).
70   *
71   * If you need to overwrite a Result with another Result instance -- as in the old 'mapred'
72   * RecordReader next invocations -- then create an empty Result with the null constructor and
73   * in then use {@link #copyFrom(Result)}
74   */
75  @InterfaceAudience.Public
76  @InterfaceStability.Stable
77  public class Result implements CellScannable, CellScanner {
78    private Cell[] cells;
79    private Boolean exists; // if the query was just to check existence.
80    private boolean stale = false;
81    // We're not using java serialization.  Transient here is just a marker to say
82    // that this is where we cache row if we're ever asked for it.
83    private transient byte [] row = null;
84    // Ditto for familyMap.  It can be composed on fly from passed in kvs.
85    private transient NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> familyMap = null;
86  
87    // never use directly
88    private static byte [] buffer = null;
89    private static final int PAD_WIDTH = 128;
90    public static final Result EMPTY_RESULT = new Result();
91  
92    private final static int INITIAL_CELLSCANNER_INDEX = -1;
93  
94    /**
95     * Index for where we are when Result is acting as a {@link CellScanner}.
96     */
97    private int cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
98  
99    /**
100    * Creates an empty Result w/ no KeyValue payload; returns null if you call {@link #rawCells()}.
101    * Use this to represent no results if <code>null</code> won't do or in old 'mapred' as oppposed to 'mapreduce' package
102    * MapReduce where you need to overwrite a Result
103    * instance with a {@link #copyFrom(Result)} call.
104    */
105   public Result() {
106     super();
107   }
108 
109   /**
110    * @deprecated Use {@link #create(List)} instead.
111    */
112   @Deprecated
113   public Result(KeyValue [] cells) {
114     this.cells = cells;
115   }
116 
117   /**
118    * @deprecated Use {@link #create(List)} instead.
119    */
120   @Deprecated
121   public Result(List<KeyValue> kvs) {
122     // TODO: Here we presume the passed in Cells are KVs.  One day this won't always be so.
123     this(kvs.toArray(new Cell[kvs.size()]), null, false);
124   }
125 
126   /**
127    * Instantiate a Result with the specified List of KeyValues.
128    * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted.
129    * @param cells List of cells
130    */
131   public static Result create(List<Cell> cells) {
132     return new Result(cells.toArray(new Cell[cells.size()]), null, false);
133   }
134 
135   public static Result create(List<Cell> cells, Boolean exists) {
136     return create(cells, exists, false);
137   }
138 
139   public static Result create(List<Cell> cells, Boolean exists, boolean stale) {
140     if (exists != null){
141       return new Result(null, exists, stale);
142     }
143     return new Result(cells.toArray(new Cell[cells.size()]), null, stale);
144   }
145 
146   /**
147    * Instantiate a Result with the specified array of KeyValues.
148    * <br><strong>Note:</strong> You must ensure that the keyvalues are already sorted.
149    * @param cells array of cells
150    */
151   public static Result create(Cell[] cells) {
152     return new Result(cells, null, false);
153   }
154 
155   public static Result create(Cell[] cells, Boolean exists, boolean stale) {
156     if (exists != null){
157       return new Result(null, exists, stale);
158     }
159     return new Result(cells, null, stale);
160   }
161 
162   /** Private ctor. Use {@link #create(Cell[])}. */
163   private Result(Cell[] cells, Boolean exists, boolean stale) {
164     this.cells = cells;
165     this.exists = exists;
166     this.stale = stale;
167   }
168 
169   /**
170    * Method for retrieving the row key that corresponds to
171    * the row from which this Result was created.
172    * @return row
173    */
174   public byte [] getRow() {
175     if (this.row == null) {
176       this.row = this.cells == null || this.cells.length == 0? null: CellUtil.cloneRow(this.cells[0]);
177     }
178     return this.row;
179   }
180 
181   /**
182    * Return the array of Cells backing this Result instance.
183    *
184    * The array is sorted from smallest -> largest using the
185    * {@link KeyValue#COMPARATOR}.
186    *
187    * The array only contains what your Get or Scan specifies and no more.
188    * For example if you request column "A" 1 version you will have at most 1
189    * Cell in the array. If you request column "A" with 2 version you will
190    * have at most 2 Cells, with the first one being the newer timestamp and
191    * the second being the older timestamp (this is the sort order defined by
192    * {@link KeyValue#COMPARATOR}).  If columns don't exist, they won't be
193    * present in the result. Therefore if you ask for 1 version all columns,
194    * it is safe to iterate over this array and expect to see 1 Cell for
195    * each column and no more.
196    *
197    * This API is faster than using getFamilyMap() and getMap()
198    *
199    * @return array of Cells; can be null if nothing in the result
200    */
201   public Cell[] rawCells() {
202     return cells;
203   }
204 
205   /**
206    * Return an cells of a Result as an array of KeyValues
207    *
208    * WARNING do not use, expensive.  This does an arraycopy of the cell[]'s value.
209    *
210    * Added to ease transition from  0.94 -> 0.96.
211    *
212    * @deprecated as of 0.96, use {@link #rawCells()}
213    * @return array of KeyValues, empty array if nothing in result.
214    */
215   @Deprecated
216   public KeyValue[] raw() {
217     KeyValue[] kvs = new KeyValue[cells.length];
218     for (int i = 0 ; i < kvs.length; i++) {
219       kvs[i] = KeyValueUtil.ensureKeyValue(cells[i]);
220     }
221     return kvs;
222   }
223 
224   /**
225    * Create a sorted list of the Cell's in this result.
226    *
227    * Since HBase 0.20.5 this is equivalent to raw().
228    *
229    * @return sorted List of Cells; can be null if no cells in the result
230    */
231   public List<Cell> listCells() {
232     return isEmpty()? null: Arrays.asList(rawCells());
233   }
234 
235   /**
236    * Return an cells of a Result as an array of KeyValues
237    *
238    * WARNING do not use, expensive.  This does  an arraycopy of the cell[]'s value.
239    *
240    * Added to ease transition from  0.94 -> 0.96.
241    *
242    * @deprecated as of 0.96, use {@link #listCells()}
243    * @return all sorted List of KeyValues; can be null if no cells in the result
244    */
245   @Deprecated
246   public List<KeyValue> list() {
247     return isEmpty() ? null : Arrays.asList(raw());
248   }
249 
250   /**
251    * @deprecated Use {@link #getColumnCells(byte[], byte[])} instead.
252    */
253   @Deprecated
254   public List<KeyValue> getColumn(byte [] family, byte [] qualifier) {
255     return KeyValueUtil.ensureKeyValues(getColumnCells(family, qualifier));
256   }
257 
258   /**
259    * Return the Cells for the specific column.  The Cells are sorted in
260    * the {@link KeyValue#COMPARATOR} order.  That implies the first entry in
261    * the list is the most recent column.  If the query (Scan or Get) only
262    * requested 1 version the list will contain at most 1 entry.  If the column
263    * did not exist in the result set (either the column does not exist
264    * or the column was not selected in the query) the list will be empty.
265    *
266    * Also see getColumnLatest which returns just a Cell
267    *
268    * @param family the family
269    * @param qualifier
270    * @return a list of Cells for this column or empty list if the column
271    * did not exist in the result set
272    */
273   public List<Cell> getColumnCells(byte [] family, byte [] qualifier) {
274     List<Cell> result = new ArrayList<Cell>();
275 
276     Cell [] kvs = rawCells();
277 
278     if (kvs == null || kvs.length == 0) {
279       return result;
280     }
281     int pos = binarySearch(kvs, family, qualifier);
282     if (pos == -1) {
283       return result; // cant find it
284     }
285 
286     for (int i = pos ; i < kvs.length ; i++ ) {
287       if (CellUtil.matchingColumn(kvs[i], family,qualifier)) {
288         result.add(kvs[i]);
289       } else {
290         break;
291       }
292     }
293 
294     return result;
295   }
296 
297   protected int binarySearch(final Cell [] kvs,
298                              final byte [] family,
299                              final byte [] qualifier) {
300     Cell searchTerm =
301         KeyValueUtil.createFirstOnRow(CellUtil.cloneRow(kvs[0]),
302             family, qualifier);
303 
304     // pos === ( -(insertion point) - 1)
305     int pos = Arrays.binarySearch(kvs, searchTerm, KeyValue.COMPARATOR);
306     // never will exact match
307     if (pos < 0) {
308       pos = (pos+1) * -1;
309       // pos is now insertion point
310     }
311     if (pos == kvs.length) {
312       return -1; // doesn't exist
313     }
314     return pos;
315   }
316 
317   /**
318    * Searches for the latest value for the specified column.
319    *
320    * @param kvs the array to search
321    * @param family family name
322    * @param foffset family offset
323    * @param flength family length
324    * @param qualifier column qualifier
325    * @param qoffset qualifier offset
326    * @param qlength qualifier length
327    *
328    * @return the index where the value was found, or -1 otherwise
329    */
330   protected int binarySearch(final Cell [] kvs,
331       final byte [] family, final int foffset, final int flength,
332       final byte [] qualifier, final int qoffset, final int qlength) {
333 
334     double keyValueSize = (double)
335         KeyValue.getKeyValueDataStructureSize(kvs[0].getRowLength(), flength, qlength, 0);
336 
337     if (buffer == null || keyValueSize > buffer.length) {
338       // pad to the smallest multiple of the pad width
339       buffer = new byte[(int) Math.ceil(keyValueSize / PAD_WIDTH) * PAD_WIDTH];
340     }
341 
342     Cell searchTerm = KeyValueUtil.createFirstOnRow(buffer, 0,
343         kvs[0].getRowArray(), kvs[0].getRowOffset(), kvs[0].getRowLength(),
344         family, foffset, flength,
345         qualifier, qoffset, qlength);
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    * @deprecated Use {@link #getColumnLatestCell(byte[], byte[])} instead.
362    */
363   @Deprecated
364   public KeyValue getColumnLatest(byte [] family, byte [] qualifier) {
365     return KeyValueUtil.ensureKeyValue(getColumnLatestCell(family, qualifier));
366   }
367 
368   /**
369    * The Cell for the most recent timestamp for a given column.
370    *
371    * @param family
372    * @param qualifier
373    *
374    * @return the Cell for the column, or null if no value exists in the row or none have been
375    * selected in the query (Get/Scan)
376    */
377   public Cell getColumnLatestCell(byte [] family, byte [] qualifier) {
378     Cell [] kvs = rawCells(); // side effect possibly.
379     if (kvs == null || kvs.length == 0) {
380       return null;
381     }
382     int pos = binarySearch(kvs, family, qualifier);
383     if (pos == -1) {
384       return null;
385     }
386     if (CellUtil.matchingColumn(kvs[pos], family, qualifier)) {
387       return kvs[pos];
388     }
389     return null;
390   }
391 
392   /**
393    * @deprecated Use {@link #getColumnLatestCell(byte[], int, int, byte[], int, int)} instead.
394    */
395   @Deprecated
396   public KeyValue getColumnLatest(byte [] family, int foffset, int flength,
397       byte [] qualifier, int qoffset, int qlength) {
398     return KeyValueUtil.ensureKeyValue(
399         getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength));
400   }
401 
402   /**
403    * The Cell for the most recent timestamp for a given column.
404    *
405    * @param family family name
406    * @param foffset family offset
407    * @param flength family length
408    * @param qualifier column qualifier
409    * @param qoffset qualifier offset
410    * @param qlength qualifier length
411    *
412    * @return the Cell for the column, or null if no value exists in the row or none have been
413    * selected in the query (Get/Scan)
414    */
415   public Cell getColumnLatestCell(byte [] family, int foffset, int flength,
416       byte [] qualifier, int qoffset, int qlength) {
417 
418     Cell [] kvs = rawCells(); // side effect possibly.
419     if (kvs == null || kvs.length == 0) {
420       return null;
421     }
422     int pos = binarySearch(kvs, family, foffset, flength, qualifier, qoffset, qlength);
423     if (pos == -1) {
424       return null;
425     }
426     if (CellUtil.matchingColumn(kvs[pos], family, foffset, flength, qualifier, qoffset, qlength)) {
427       return kvs[pos];
428     }
429     return null;
430   }
431 
432   /**
433    * Get the latest version of the specified column.
434    * @param family family name
435    * @param qualifier column qualifier
436    * @return value of latest version of column, null if none found
437    */
438   public byte[] getValue(byte [] family, byte [] qualifier) {
439     Cell kv = getColumnLatestCell(family, qualifier);
440     if (kv == null) {
441       return null;
442     }
443     return CellUtil.cloneValue(kv);
444   }
445 
446   /**
447    * Returns the value wrapped in a new <code>ByteBuffer</code>.
448    *
449    * @param family family name
450    * @param qualifier column qualifier
451    *
452    * @return the latest version of the column, or <code>null</code> if none found
453    */
454   public ByteBuffer getValueAsByteBuffer(byte [] family, byte [] qualifier) {
455 
456     Cell kv = getColumnLatestCell(family, 0, family.length, qualifier, 0, qualifier.length);
457 
458     if (kv == null) {
459       return null;
460     }
461     return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
462   }
463 
464   /**
465    * Returns the value wrapped in a new <code>ByteBuffer</code>.
466    *
467    * @param family family name
468    * @param foffset family offset
469    * @param flength family length
470    * @param qualifier column qualifier
471    * @param qoffset qualifier offset
472    * @param qlength qualifier length
473    *
474    * @return the latest version of the column, or <code>null</code> if none found
475    */
476   public ByteBuffer getValueAsByteBuffer(byte [] family, int foffset, int flength,
477       byte [] qualifier, int qoffset, int qlength) {
478 
479     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
480 
481     if (kv == null) {
482       return null;
483     }
484     return ByteBuffer.wrap(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
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 qualifier column qualifier
494    * @param dst the buffer where to write the value
495    *
496    * @return <code>true</code> if a value was found, <code>false</code> otherwise
497    *
498    * @throws BufferOverflowException there is insufficient space remaining in the buffer
499    */
500   public boolean loadValue(byte [] family, byte [] qualifier, ByteBuffer dst)
501           throws BufferOverflowException {
502     return loadValue(family, 0, family.length, qualifier, 0, qualifier.length, dst);
503   }
504 
505   /**
506    * Loads the latest version of the specified column into the provided <code>ByteBuffer</code>.
507    * <p>
508    * Does not clear or flip the buffer.
509    *
510    * @param family family name
511    * @param foffset family offset
512    * @param flength family length
513    * @param qualifier column qualifier
514    * @param qoffset qualifier offset
515    * @param qlength qualifier length
516    * @param dst the buffer where to write the value
517    *
518    * @return <code>true</code> if a value was found, <code>false</code> otherwise
519    *
520    * @throws BufferOverflowException there is insufficient space remaining in the buffer
521    */
522   public boolean loadValue(byte [] family, int foffset, int flength,
523       byte [] qualifier, int qoffset, int qlength, ByteBuffer dst)
524           throws BufferOverflowException {
525     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
526 
527     if (kv == null) {
528       return false;
529     }
530     dst.put(kv.getValueArray(), kv.getValueOffset(), kv.getValueLength());
531     return true;
532   }
533 
534   /**
535    * Checks if the specified column contains a non-empty value (not a zero-length byte array).
536    *
537    * @param family family name
538    * @param qualifier column qualifier
539    *
540    * @return whether or not a latest value exists and is not empty
541    */
542   public boolean containsNonEmptyColumn(byte [] family, byte [] qualifier) {
543 
544     return containsNonEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
545   }
546 
547   /**
548    * Checks if the specified column contains a non-empty value (not a zero-length byte array).
549    *
550    * @param family family name
551    * @param foffset family offset
552    * @param flength family length
553    * @param qualifier column qualifier
554    * @param qoffset qualifier offset
555    * @param qlength qualifier length
556    *
557    * @return whether or not a latest value exists and is not empty
558    */
559   public boolean containsNonEmptyColumn(byte [] family, int foffset, int flength,
560       byte [] qualifier, int qoffset, int qlength) {
561 
562     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
563 
564     return (kv != null) && (kv.getValueLength() > 0);
565   }
566 
567   /**
568    * Checks if the specified column contains an empty value (a zero-length byte array).
569    *
570    * @param family family name
571    * @param qualifier column qualifier
572    *
573    * @return whether or not a latest value exists and is empty
574    */
575   public boolean containsEmptyColumn(byte [] family, byte [] qualifier) {
576 
577     return containsEmptyColumn(family, 0, family.length, qualifier, 0, qualifier.length);
578   }
579 
580   /**
581    * Checks if the specified column contains an empty value (a zero-length byte array).
582    *
583    * @param family family name
584    * @param foffset family offset
585    * @param flength family length
586    * @param qualifier column qualifier
587    * @param qoffset qualifier offset
588    * @param qlength qualifier length
589    *
590    * @return whether or not a latest value exists and is empty
591    */
592   public boolean containsEmptyColumn(byte [] family, int foffset, int flength,
593       byte [] qualifier, int qoffset, int qlength) {
594     Cell kv = getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength);
595 
596     return (kv != null) && (kv.getValueLength() == 0);
597   }
598 
599   /**
600    * Checks for existence of a value for the specified column (empty or not).
601    *
602    * @param family family name
603    * @param qualifier column qualifier
604    *
605    * @return true if at least one value exists in the result, false if not
606    */
607   public boolean containsColumn(byte [] family, byte [] qualifier) {
608     Cell kv = getColumnLatestCell(family, qualifier);
609     return kv != null;
610   }
611 
612   /**
613    * Checks for existence of a value for the specified column (empty or not).
614    *
615    * @param family family name
616    * @param foffset family offset
617    * @param flength family length
618    * @param qualifier column qualifier
619    * @param qoffset qualifier offset
620    * @param qlength qualifier length
621    *
622    * @return true if at least one value exists in the result, false if not
623    */
624   public boolean containsColumn(byte [] family, int foffset, int flength,
625       byte [] qualifier, int qoffset, int qlength) {
626 
627     return getColumnLatestCell(family, foffset, flength, qualifier, qoffset, qlength) != null;
628   }
629 
630   /**
631    * Map of families to all versions of its qualifiers and values.
632    * <p>
633    * Returns a three level Map of the form:
634    * <code>Map&amp;family,Map&lt;qualifier,Map&lt;timestamp,value>>></code>
635    * <p>
636    * Note: All other map returning methods make use of this map internally.
637    * @return map from families to qualifiers to versions
638    */
639   public NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>> getMap() {
640     if (this.familyMap != null) {
641       return this.familyMap;
642     }
643     if(isEmpty()) {
644       return null;
645     }
646     this.familyMap = new TreeMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>(Bytes.BYTES_COMPARATOR);
647     for(Cell kv : this.cells) {
648       byte [] family = CellUtil.cloneFamily(kv);
649       NavigableMap<byte[], NavigableMap<Long, byte[]>> columnMap =
650         familyMap.get(family);
651       if(columnMap == null) {
652         columnMap = new TreeMap<byte[], NavigableMap<Long, byte[]>>
653           (Bytes.BYTES_COMPARATOR);
654         familyMap.put(family, columnMap);
655       }
656       byte [] qualifier = CellUtil.cloneQualifier(kv);
657       NavigableMap<Long, byte[]> versionMap = columnMap.get(qualifier);
658       if(versionMap == null) {
659         versionMap = new TreeMap<Long, byte[]>(new Comparator<Long>() {
660           @Override
661           public int compare(Long l1, Long l2) {
662             return l2.compareTo(l1);
663           }
664         });
665         columnMap.put(qualifier, versionMap);
666       }
667       Long timestamp = kv.getTimestamp();
668       byte [] value = CellUtil.cloneValue(kv);
669 
670       versionMap.put(timestamp, value);
671     }
672     return this.familyMap;
673   }
674 
675   /**
676    * Map of families to their most recent qualifiers and values.
677    * <p>
678    * Returns a two level Map of the form: <code>Map&amp;family,Map&lt;qualifier,value>></code>
679    * <p>
680    * The most recent version of each qualifier will be used.
681    * @return map from families to qualifiers and value
682    */
683   public NavigableMap<byte[], NavigableMap<byte[], byte[]>> getNoVersionMap() {
684     if(this.familyMap == null) {
685       getMap();
686     }
687     if(isEmpty()) {
688       return null;
689     }
690     NavigableMap<byte[], NavigableMap<byte[], byte[]>> returnMap =
691       new TreeMap<byte[], NavigableMap<byte[], byte[]>>(Bytes.BYTES_COMPARATOR);
692     for(Map.Entry<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>
693       familyEntry : familyMap.entrySet()) {
694       NavigableMap<byte[], byte[]> qualifierMap =
695         new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
696       for(Map.Entry<byte[], NavigableMap<Long, byte[]>> qualifierEntry :
697         familyEntry.getValue().entrySet()) {
698         byte [] value =
699           qualifierEntry.getValue().get(qualifierEntry.getValue().firstKey());
700         qualifierMap.put(qualifierEntry.getKey(), value);
701       }
702       returnMap.put(familyEntry.getKey(), qualifierMap);
703     }
704     return returnMap;
705   }
706 
707   /**
708    * Map of qualifiers to values.
709    * <p>
710    * Returns a Map of the form: <code>Map&lt;qualifier,value></code>
711    * @param family column family to get
712    * @return map of qualifiers to values
713    */
714   public NavigableMap<byte[], byte[]> getFamilyMap(byte [] family) {
715     if(this.familyMap == null) {
716       getMap();
717     }
718     if(isEmpty()) {
719       return null;
720     }
721     NavigableMap<byte[], byte[]> returnMap =
722       new TreeMap<byte[], byte[]>(Bytes.BYTES_COMPARATOR);
723     NavigableMap<byte[], NavigableMap<Long, byte[]>> qualifierMap =
724       familyMap.get(family);
725     if(qualifierMap == null) {
726       return returnMap;
727     }
728     for(Map.Entry<byte[], NavigableMap<Long, byte[]>> entry :
729       qualifierMap.entrySet()) {
730       byte [] value =
731         entry.getValue().get(entry.getValue().firstKey());
732       returnMap.put(entry.getKey(), value);
733     }
734     return returnMap;
735   }
736 
737   /**
738    * Returns the value of the first column in the Result.
739    * @return value of the first column
740    */
741   public byte [] value() {
742     if (isEmpty()) {
743       return null;
744     }
745     return CellUtil.cloneValue(cells[0]);
746   }
747 
748   /**
749    * Check if the underlying Cell [] is empty or not
750    * @return true if empty
751    */
752   public boolean isEmpty() {
753     return this.cells == null || this.cells.length == 0;
754   }
755 
756   /**
757    * @return the size of the underlying Cell []
758    */
759   public int size() {
760     return this.cells == null? 0: this.cells.length;
761   }
762 
763   /**
764    * @return String
765    */
766   @Override
767   public String toString() {
768     StringBuilder sb = new StringBuilder();
769     sb.append("keyvalues=");
770     if(isEmpty()) {
771       sb.append("NONE");
772       return sb.toString();
773     }
774     sb.append("{");
775     boolean moreThanOne = false;
776     for(Cell kv : this.cells) {
777       if(moreThanOne) {
778         sb.append(", ");
779       } else {
780         moreThanOne = true;
781       }
782       sb.append(kv.toString());
783     }
784     sb.append("}");
785     return sb.toString();
786   }
787 
788   /**
789    * Does a deep comparison of two Results, down to the byte arrays.
790    * @param res1 first result to compare
791    * @param res2 second result to compare
792    * @throws Exception Every difference is throwing an exception
793    */
794   public static void compareResults(Result res1, Result res2)
795       throws Exception {
796     if (res2 == null) {
797       throw new Exception("There wasn't enough rows, we stopped at "
798           + Bytes.toStringBinary(res1.getRow()));
799     }
800     if (res1.size() != res2.size()) {
801       throw new Exception("This row doesn't have the same number of KVs: "
802           + res1.toString() + " compared to " + res2.toString());
803     }
804     Cell[] ourKVs = res1.rawCells();
805     Cell[] replicatedKVs = res2.rawCells();
806     for (int i = 0; i < res1.size(); i++) {
807       if (!ourKVs[i].equals(replicatedKVs[i]) ||
808           !Bytes.equals(CellUtil.cloneValue(ourKVs[i]), CellUtil.cloneValue(replicatedKVs[i]))) {
809         throw new Exception("This result was different: "
810             + res1.toString() + " compared to " + res2.toString());
811       }
812     }
813   }
814 
815   /**
816    * Get total size of raw cells 
817    * @param result
818    * @return Total size.
819    */
820   public static long getTotalSizeOfCells(Result result) {
821     long size = 0;
822     for (Cell c : result.rawCells()) {
823       size += KeyValueUtil.ensureKeyValue(c).heapSize();
824     }
825     return size;
826   }
827 
828   /**
829    * Copy another Result into this one. Needed for the old Mapred framework
830    * @param other
831    */
832   public void copyFrom(Result other) {
833     this.row = null;
834     this.familyMap = null;
835     this.cells = other.cells;
836   }
837 
838   @Override
839   public CellScanner cellScanner() {
840     // Reset
841     this.cellScannerIndex = INITIAL_CELLSCANNER_INDEX;
842     return this;
843   }
844 
845   @Override
846   public Cell current() {
847     if (cells == null) return null;
848     return (cellScannerIndex < 0)? null: this.cells[cellScannerIndex];
849   }
850 
851   @Override
852   public boolean advance() {
853     if (cells == null) return false;
854     return ++cellScannerIndex < this.cells.length;
855   }
856 
857   public Boolean getExists() {
858     return exists;
859   }
860 
861   public void setExists(Boolean exists) {
862     this.exists = exists;
863   }
864 
865   /**
866    * Whether or not the results are coming from possibly stale data. Stale results
867    * might be returned if {@link Consistency} is not STRONG for the query.
868    * @return Whether or not the results are coming from possibly stale data.
869    */
870   public boolean isStale() {
871     return stale;
872   }
873 }