View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase;
20  
21  import java.nio.ByteBuffer;
22  import java.util.Iterator;
23  import java.util.List;
24  import java.util.Map.Entry;
25  import java.util.NavigableMap;
26  
27  import org.apache.hadoop.classification.InterfaceAudience;
28  import org.apache.hadoop.classification.InterfaceStability;
29  import org.apache.hadoop.hbase.util.ByteRange;
30  
31  /**
32   * Utility methods helpful slinging {@link Cell} instances.
33   */
34  @InterfaceAudience.Private
35  @InterfaceStability.Evolving
36  public final class CellUtil {
37  
38    /******************* ByteRange *******************************/
39  
40    public static ByteRange fillRowRange(Cell cell, ByteRange range) {
41      return range.set(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
42    }
43  
44    public static ByteRange fillFamilyRange(Cell cell, ByteRange range) {
45      return range.set(cell.getFamilyArray(), cell.getFamilyOffset(), cell.getFamilyLength());
46    }
47  
48    public static ByteRange fillQualifierRange(Cell cell, ByteRange range) {
49      return range.set(cell.getQualifierArray(), cell.getQualifierOffset(),
50        cell.getQualifierLength());
51    }
52  
53  
54    /***************** get individual arrays for tests ************/
55  
56    public static byte[] getRowArray(Cell cell){
57      byte[] output = new byte[cell.getRowLength()];
58      copyRowTo(cell, output, 0);
59      return output;
60    }
61  
62    public static byte[] getFamilyArray(Cell cell){
63      byte[] output = new byte[cell.getFamilyLength()];
64      copyFamilyTo(cell, output, 0);
65      return output;
66    }
67  
68    public static byte[] getQualifierArray(Cell cell){
69      byte[] output = new byte[cell.getQualifierLength()];
70      copyQualifierTo(cell, output, 0);
71      return output;
72    }
73  
74    public static byte[] getValueArray(Cell cell){
75      byte[] output = new byte[cell.getValueLength()];
76      copyValueTo(cell, output, 0);
77      return output;
78    }
79  
80  
81    /******************** copyTo **********************************/
82  
83    public static int copyRowTo(Cell cell, byte[] destination, int destinationOffset) {
84      System.arraycopy(cell.getRowArray(), cell.getRowOffset(), destination, destinationOffset,
85        cell.getRowLength());
86      return destinationOffset + cell.getRowLength();
87    }
88  
89    public static int copyFamilyTo(Cell cell, byte[] destination, int destinationOffset) {
90      System.arraycopy(cell.getFamilyArray(), cell.getFamilyOffset(), destination, destinationOffset,
91        cell.getFamilyLength());
92      return destinationOffset + cell.getFamilyLength();
93    }
94  
95    public static int copyQualifierTo(Cell cell, byte[] destination, int destinationOffset) {
96      System.arraycopy(cell.getQualifierArray(), cell.getQualifierOffset(), destination,
97        destinationOffset, cell.getQualifierLength());
98      return destinationOffset + cell.getQualifierLength();
99    }
100 
101   public static int copyValueTo(Cell cell, byte[] destination, int destinationOffset) {
102     System.arraycopy(cell.getValueArray(), cell.getValueOffset(), destination, destinationOffset,
103       cell.getValueLength());
104     return destinationOffset + cell.getValueLength();
105   }
106 
107 
108   /********************* misc *************************************/
109 
110   public static byte getRowByte(Cell cell, int index) {
111     return cell.getRowArray()[cell.getRowOffset() + index];
112   }
113 
114   public static ByteBuffer getValueBufferShallowCopy(Cell cell) {
115     ByteBuffer buffer = ByteBuffer.wrap(cell.getValueArray(), cell.getValueOffset(),
116       cell.getValueLength());
117 //    buffer.position(buffer.limit());//make it look as if value was appended
118     return buffer;
119   }
120 
121   public static Cell createCell(final byte [] row, final byte [] family, final byte [] qualifier,
122       final long timestamp, final byte type, final byte [] value) {
123     // I need a Cell Factory here.  Using KeyValue for now. TODO.
124     // TODO: Make a new Cell implementation that just carries these
125     // byte arrays.
126     return new KeyValue(row, family, qualifier, timestamp,
127       KeyValue.Type.codeToType(type), value);
128   }
129 
130   /**
131    * @param cellScannerables
132    * @return CellScanner interface over <code>cellIterables</code>
133    */
134   public static CellScanner createCellScanner(final List<CellScannable> cellScannerables) {
135     return new CellScanner() {
136       private final Iterator<CellScannable> iterator = cellScannerables.iterator();
137       private CellScanner cellScanner = null;
138 
139       @Override
140       public Cell current() {
141         return this.cellScanner != null? this.cellScanner.current(): null;
142       }
143 
144       @Override
145       public boolean advance() {
146         if (this.cellScanner == null) {
147           if (!this.iterator.hasNext()) return false;
148           this.cellScanner = this.iterator.next().cellScanner();
149         }
150         if (this.cellScanner.advance()) return true;
151         this.cellScanner = null;
152         return advance();
153       }
154     };
155   }
156 
157   /**
158    * @param cellIterable
159    * @return CellScanner interface over <code>cellIterable</code>
160    */
161   public static CellScanner createCellScanner(final Iterable<Cell> cellIterable) {
162     return createCellScanner(cellIterable.iterator());
163   }
164 
165   /**
166    * @param cells
167    * @return CellScanner interface over <code>cellIterable</code>
168    */
169   public static CellScanner createCellScanner(final Iterator<Cell> cells) {
170     return new CellScanner() {
171       private final Iterator<Cell> iterator = cells;
172       private Cell current = null;
173 
174       @Override
175       public Cell current() {
176         return this.current;
177       }
178 
179       @Override
180       public boolean advance() {
181         boolean hasNext = this.iterator.hasNext();
182         this.current = hasNext? this.iterator.next(): null;
183         return hasNext;
184       }
185     };
186   }
187 
188   /**
189    * @param cellArray
190    * @return CellScanner interface over <code>cellArray</code>
191    */
192   public static CellScanner createCellScanner(final Cell[] cellArray) {
193     return new CellScanner() {
194       private final Cell [] cells = cellArray;
195       private int index = -1;
196 
197       @Override
198       public Cell current() {
199         return (index < 0)? null: this.cells[index];
200       }
201 
202       @Override
203       public boolean advance() {
204         return ++index < this.cells.length;
205       }
206     };
207   }
208 
209   /**
210    * Flatten the map of cells out under the CellScanner
211    * @param map Map of Cell Lists; for example, the map of families to Cells that is used
212    * inside Put, etc., keeping Cells organized by family.
213    * @return CellScanner interface over <code>cellIterable</code>
214    */
215   public static CellScanner createCellScanner(final NavigableMap<byte [],
216       List<? extends Cell>> map) {
217     return new CellScanner() {
218       private final Iterator<Entry<byte[], List<? extends Cell>>> entries =
219           map.entrySet().iterator();
220       private Iterator<? extends Cell> currentIterator = null;
221       private Cell currentCell;
222 
223       @Override
224       public Cell current() {
225         return this.currentCell;
226       }
227 
228       @Override
229       public boolean advance() {
230         if (this.currentIterator == null) {
231           if (!this.entries.hasNext()) return false;
232           this.currentIterator = this.entries.next().getValue().iterator();
233         }
234         if (this.currentIterator.hasNext()) {
235           this.currentCell = this.currentIterator.next();
236           return true;
237         }
238         this.currentCell = null;
239         this.currentIterator = null;
240         return advance();
241       }
242     };
243   }
244 }