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  package org.apache.hadoop.hbase.thrift2;
20  
21  import static org.apache.hadoop.hbase.util.Bytes.getBytes;
22  
23  import java.io.IOException;
24  import java.nio.ByteBuffer;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.hadoop.hbase.HRegionInfo;
30  import org.apache.hadoop.hbase.HRegionLocation;
31  import org.apache.hadoop.hbase.ServerName;
32  import org.apache.hadoop.hbase.classification.InterfaceAudience;
33  import org.apache.hadoop.hbase.Cell;
34  import org.apache.hadoop.hbase.CellUtil;
35  import org.apache.hadoop.hbase.HConstants;
36  import org.apache.hadoop.hbase.client.Append;
37  import org.apache.hadoop.hbase.client.Delete;
38  import org.apache.hadoop.hbase.client.Durability;
39  import org.apache.hadoop.hbase.client.Get;
40  import org.apache.hadoop.hbase.client.HRegionLocator;
41  import org.apache.hadoop.hbase.client.Increment;
42  import org.apache.hadoop.hbase.client.OperationWithAttributes;
43  import org.apache.hadoop.hbase.client.Put;
44  import org.apache.hadoop.hbase.client.Result;
45  import org.apache.hadoop.hbase.client.RowMutations;
46  import org.apache.hadoop.hbase.client.Scan;
47  import org.apache.hadoop.hbase.filter.CompareFilter.CompareOp;
48  import org.apache.hadoop.hbase.filter.ParseFilter;
49  import org.apache.hadoop.hbase.security.visibility.Authorizations;
50  import org.apache.hadoop.hbase.security.visibility.CellVisibility;
51  import org.apache.hadoop.hbase.thrift2.generated.TAppend;
52  import org.apache.hadoop.hbase.thrift2.generated.TColumn;
53  import org.apache.hadoop.hbase.thrift2.generated.TColumnIncrement;
54  import org.apache.hadoop.hbase.thrift2.generated.TColumnValue;
55  import org.apache.hadoop.hbase.thrift2.generated.TCompareOp;
56  import org.apache.hadoop.hbase.thrift2.generated.TDelete;
57  import org.apache.hadoop.hbase.thrift2.generated.TDeleteType;
58  import org.apache.hadoop.hbase.thrift2.generated.TDurability;
59  import org.apache.hadoop.hbase.thrift2.generated.TGet;
60  import org.apache.hadoop.hbase.thrift2.generated.THRegionInfo;
61  import org.apache.hadoop.hbase.thrift2.generated.THRegionLocation;
62  import org.apache.hadoop.hbase.thrift2.generated.TIncrement;
63  import org.apache.hadoop.hbase.thrift2.generated.TMutation;
64  import org.apache.hadoop.hbase.thrift2.generated.TPut;
65  import org.apache.hadoop.hbase.thrift2.generated.TResult;
66  import org.apache.hadoop.hbase.thrift2.generated.TRowMutations;
67  import org.apache.hadoop.hbase.thrift2.generated.TScan;
68  import org.apache.hadoop.hbase.thrift2.generated.TServerName;
69  import org.apache.hadoop.hbase.thrift2.generated.TTimeRange;
70  import org.apache.hadoop.hbase.util.Bytes;
71  
72  @InterfaceAudience.Private
73  public class ThriftUtilities {
74  
75    private ThriftUtilities() {
76      throw new UnsupportedOperationException("Can't initialize class");
77    }
78  
79    /**
80     * Creates a {@link Get} (HBase) from a {@link TGet} (Thrift).
81     *
82     * This ignores any timestamps set on {@link TColumn} objects.
83     *
84     * @param in the <code>TGet</code> to convert
85     *
86     * @return <code>Get</code> object
87     *
88     * @throws IOException if an invalid time range or max version parameter is given
89     */
90    public static Get getFromThrift(TGet in) throws IOException {
91      Get out = new Get(in.getRow());
92  
93      // Timestamp overwrites time range if both are set
94      if (in.isSetTimestamp()) {
95        out.setTimeStamp(in.getTimestamp());
96      } else if (in.isSetTimeRange()) {
97        out.setTimeRange(in.getTimeRange().getMinStamp(), in.getTimeRange().getMaxStamp());
98      }
99  
100     if (in.isSetMaxVersions()) {
101       out.setMaxVersions(in.getMaxVersions());
102     }
103 
104     if (in.isSetFilterString()) {
105       ParseFilter parseFilter = new ParseFilter();
106       out.setFilter(parseFilter.parseFilterString(in.getFilterString()));
107     }
108 
109     if (in.isSetAttributes()) {
110       addAttributes(out,in.getAttributes());
111     }
112 
113     if (in.isSetAuthorizations()) {
114       out.setAuthorizations(new Authorizations(in.getAuthorizations().getLabels()));
115     }
116     
117     if (!in.isSetColumns()) {
118       return out;
119     }
120 
121     for (TColumn column : in.getColumns()) {
122       if (column.isSetQualifier()) {
123         out.addColumn(column.getFamily(), column.getQualifier());
124       } else {
125         out.addFamily(column.getFamily());
126       }
127     }
128 
129     return out;
130   }
131 
132   /**
133    * Converts multiple {@link TGet}s (Thrift) into a list of {@link Get}s (HBase).
134    *
135    * @param in list of <code>TGet</code>s to convert
136    *
137    * @return list of <code>Get</code> objects
138    *
139    * @throws IOException if an invalid time range or max version parameter is given
140    * @see #getFromThrift(TGet)
141    */
142   public static List<Get> getsFromThrift(List<TGet> in) throws IOException {
143     List<Get> out = new ArrayList<Get>(in.size());
144     for (TGet get : in) {
145       out.add(getFromThrift(get));
146     }
147     return out;
148   }
149 
150   /**
151    * Creates a {@link TResult} (Thrift) from a {@link Result} (HBase).
152    *
153    * @param in the <code>Result</code> to convert
154    *
155    * @return converted result, returns an empty result if the input is <code>null</code>
156    */
157   public static TResult resultFromHBase(Result in) {
158     Cell[] raw = in.rawCells();
159     TResult out = new TResult();
160     byte[] row = in.getRow();
161     if (row != null) {
162       out.setRow(in.getRow());
163     }
164     List<TColumnValue> columnValues = new ArrayList<TColumnValue>();
165     for (Cell kv : raw) {
166       TColumnValue col = new TColumnValue();
167       col.setFamily(CellUtil.cloneFamily(kv));
168       col.setQualifier(CellUtil.cloneQualifier(kv));
169       col.setTimestamp(kv.getTimestamp());
170       col.setValue(CellUtil.cloneValue(kv));
171       if (kv.getTagsLength() > 0) {
172         col.setTags(CellUtil.getTagArray(kv));
173       }
174       columnValues.add(col);
175     }
176     out.setColumnValues(columnValues);
177     return out;
178   }
179 
180   /**
181    * Converts multiple {@link Result}s (HBase) into a list of {@link TResult}s (Thrift).
182    *
183    * @param in array of <code>Result</code>s to convert
184    *
185    * @return list of converted <code>TResult</code>s
186    *
187    * @see #resultFromHBase(Result)
188    */
189   public static List<TResult> resultsFromHBase(Result[] in) {
190     List<TResult> out = new ArrayList<TResult>(in.length);
191     for (Result result : in) {
192       out.add(resultFromHBase(result));
193     }
194     return out;
195   }
196 
197   /**
198    * Creates a {@link Put} (HBase) from a {@link TPut} (Thrift)
199    *
200    * @param in the <code>TPut</code> to convert
201    *
202    * @return converted <code>Put</code>
203    */
204   public static Put putFromThrift(TPut in) {
205     Put out;
206 
207     if (in.isSetTimestamp()) {
208       out = new Put(in.getRow(), in.getTimestamp());
209     } else {
210       out = new Put(in.getRow());
211     }
212 
213     if (in.isSetDurability()) {
214       out.setDurability(durabilityFromThrift(in.getDurability()));
215     }
216 
217     for (TColumnValue columnValue : in.getColumnValues()) {
218       if (columnValue.isSetTimestamp()) {
219         out.addImmutable(
220             columnValue.getFamily(), columnValue.getQualifier(), columnValue.getTimestamp(),
221             columnValue.getValue());
222       } else {
223         out.addImmutable(
224             columnValue.getFamily(), columnValue.getQualifier(), columnValue.getValue());
225       }
226     }
227 
228     if (in.isSetAttributes()) {
229       addAttributes(out,in.getAttributes());
230     }
231     
232     if (in.getCellVisibility() != null) {
233       out.setCellVisibility(new CellVisibility(in.getCellVisibility().getExpression()));
234     }
235 
236     return out;
237   }
238 
239   /**
240    * Converts multiple {@link TPut}s (Thrift) into a list of {@link Put}s (HBase).
241    *
242    * @param in list of <code>TPut</code>s to convert
243    *
244    * @return list of converted <code>Put</code>s
245    *
246    * @see #putFromThrift(TPut)
247    */
248   public static List<Put> putsFromThrift(List<TPut> in) {
249     List<Put> out = new ArrayList<Put>(in.size());
250     for (TPut put : in) {
251       out.add(putFromThrift(put));
252     }
253     return out;
254   }
255 
256   /**
257    * Creates a {@link Delete} (HBase) from a {@link TDelete} (Thrift).
258    *
259    * @param in the <code>TDelete</code> to convert
260    *
261    * @return converted <code>Delete</code>
262    */
263   public static Delete deleteFromThrift(TDelete in) {
264     Delete out;
265 
266     if (in.isSetColumns()) {
267       out = new Delete(in.getRow());
268       for (TColumn column : in.getColumns()) {
269         if (column.isSetQualifier()) {
270           if (column.isSetTimestamp()) {
271             if (in.isSetDeleteType() &&
272                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
273               out.deleteColumns(column.getFamily(), column.getQualifier(), column.getTimestamp());
274             else
275               out.deleteColumn(column.getFamily(), column.getQualifier(), column.getTimestamp());
276           } else {
277             if (in.isSetDeleteType() &&
278                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
279               out.deleteColumns(column.getFamily(), column.getQualifier());
280             else
281               out.deleteColumn(column.getFamily(), column.getQualifier());
282           }
283 
284         } else {
285           if (column.isSetTimestamp()) {
286             out.deleteFamily(column.getFamily(), column.getTimestamp());
287           } else {
288             out.deleteFamily(column.getFamily());
289           }
290         }
291       }
292     } else {
293       if (in.isSetTimestamp()) {
294         out = new Delete(in.getRow(), in.getTimestamp());
295       } else {
296         out = new Delete(in.getRow());
297       }
298     }
299 
300     if (in.isSetAttributes()) {
301       addAttributes(out,in.getAttributes());
302     }
303 
304     if (in.isSetDurability()) {
305       out.setDurability(durabilityFromThrift(in.getDurability()));
306     }
307 
308     return out;
309   }
310 
311   /**
312    * Converts multiple {@link TDelete}s (Thrift) into a list of {@link Delete}s (HBase).
313    *
314    * @param in list of <code>TDelete</code>s to convert
315    *
316    * @return list of converted <code>Delete</code>s
317    *
318    * @see #deleteFromThrift(TDelete)
319    */
320 
321   public static List<Delete> deletesFromThrift(List<TDelete> in) {
322     List<Delete> out = new ArrayList<Delete>(in.size());
323     for (TDelete delete : in) {
324       out.add(deleteFromThrift(delete));
325     }
326     return out;
327   }
328 
329   public static TDelete deleteFromHBase(Delete in) {
330     TDelete out = new TDelete(ByteBuffer.wrap(in.getRow()));
331 
332     List<TColumn> columns = new ArrayList<TColumn>();
333     long rowTimestamp = in.getTimeStamp();
334     if (rowTimestamp != HConstants.LATEST_TIMESTAMP) {
335       out.setTimestamp(rowTimestamp);
336     }
337 
338     // Map<family, List<KeyValue>>
339     for (Map.Entry<byte[], List<org.apache.hadoop.hbase.Cell>> familyEntry:
340         in.getFamilyCellMap().entrySet()) {
341       TColumn column = new TColumn(ByteBuffer.wrap(familyEntry.getKey()));
342       for (org.apache.hadoop.hbase.Cell cell: familyEntry.getValue()) {
343         byte[] family = CellUtil.cloneFamily(cell);
344         byte[] qualifier = CellUtil.cloneQualifier(cell);
345         long timestamp = cell.getTimestamp();
346         if (family != null) {
347           column.setFamily(family);
348         }
349         if (qualifier != null) {
350           column.setQualifier(qualifier);
351         }
352         if (timestamp != HConstants.LATEST_TIMESTAMP) {
353           column.setTimestamp(timestamp);
354         }
355       }
356       columns.add(column);
357     }
358     out.setColumns(columns);
359 
360     return out;
361   }
362 
363   /**
364    * Creates a {@link RowMutations} (HBase) from a {@link TRowMutations} (Thrift)
365    *
366    * @param in the <code>TRowMutations</code> to convert
367    *
368    * @return converted <code>RowMutations</code>
369    */
370   public static RowMutations rowMutationsFromThrift(TRowMutations in) throws IOException {
371     RowMutations out = new RowMutations(in.getRow());
372     List<TMutation> mutations = in.getMutations();
373     for (TMutation mutation : mutations) {
374       if (mutation.isSetPut()) {
375         out.add(putFromThrift(mutation.getPut()));
376       }
377       if (mutation.isSetDeleteSingle()) {
378         out.add(deleteFromThrift(mutation.getDeleteSingle()));
379       }
380     }
381     return out;
382   }
383 
384   public static Scan scanFromThrift(TScan in) throws IOException {
385     Scan out = new Scan();
386 
387     if (in.isSetStartRow())
388       out.setStartRow(in.getStartRow());
389     if (in.isSetStopRow())
390       out.setStopRow(in.getStopRow());
391     if (in.isSetCaching())
392       out.setCaching(in.getCaching());
393     if (in.isSetMaxVersions()) {
394       out.setMaxVersions(in.getMaxVersions());
395     }
396 
397     if (in.isSetColumns()) {
398       for (TColumn column : in.getColumns()) {
399         if (column.isSetQualifier()) {
400           out.addColumn(column.getFamily(), column.getQualifier());
401         } else {
402           out.addFamily(column.getFamily());
403         }
404       }
405     }
406 
407     TTimeRange timeRange = in.getTimeRange();
408     if (timeRange != null &&
409         timeRange.isSetMinStamp() && timeRange.isSetMaxStamp()) {
410       out.setTimeRange(timeRange.getMinStamp(), timeRange.getMaxStamp());
411     }
412 
413     if (in.isSetBatchSize()) {
414       out.setBatch(in.getBatchSize());
415     }
416 
417     if (in.isSetFilterString()) {
418       ParseFilter parseFilter = new ParseFilter();
419       out.setFilter(parseFilter.parseFilterString(in.getFilterString()));
420     }
421 
422     if (in.isSetAttributes()) {
423       addAttributes(out,in.getAttributes());
424     }
425     
426     if (in.isSetAuthorizations()) {
427       out.setAuthorizations(new Authorizations(in.getAuthorizations().getLabels()));
428     }
429 
430     if (in.isSetReversed()) {
431       out.setReversed(in.isReversed());
432     }
433 
434     if (in.isSetCacheBlocks()) {
435       out.setCacheBlocks(in.isCacheBlocks());
436     }
437 
438     return out;
439   }
440 
441   public static Increment incrementFromThrift(TIncrement in) throws IOException {
442     Increment out = new Increment(in.getRow());
443     for (TColumnIncrement column : in.getColumns()) {
444       out.addColumn(column.getFamily(), column.getQualifier(), column.getAmount());
445     }
446 
447     if (in.isSetAttributes()) {
448       addAttributes(out,in.getAttributes());
449     }
450 
451     if (in.isSetDurability()) {
452       out.setDurability(durabilityFromThrift(in.getDurability()));
453     }
454     
455     if(in.getCellVisibility() != null) {
456       out.setCellVisibility(new CellVisibility(in.getCellVisibility().getExpression()));
457     }
458 
459     return out;
460   }
461 
462   public static Append appendFromThrift(TAppend append) throws IOException {
463     Append out = new Append(append.getRow());
464     for (TColumnValue column : append.getColumns()) {
465       out.add(column.getFamily(), column.getQualifier(), column.getValue());
466     }
467 
468     if (append.isSetAttributes()) {
469       addAttributes(out, append.getAttributes());
470     }
471 
472     if (append.isSetDurability()) {
473       out.setDurability(durabilityFromThrift(append.getDurability()));
474     }
475     
476     if(append.getCellVisibility() != null) {
477       out.setCellVisibility(new CellVisibility(append.getCellVisibility().getExpression()));
478     }
479 
480     return out;
481   }
482 
483   public static THRegionLocation regionLocationFromHBase(HRegionLocation hrl) {
484     HRegionInfo hri = hrl.getRegionInfo();
485     ServerName serverName = hrl.getServerName();
486 
487     THRegionInfo thRegionInfo = new THRegionInfo();
488     THRegionLocation thRegionLocation = new THRegionLocation();
489     TServerName tServerName = new TServerName();
490 
491     tServerName.setHostName(serverName.getHostname());
492     tServerName.setPort(serverName.getPort());
493     tServerName.setStartCode(serverName.getStartcode());
494 
495     thRegionInfo.setTableName(hri.getTable().getName());
496     thRegionInfo.setEndKey(hri.getEndKey());
497     thRegionInfo.setStartKey(hri.getStartKey());
498     thRegionInfo.setOffline(hri.isOffline());
499     thRegionInfo.setSplit(hri.isSplit());
500     thRegionInfo.setReplicaId(hri.getReplicaId());
501 
502     thRegionLocation.setRegionInfo(thRegionInfo);
503     thRegionLocation.setServerName(tServerName);
504 
505     return thRegionLocation;
506   }
507 
508   public static List<THRegionLocation> regionLocationsFromHBase(List<HRegionLocation> locations) {
509     List<THRegionLocation> tlocations = new ArrayList<THRegionLocation>(locations.size());
510     for (HRegionLocation hrl:locations) {
511       tlocations.add(regionLocationFromHBase(hrl));
512     }
513     return tlocations;
514   }
515 
516   /**
517    * Adds all the attributes into the Operation object
518    */
519   private static void addAttributes(OperationWithAttributes op,
520                                     Map<ByteBuffer, ByteBuffer> attributes) {
521     if (attributes == null || attributes.size() == 0) {
522       return;
523     }
524     for (Map.Entry<ByteBuffer, ByteBuffer> entry : attributes.entrySet()) {
525       String name = Bytes.toStringBinary(getBytes(entry.getKey()));
526       byte[] value =  getBytes(entry.getValue());
527       op.setAttribute(name, value);
528     }
529   }
530 
531   private static Durability durabilityFromThrift(TDurability tDurability) {
532     switch (tDurability.getValue()) {
533       case 1: return Durability.SKIP_WAL;
534       case 2: return Durability.ASYNC_WAL;
535       case 3: return Durability.SYNC_WAL;
536       case 4: return Durability.FSYNC_WAL;
537       default: return null;
538     }
539   }
540 
541   public static CompareOp compareOpFromThrift(TCompareOp tCompareOp) {
542     switch (tCompareOp.getValue()) {
543       case 0: return CompareOp.LESS;
544       case 1: return CompareOp.LESS_OR_EQUAL;
545       case 2: return CompareOp.EQUAL;
546       case 3: return CompareOp.NOT_EQUAL;
547       case 4: return CompareOp.GREATER_OR_EQUAL;
548       case 5: return CompareOp.GREATER;
549       case 6: return CompareOp.NO_OP;
550       default: return null;
551     }
552   }
553 }