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     out.setWriteToWAL(in.isWriteToWal());
169 
170     for (TColumnValue columnValue : in.getColumnValues()) {
171       if (columnValue.isSetTimestamp()) {
172         out.add(columnValue.getFamily(), columnValue.getQualifier(), columnValue.getTimestamp(),
173             columnValue.getValue());
174       } else {
175         out.add(columnValue.getFamily(), columnValue.getQualifier(), columnValue.getValue());
176       }
177     }
178 
179     if (in.isSetAttributes()) {
180       addAttributes(out,in.getAttributes());
181     }
182 
183     return out;
184   }
185 
186   /**
187    * Converts multiple {@link TPut}s (Thrift) into a list of {@link Put}s (HBase).
188    * 
189    * @param in list of <code>TPut</code>s to convert
190    * 
191    * @return list of converted <code>Put</code>s
192    * 
193    * @see #putFromThrift(TPut)
194    */
195   public static List<Put> putsFromThrift(List<TPut> in) {
196     List<Put> out = new ArrayList<Put>(in.size());
197     for (TPut put : in) {
198       out.add(putFromThrift(put));
199     }
200     return out;
201   }
202 
203   /**
204    * Creates a {@link Delete} (HBase) from a {@link TDelete} (Thrift).
205    * 
206    * @param in the <code>TDelete</code> to convert
207    * 
208    * @return converted <code>Delete</code>
209    */
210   public static Delete deleteFromThrift(TDelete in) {
211     Delete out;
212 
213     if (in.isSetColumns()) {
214       out = new Delete(in.getRow());
215       for (TColumn column : in.getColumns()) {
216         if (column.isSetQualifier()) {
217           if (column.isSetTimestamp()) {
218             if (in.isSetDeleteType() &&
219                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
220               out.deleteColumns(column.getFamily(), column.getQualifier(), column.getTimestamp());
221             else
222               out.deleteColumn(column.getFamily(), column.getQualifier(), column.getTimestamp());
223           } else {
224             if (in.isSetDeleteType() &&
225                 in.getDeleteType().equals(TDeleteType.DELETE_COLUMNS))
226               out.deleteColumns(column.getFamily(), column.getQualifier());
227             else
228               out.deleteColumn(column.getFamily(), column.getQualifier());
229           }
230 
231         } else {
232           if (column.isSetTimestamp()) {
233             out.deleteFamily(column.getFamily(), column.getTimestamp());
234           } else {
235             out.deleteFamily(column.getFamily());
236           }
237         }
238       }
239     } else {
240       if (in.isSetTimestamp()) {
241         out = new Delete(in.getRow(), in.getTimestamp(), null);
242       } else {
243         out = new Delete(in.getRow());
244       }
245     }
246 
247     if (in.isSetAttributes()) {
248       addAttributes(out,in.getAttributes());
249     }
250 
251     out.setWriteToWAL(in.isWriteToWal());
252     return out;
253   }
254 
255   /**
256    * Converts multiple {@link TDelete}s (Thrift) into a list of {@link Delete}s (HBase).
257    * 
258    * @param in list of <code>TDelete</code>s to convert
259    * 
260    * @return list of converted <code>Delete</code>s
261    * 
262    * @see #deleteFromThrift(TDelete)
263    */
264 
265   public static List<Delete> deletesFromThrift(List<TDelete> in) {
266     List<Delete> out = new ArrayList<Delete>(in.size());
267     for (TDelete delete : in) {
268       out.add(deleteFromThrift(delete));
269     }
270     return out;
271   }
272 
273   public static TDelete deleteFromHBase(Delete in) {
274     TDelete out = new TDelete(ByteBuffer.wrap(in.getRow()));
275 
276     List<TColumn> columns = new ArrayList<TColumn>();
277     long rowTimestamp = in.getTimeStamp();
278     if (rowTimestamp != HConstants.LATEST_TIMESTAMP) {
279       out.setTimestamp(rowTimestamp);
280     }
281 
282     // Map<family, List<KeyValue>>
283     for (Map.Entry<byte[], List<KeyValue>> familyEntry : in.getFamilyMap().entrySet()) {
284       TColumn column = new TColumn(ByteBuffer.wrap(familyEntry.getKey()));
285       for (KeyValue keyValue : familyEntry.getValue()) {
286         byte[] family = keyValue.getFamily();
287         byte[] qualifier = keyValue.getQualifier();
288         long timestamp = keyValue.getTimestamp();
289         if (family != null) {
290           column.setFamily(family);
291         }
292         if (qualifier != null) {
293           column.setQualifier(qualifier);
294         }
295         if (timestamp != HConstants.LATEST_TIMESTAMP) {
296           column.setTimestamp(keyValue.getTimestamp());
297         }
298       }
299       columns.add(column);
300     }
301     out.setColumns(columns);
302 
303     return out;
304   }
305 
306   public static List<TDelete> deletesFromHBase(List<Delete> in) {
307     List<TDelete> out = new ArrayList<TDelete>(in.size());
308     for (Delete delete : in) {
309       if (delete == null) {
310         out.add(null);
311       } else {
312         out.add(deleteFromHBase(delete));
313       }
314     }
315     return out;
316   }
317 
318   /**
319    * Creates a {@link RowMutations} (HBase) from a {@link TRowMutations} (Thrift)
320    *
321    * @param in the <code>TRowMutations</code> to convert
322    *
323    * @return converted <code>RowMutations</code>
324    */
325   public static RowMutations rowMutationsFromThrift(TRowMutations in) throws IOException {
326     RowMutations out = new RowMutations(in.getRow());
327     List<TMutation> mutations = in.getMutations();
328     for (TMutation mutation : mutations) {
329       if (mutation.isSetPut()) {
330         out.add(putFromThrift(mutation.getPut()));
331       }
332       if (mutation.isSetDeleteSingle()) {
333         out.add(deleteFromThrift(mutation.getDeleteSingle()));
334       }
335     }
336     return out;
337   }
338 
339   public static Scan scanFromThrift(TScan in) throws IOException {
340     Scan out = new Scan();
341 
342     if (in.isSetStartRow())
343       out.setStartRow(in.getStartRow());
344     if (in.isSetStopRow())
345       out.setStopRow(in.getStopRow());
346     if (in.isSetCaching())
347       out.setCaching(in.getCaching());
348     if (in.isSetMaxVersions()) {
349       out.setMaxVersions(in.getMaxVersions());
350     }
351 
352     if (in.isSetColumns()) {
353       for (TColumn column : in.getColumns()) {
354         if (column.isSetQualifier()) {
355           out.addColumn(column.getFamily(), column.getQualifier());
356         } else {
357           out.addFamily(column.getFamily());
358         }
359       }
360     }
361 
362     TTimeRange timeRange = in.getTimeRange();
363     if (timeRange != null &&
364         timeRange.isSetMinStamp() && timeRange.isSetMaxStamp()) {
365       out.setTimeRange(timeRange.getMinStamp(), timeRange.getMaxStamp());
366     }
367 
368     if (in.isSetBatchSize()) {
369       out.setBatch(in.getBatchSize());
370     }
371 
372     if (in.isSetFilterString()) {
373       ParseFilter parseFilter = new ParseFilter();
374       out.setFilter(parseFilter.parseFilterString(in.getFilterString()));
375     }
376 
377     if (in.isSetAttributes()) {
378       addAttributes(out,in.getAttributes());
379     }
380 
381     return out;
382   }
383 
384   public static Increment incrementFromThrift(TIncrement in) throws IOException {
385     Increment out = new Increment(in.getRow());
386     for (TColumnIncrement column : in.getColumns()) {
387       out.addColumn(column.getFamily(), column.getQualifier(), column.getAmount());
388     }
389 
390     out.setWriteToWAL(in.isWriteToWal());
391     return out;
392   }
393 
394   /**
395    * Adds all the attributes into the Operation object
396    */
397   private static void addAttributes(OperationWithAttributes op,
398                                     Map<ByteBuffer, ByteBuffer> attributes) {
399     if (attributes == null || attributes.size() == 0) {
400       return;
401     }
402     for (Map.Entry<ByteBuffer, ByteBuffer> entry : attributes.entrySet()) {
403       String name = Bytes.toStringBinary(getBytes(entry.getKey()));
404       byte[] value =  getBytes(entry.getValue());
405       op.setAttribute(name, value);
406     }
407   }
408 }