View Javadoc

1   /**
2    * Copyright 2011 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.thrift2;
21  
22  import org.apache.hadoop.hbase.HConstants;
23  import org.apache.hadoop.hbase.KeyValue;
24  import org.apache.hadoop.hbase.client.*;
25  import org.apache.hadoop.hbase.filter.ParseFilter;
26  import org.apache.hadoop.hbase.thrift2.generated.*;
27  import org.apache.hadoop.hbase.util.Bytes;
28  
29  import java.io.IOException;
30  import java.nio.ByteBuffer;
31  import java.util.*;
32  
33  import static org.apache.hadoop.hbase.util.Bytes.getBytes;
34  
35  public class ThriftUtilities {
36  
37    private ThriftUtilities() {
38      throw new UnsupportedOperationException("Can't initialize class");
39    }
40  
41    /**
42     * Creates a {@link Get} (HBase) from a {@link TGet} (Thrift).
43     * 
44     * This ignores any timestamps set on {@link TColumn} objects.
45     * 
46     * @param in the <code>TGet</code> to convert
47     * 
48     * @return <code>Get</code> object
49     * 
50     * @throws IOException if an invalid time range or max version parameter is given
51     */
52    public static Get getFromThrift(TGet in) throws IOException {
53      Get out = new Get(in.getRow());
54  
55      // Timestamp overwrites time range if both are set
56      if (in.isSetTimestamp()) {
57        out.setTimeStamp(in.getTimestamp());
58      } else if (in.isSetTimeRange()) {
59        out.setTimeRange(in.getTimeRange().getMinStamp(), in.getTimeRange().getMaxStamp());
60      }
61  
62      if (in.isSetMaxVersions()) {
63        out.setMaxVersions(in.getMaxVersions());
64      }
65  
66      if (in.isSetFilterString()) {
67        ParseFilter parseFilter = new ParseFilter();
68        out.setFilter(parseFilter.parseFilterString(in.getFilterString()));
69      }
70  
71      if (in.isSetAttributes()) {
72        addAttributes(out,in.getAttributes());
73      }
74  
75      if (!in.isSetColumns()) {
76        return out;
77      }
78  
79      for (TColumn column : in.getColumns()) {
80        if (column.isSetQualifier()) {
81          out.addColumn(column.getFamily(), column.getQualifier());
82        } else {
83          out.addFamily(column.getFamily());
84        }
85      }
86  
87      return out;
88    }
89  
90    /**
91     * Converts multiple {@link TGet}s (Thrift) into a list of {@link Get}s (HBase).
92     * 
93     * @param in list of <code>TGet</code>s to convert
94     * 
95     * @return list of <code>Get</code> objects
96     * 
97     * @throws IOException if an invalid time range or max version parameter is given
98     * @see #getFromThrift(TGet)
99     */
100   public static List<Get> getsFromThrift(List<TGet> in) throws IOException {
101     List<Get> out = new ArrayList<Get>(in.size());
102     for (TGet get : in) {
103       out.add(getFromThrift(get));
104     }
105     return out;
106   }
107 
108   /**
109    * Creates a {@link TResult} (Thrift) from a {@link Result} (HBase).
110    * 
111    * @param in the <code>Result</code> to convert
112    * 
113    * @return converted result, returns an empty result if the input is <code>null</code>
114    */
115   public static TResult resultFromHBase(Result in) {
116     KeyValue[] raw = in.raw();
117     TResult out = new TResult();
118     byte[] row = in.getRow();
119     if (row != null) {
120       out.setRow(in.getRow());
121     }
122     List<TColumnValue> columnValues = new ArrayList<TColumnValue>();
123     for (KeyValue kv : raw) {
124       TColumnValue col = new TColumnValue();
125       col.setFamily(kv.getFamily());
126       col.setQualifier(kv.getQualifier());
127       col.setTimestamp(kv.getTimestamp());
128       col.setValue(kv.getValue());
129       columnValues.add(col);
130     }
131     out.setColumnValues(columnValues);
132     return out;
133   }
134 
135   /**
136    * Converts multiple {@link Result}s (HBase) into a list of {@link TResult}s (Thrift).
137    * 
138    * @param in array of <code>Result</code>s to convert
139    * 
140    * @return list of converted <code>TResult</code>s
141    * 
142    * @see #resultFromHBase(Result)
143    */
144   public static List<TResult> resultsFromHBase(Result[] in) {
145     List<TResult> out = new ArrayList<TResult>(in.length);
146     for (Result result : in) {
147       out.add(resultFromHBase(result));
148     }
149     return out;
150   }
151 
152   /**
153    * Creates a {@link Put} (HBase) from a {@link TPut} (Thrift)
154    * 
155    * @param in the <code>TPut</code> to convert
156    * 
157    * @return converted <code>Put</code>
158    */
159   public static Put putFromThrift(TPut in) {
160     Put out;
161 
162     if (in.isSetTimestamp()) {
163       out = new Put(in.getRow(), in.getTimestamp(), null);
164     } else {
165       out = new Put(in.getRow());
166     }
167 
168     if (in.isSetDurability()) {
169       out.setDurability(durabilityFromThrift(in.getDurability()));
170     } else if (in.isSetWriteToWal()) {
171       out.setWriteToWAL(in.isWriteToWal());
172     }
173 
174     for (TColumnValue columnValue : in.getColumnValues()) {
175       if (columnValue.isSetTimestamp()) {
176         out.add(columnValue.getFamily(), columnValue.getQualifier(), columnValue.getTimestamp(),
177             columnValue.getValue());
178       } else {
179         out.add(columnValue.getFamily(), columnValue.getQualifier(), columnValue.getValue());
180       }
181     }
182 
183     if (in.isSetAttributes()) {
184       addAttributes(out,in.getAttributes());
185     }
186 
187     return out;
188   }
189 
190   /**
191    * Converts multiple {@link TPut}s (Thrift) into a list of {@link Put}s (HBase).
192    * 
193    * @param in list of <code>TPut</code>s to convert
194    * 
195    * @return list of converted <code>Put</code>s
196    * 
197    * @see #putFromThrift(TPut)
198    */
199   public static List<Put> putsFromThrift(List<TPut> in) {
200     List<Put> out = new ArrayList<Put>(in.size());
201     for (TPut put : in) {
202       out.add(putFromThrift(put));
203     }
204     return out;
205   }
206 
207   /**
208    * Creates a {@link Delete} (HBase) from a {@link TDelete} (Thrift).
209    * 
210    * @param in the <code>TDelete</code> to convert
211    * 
212    * @return converted <code>Delete</code>
213    */
214   public static Delete deleteFromThrift(TDelete in) {
215     Delete out;
216 
217     if (in.isSetColumns()) {
218       out = new Delete(in.getRow());
219       for (TColumn column : in.getColumns()) {
220         if (column.isSetQualifier()) {
221           if (column.isSetTimestamp()) {
222             if (in.isSetDeleteType() &&
223                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
224               out.deleteColumns(column.getFamily(), column.getQualifier(), column.getTimestamp());
225             else
226               out.deleteColumn(column.getFamily(), column.getQualifier(), column.getTimestamp());
227           } else {
228             if (in.isSetDeleteType() &&
229                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
230               out.deleteColumns(column.getFamily(), column.getQualifier());
231             else
232               out.deleteColumn(column.getFamily(), column.getQualifier());
233           }
234 
235         } else {
236           if (column.isSetTimestamp()) {
237             out.deleteFamily(column.getFamily(), column.getTimestamp());
238           } else {
239             out.deleteFamily(column.getFamily());
240           }
241         }
242       }
243     } else {
244       if (in.isSetTimestamp()) {
245         out = new Delete(in.getRow(), in.getTimestamp(), null);
246       } else {
247         out = new Delete(in.getRow());
248       }
249     }
250 
251     if (in.isSetAttributes()) {
252       addAttributes(out,in.getAttributes());
253     }
254 
255     if (in.isSetDurability()) {
256       out.setDurability(durabilityFromThrift(in.getDurability()));
257     } else if (in.isSetWriteToWal()) {
258       out.setWriteToWAL(in.isWriteToWal());
259     }
260 
261     return out;
262   }
263 
264   /**
265    * Converts multiple {@link TDelete}s (Thrift) into a list of {@link Delete}s (HBase).
266    * 
267    * @param in list of <code>TDelete</code>s to convert
268    * 
269    * @return list of converted <code>Delete</code>s
270    * 
271    * @see #deleteFromThrift(TDelete)
272    */
273 
274   public static List<Delete> deletesFromThrift(List<TDelete> in) {
275     List<Delete> out = new ArrayList<Delete>(in.size());
276     for (TDelete delete : in) {
277       out.add(deleteFromThrift(delete));
278     }
279     return out;
280   }
281 
282   public static TDelete deleteFromHBase(Delete in) {
283     TDelete out = new TDelete(ByteBuffer.wrap(in.getRow()));
284 
285     List<TColumn> columns = new ArrayList<TColumn>();
286     long rowTimestamp = in.getTimeStamp();
287     if (rowTimestamp != HConstants.LATEST_TIMESTAMP) {
288       out.setTimestamp(rowTimestamp);
289     }
290 
291     // Map<family, List<KeyValue>>
292     for (Map.Entry<byte[], List<KeyValue>> familyEntry : in.getFamilyMap().entrySet()) {
293       TColumn column = new TColumn(ByteBuffer.wrap(familyEntry.getKey()));
294       for (KeyValue keyValue : familyEntry.getValue()) {
295         byte[] family = keyValue.getFamily();
296         byte[] qualifier = keyValue.getQualifier();
297         long timestamp = keyValue.getTimestamp();
298         if (family != null) {
299           column.setFamily(family);
300         }
301         if (qualifier != null) {
302           column.setQualifier(qualifier);
303         }
304         if (timestamp != HConstants.LATEST_TIMESTAMP) {
305           column.setTimestamp(keyValue.getTimestamp());
306         }
307       }
308       columns.add(column);
309     }
310     out.setColumns(columns);
311 
312     return out;
313   }
314 
315   public static List<TDelete> deletesFromHBase(List<Delete> in) {
316     List<TDelete> out = new ArrayList<TDelete>(in.size());
317     for (Delete delete : in) {
318       if (delete == null) {
319         out.add(null);
320       } else {
321         out.add(deleteFromHBase(delete));
322       }
323     }
324     return out;
325   }
326 
327   /**
328    * Creates a {@link RowMutations} (HBase) from a {@link TRowMutations} (Thrift)
329    *
330    * @param in the <code>TRowMutations</code> to convert
331    *
332    * @return converted <code>RowMutations</code>
333    */
334   public static RowMutations rowMutationsFromThrift(TRowMutations in) throws IOException {
335     RowMutations out = new RowMutations(in.getRow());
336     List<TMutation> mutations = in.getMutations();
337     for (TMutation mutation : mutations) {
338       if (mutation.isSetPut()) {
339         out.add(putFromThrift(mutation.getPut()));
340       }
341       if (mutation.isSetDeleteSingle()) {
342         out.add(deleteFromThrift(mutation.getDeleteSingle()));
343       }
344     }
345     return out;
346   }
347 
348   public static Scan scanFromThrift(TScan in) throws IOException {
349     Scan out = new Scan();
350 
351     if (in.isSetStartRow())
352       out.setStartRow(in.getStartRow());
353     if (in.isSetStopRow())
354       out.setStopRow(in.getStopRow());
355     if (in.isSetCaching())
356       out.setCaching(in.getCaching());
357     if (in.isSetMaxVersions()) {
358       out.setMaxVersions(in.getMaxVersions());
359     }
360 
361     if (in.isSetColumns()) {
362       for (TColumn column : in.getColumns()) {
363         if (column.isSetQualifier()) {
364           out.addColumn(column.getFamily(), column.getQualifier());
365         } else {
366           out.addFamily(column.getFamily());
367         }
368       }
369     }
370 
371     TTimeRange timeRange = in.getTimeRange();
372     if (timeRange != null &&
373         timeRange.isSetMinStamp() && timeRange.isSetMaxStamp()) {
374       out.setTimeRange(timeRange.getMinStamp(), timeRange.getMaxStamp());
375     }
376 
377     if (in.isSetBatchSize()) {
378       out.setBatch(in.getBatchSize());
379     }
380 
381     if (in.isSetFilterString()) {
382       ParseFilter parseFilter = new ParseFilter();
383       out.setFilter(parseFilter.parseFilterString(in.getFilterString()));
384     }
385 
386     if (in.isSetAttributes()) {
387       addAttributes(out,in.getAttributes());
388     }
389 
390     return out;
391   }
392 
393   public static Increment incrementFromThrift(TIncrement in) throws IOException {
394     Increment out = new Increment(in.getRow());
395     for (TColumnIncrement column : in.getColumns()) {
396       out.addColumn(column.getFamily(), column.getQualifier(), column.getAmount());
397     }
398 
399     out.setWriteToWAL(in.isWriteToWal());
400     return out;
401   }
402 
403   /**
404    * Adds all the attributes into the Operation object
405    */
406   private static void addAttributes(OperationWithAttributes op,
407                                     Map<ByteBuffer, ByteBuffer> attributes) {
408     if (attributes == null || attributes.size() == 0) {
409       return;
410     }
411     for (Map.Entry<ByteBuffer, ByteBuffer> entry : attributes.entrySet()) {
412       String name = Bytes.toStringBinary(getBytes(entry.getKey()));
413       byte[] value =  getBytes(entry.getValue());
414       op.setAttribute(name, value);
415     }
416   }
417 
418   private static Durability durabilityFromThrift(TDurability tDurability) {
419     switch (tDurability.getValue()) {
420       case 1: return Durability.SKIP_WAL;
421       case 2: return Durability.ASYNC_WAL;
422       case 3: return Durability.SYNC_WAL;
423       case 4: return Durability.FSYNC_WAL;
424       default: return null;
425     }
426   }
427 }