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  package org.apache.hadoop.hbase.protobuf;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import com.google.protobuf.HBaseZeroCopyByteString;
24  import org.apache.hadoop.classification.InterfaceAudience;
25  import org.apache.hadoop.hbase.CellScannable;
26  import org.apache.hadoop.hbase.DoNotRetryIOException;
27  import org.apache.hadoop.hbase.HColumnDescriptor;
28  import org.apache.hadoop.hbase.HRegionInfo;
29  import org.apache.hadoop.hbase.HTableDescriptor;
30  import org.apache.hadoop.hbase.ServerName;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.client.Action;
33  import org.apache.hadoop.hbase.client.Append;
34  import org.apache.hadoop.hbase.client.Delete;
35  import org.apache.hadoop.hbase.client.Durability;
36  import org.apache.hadoop.hbase.client.Get;
37  import org.apache.hadoop.hbase.client.Increment;
38  import org.apache.hadoop.hbase.client.Mutation;
39  import org.apache.hadoop.hbase.client.Put;
40  import org.apache.hadoop.hbase.client.Row;
41  import org.apache.hadoop.hbase.client.RowMutations;
42  import org.apache.hadoop.hbase.client.Scan;
43  import org.apache.hadoop.hbase.exceptions.DeserializationException;
44  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
45  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
46  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
47  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
48  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
49  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
50  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
51  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
52  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
53  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsRequest;
54  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
55  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest.RegionOpenInfo;
56  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
57  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
58  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
59  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest;
60  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest.RegionUpdateInfo;
61  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
62  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
63  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest.FamilyPath;
64  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Column;
65  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition;
66  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
67  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
68  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
69  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue;
70  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue.QualifierValue;
71  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
72  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
73  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
74  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.CompareType;
75  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
76  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
77  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
78  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
79  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceRequest;
80  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
81  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
82  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
83  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
84  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
85  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
86  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
87  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
88  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
89  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
90  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
91  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningRequest;
92  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
93  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
94  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
95  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionRequest;
96  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
97  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
98  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
99  import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest;
100 import org.apache.hadoop.hbase.util.Bytes;
101 import org.apache.hadoop.hbase.util.Pair;
102 import org.apache.hadoop.hbase.util.Triple;
103 
104 import com.google.protobuf.ByteString;
105 
106 /**
107  * Helper utility to build protocol buffer requests,
108  * or build components for protocol buffer requests.
109  */
110 @InterfaceAudience.Private
111 public final class RequestConverter {
112 
113   private RequestConverter() {
114   }
115 
116 // Start utilities for Client
117 
118 /**
119    * Create a new protocol buffer GetRequest to get a row, all columns in a family.
120    * If there is no such row, return the closest row before it.
121    *
122    * @param regionName the name of the region to get
123    * @param row the row to get
124    * @param family the column family to get
125    * should return the immediate row before
126    * @return a protocol buffer GetReuqest
127    */
128   public static GetRequest buildGetRowOrBeforeRequest(
129       final byte[] regionName, final byte[] row, final byte[] family) {
130     GetRequest.Builder builder = GetRequest.newBuilder();
131     RegionSpecifier region = buildRegionSpecifier(
132       RegionSpecifierType.REGION_NAME, regionName);
133     builder.setRegion(region);
134 
135     Column.Builder columnBuilder = Column.newBuilder();
136     columnBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
137     ClientProtos.Get.Builder getBuilder =
138       ClientProtos.Get.newBuilder();
139     getBuilder.setRow(HBaseZeroCopyByteString.wrap(row));
140     getBuilder.addColumn(columnBuilder.build());
141     getBuilder.setClosestRowBefore(true);
142     builder.setGet(getBuilder.build());
143     return builder.build();
144   }
145 
146 
147   /**
148    * Create a protocol buffer GetRequest for a client Get
149    *
150    * @param regionName the name of the region to get
151    * @param get the client Get
152    * @return a protocol buffer GetRequest
153    */
154   public static GetRequest buildGetRequest(final byte[] regionName,
155       final Get get) throws IOException {
156     GetRequest.Builder builder = GetRequest.newBuilder();
157     RegionSpecifier region = buildRegionSpecifier(
158       RegionSpecifierType.REGION_NAME, regionName);
159     builder.setRegion(region);
160     builder.setGet(ProtobufUtil.toGet(get));
161     return builder.build();
162   }
163 
164   /**
165    * Create a protocol buffer MutateRequest for a client increment
166    *
167    * @param regionName
168    * @param row
169    * @param family
170    * @param qualifier
171    * @param amount
172    * @param durability
173    * @return a mutate request
174    */
175   public static MutateRequest buildMutateRequest(
176       final byte[] regionName, final byte[] row, final byte[] family,
177       final byte [] qualifier, final long amount, final Durability durability) {
178     MutateRequest.Builder builder = MutateRequest.newBuilder();
179     RegionSpecifier region = buildRegionSpecifier(
180       RegionSpecifierType.REGION_NAME, regionName);
181     builder.setRegion(region);
182 
183     MutationProto.Builder mutateBuilder = MutationProto.newBuilder();
184     mutateBuilder.setRow(HBaseZeroCopyByteString.wrap(row));
185     mutateBuilder.setMutateType(MutationType.INCREMENT);
186     mutateBuilder.setDurability(ProtobufUtil.toDurability(durability));
187     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
188     columnBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
189     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
190     valueBuilder.setValue(HBaseZeroCopyByteString.wrap(Bytes.toBytes(amount)));
191     valueBuilder.setQualifier(HBaseZeroCopyByteString.wrap(qualifier));
192     columnBuilder.addQualifierValue(valueBuilder.build());
193     mutateBuilder.addColumnValue(columnBuilder.build());
194     builder.setMutation(mutateBuilder.build());
195     return builder.build();
196   }
197 
198   /**
199    * Create a protocol buffer MutateRequest for a conditioned put
200    *
201    * @param regionName
202    * @param row
203    * @param family
204    * @param qualifier
205    * @param comparator
206    * @param compareType
207    * @param put
208    * @return a mutate request
209    * @throws IOException
210    */
211   public static MutateRequest buildMutateRequest(
212       final byte[] regionName, final byte[] row, final byte[] family,
213       final byte [] qualifier, final ByteArrayComparable comparator,
214       final CompareType compareType, final Put put) throws IOException {
215     MutateRequest.Builder builder = MutateRequest.newBuilder();
216     RegionSpecifier region = buildRegionSpecifier(
217       RegionSpecifierType.REGION_NAME, regionName);
218     builder.setRegion(region);
219     Condition condition = buildCondition(
220       row, family, qualifier, comparator, compareType);
221     builder.setMutation(ProtobufUtil.toMutation(MutationType.PUT, put, MutationProto.newBuilder()));
222     builder.setCondition(condition);
223     return builder.build();
224   }
225 
226   /**
227    * Create a protocol buffer MutateRequest for a conditioned delete
228    *
229    * @param regionName
230    * @param row
231    * @param family
232    * @param qualifier
233    * @param comparator
234    * @param compareType
235    * @param delete
236    * @return a mutate request
237    * @throws IOException
238    */
239   public static MutateRequest buildMutateRequest(
240       final byte[] regionName, final byte[] row, final byte[] family,
241       final byte [] qualifier, final ByteArrayComparable comparator,
242       final CompareType compareType, final Delete delete) throws IOException {
243     MutateRequest.Builder builder = MutateRequest.newBuilder();
244     RegionSpecifier region = buildRegionSpecifier(
245       RegionSpecifierType.REGION_NAME, regionName);
246     builder.setRegion(region);
247     Condition condition = buildCondition(
248       row, family, qualifier, comparator, compareType);
249     builder.setMutation(ProtobufUtil.toMutation(MutationType.DELETE, delete,
250       MutationProto.newBuilder()));
251     builder.setCondition(condition);
252     return builder.build();
253   }
254 
255   /**
256    * Create a protocol buffer MutateRequest for a put
257    *
258    * @param regionName
259    * @param put
260    * @return a mutate request
261    * @throws IOException
262    */
263   public static MutateRequest buildMutateRequest(
264       final byte[] regionName, final Put put) throws IOException {
265     MutateRequest.Builder builder = MutateRequest.newBuilder();
266     RegionSpecifier region = buildRegionSpecifier(
267       RegionSpecifierType.REGION_NAME, regionName);
268     builder.setRegion(region);
269     builder.setMutation(ProtobufUtil.toMutation(MutationType.PUT, put, MutationProto.newBuilder()));
270     return builder.build();
271   }
272 
273   /**
274    * Create a protocol buffer MutateRequest for an append
275    *
276    * @param regionName
277    * @param append
278    * @return a mutate request
279    * @throws IOException
280    */
281   public static MutateRequest buildMutateRequest(
282       final byte[] regionName, final Append append) throws IOException {
283     MutateRequest.Builder builder = MutateRequest.newBuilder();
284     RegionSpecifier region = buildRegionSpecifier(
285       RegionSpecifierType.REGION_NAME, regionName);
286     builder.setRegion(region);
287     builder.setMutation(ProtobufUtil.toMutation(MutationType.APPEND, append,
288       MutationProto.newBuilder()));
289     return builder.build();
290   }
291 
292   /**
293    * Create a protocol buffer MutateRequest for a client increment
294    *
295    * @param regionName
296    * @param increment
297    * @return a mutate request
298    */
299   public static MutateRequest buildMutateRequest(
300       final byte[] regionName, final Increment increment) {
301     MutateRequest.Builder builder = MutateRequest.newBuilder();
302     RegionSpecifier region = buildRegionSpecifier(
303       RegionSpecifierType.REGION_NAME, regionName);
304     builder.setRegion(region);
305     builder.setMutation(ProtobufUtil.toMutation(increment, MutationProto.newBuilder()));
306     return builder.build();
307   }
308 
309   /**
310    * Create a protocol buffer MutateRequest for a delete
311    *
312    * @param regionName
313    * @param delete
314    * @return a mutate request
315    * @throws IOException
316    */
317   public static MutateRequest buildMutateRequest(
318       final byte[] regionName, final Delete delete) throws IOException {
319     MutateRequest.Builder builder = MutateRequest.newBuilder();
320     RegionSpecifier region = buildRegionSpecifier(
321       RegionSpecifierType.REGION_NAME, regionName);
322     builder.setRegion(region);
323     builder.setMutation(ProtobufUtil.toMutation(MutationType.DELETE, delete,
324       MutationProto.newBuilder()));
325     return builder.build();
326   }
327 
328   /**
329    * Create a protocol buffer MultiRequest for row mutations.
330    * Does not propagate Action absolute position.  Does not set atomic action on the created
331    * RegionAtomic.  Caller should do that if wanted.
332    * @param regionName
333    * @param rowMutations
334    * @return a data-laden RegionMutation.Builder
335    * @throws IOException
336    */
337   public static RegionAction.Builder buildRegionAction(final byte [] regionName,
338       final RowMutations rowMutations)
339   throws IOException {
340     RegionAction.Builder builder =
341       getRegionActionBuilderWithRegion(RegionAction.newBuilder(), regionName);
342     ClientProtos.Action.Builder actionBuilder = ClientProtos.Action.newBuilder();
343     MutationProto.Builder mutationBuilder = MutationProto.newBuilder();
344     for (Mutation mutation: rowMutations.getMutations()) {
345       MutationType mutateType = null;
346       if (mutation instanceof Put) {
347         mutateType = MutationType.PUT;
348       } else if (mutation instanceof Delete) {
349         mutateType = MutationType.DELETE;
350       } else {
351         throw new DoNotRetryIOException("RowMutations supports only put and delete, not " +
352           mutation.getClass().getName());
353       }
354       mutationBuilder.clear();
355       MutationProto mp = ProtobufUtil.toMutation(mutateType, mutation, mutationBuilder);
356       actionBuilder.clear();
357       actionBuilder.setMutation(mp);
358       builder.addAction(actionBuilder.build());
359     }
360     return builder;
361   }
362 
363   /**
364    * Create a protocol buffer MultiRequest for row mutations that does not hold data.  Data/Cells
365    * are carried outside of protobuf.  Return references to the Cells in <code>cells</code> param.
366     * Does not propagate Action absolute position.  Does not set atomic action on the created
367    * RegionAtomic.  Caller should do that if wanted.
368    * @param regionName
369    * @param rowMutations
370    * @param cells Return in here a list of Cells as CellIterable.
371    * @return a region mutation minus data
372    * @throws IOException
373    */
374   public static RegionAction.Builder buildNoDataRegionAction(final byte[] regionName,
375       final RowMutations rowMutations, final List<CellScannable> cells,
376       final RegionAction.Builder regionActionBuilder,
377       final ClientProtos.Action.Builder actionBuilder,
378       final MutationProto.Builder mutationBuilder)
379   throws IOException {
380     for (Mutation mutation: rowMutations.getMutations()) {
381       MutationType type = null;
382       if (mutation instanceof Put) {
383         type = MutationType.PUT;
384       } else if (mutation instanceof Delete) {
385         type = MutationType.DELETE;
386       } else {
387         throw new DoNotRetryIOException("RowMutations supports only put and delete, not " +
388           mutation.getClass().getName());
389       }
390       mutationBuilder.clear();
391       MutationProto mp = ProtobufUtil.toMutationNoData(type, mutation, mutationBuilder);
392       cells.add(mutation);
393       actionBuilder.clear();
394       regionActionBuilder.addAction(actionBuilder.setMutation(mp).build());
395     }
396     return regionActionBuilder;
397   }
398 
399   private static RegionAction.Builder getRegionActionBuilderWithRegion(
400       final RegionAction.Builder regionActionBuilder, final byte [] regionName) {
401     RegionSpecifier region = buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName);
402     regionActionBuilder.setRegion(region);
403     return regionActionBuilder;
404   }
405 
406   /**
407    * Create a protocol buffer ScanRequest for a client Scan
408    *
409    * @param regionName
410    * @param scan
411    * @param numberOfRows
412    * @param closeScanner
413    * @return a scan request
414    * @throws IOException
415    */
416   public static ScanRequest buildScanRequest(final byte[] regionName,
417       final Scan scan, final int numberOfRows,
418         final boolean closeScanner) throws IOException {
419     ScanRequest.Builder builder = ScanRequest.newBuilder();
420     RegionSpecifier region = buildRegionSpecifier(
421       RegionSpecifierType.REGION_NAME, regionName);
422     builder.setNumberOfRows(numberOfRows);
423     builder.setCloseScanner(closeScanner);
424     builder.setRegion(region);
425     builder.setScan(ProtobufUtil.toScan(scan));
426     return builder.build();
427   }
428 
429   /**
430    * Create a protocol buffer ScanRequest for a scanner id
431    *
432    * @param scannerId
433    * @param numberOfRows
434    * @param closeScanner
435    * @return a scan request
436    */
437   public static ScanRequest buildScanRequest(final long scannerId,
438       final int numberOfRows, final boolean closeScanner) {
439     ScanRequest.Builder builder = ScanRequest.newBuilder();
440     builder.setNumberOfRows(numberOfRows);
441     builder.setCloseScanner(closeScanner);
442     builder.setScannerId(scannerId);
443     return builder.build();
444   }
445 
446   /**
447    * Create a protocol buffer ScanRequest for a scanner id
448    *
449    * @param scannerId
450    * @param numberOfRows
451    * @param closeScanner
452    * @param nextCallSeq
453    * @return a scan request
454    */
455   public static ScanRequest buildScanRequest(final long scannerId, final int numberOfRows,
456       final boolean closeScanner, final long nextCallSeq) {
457     ScanRequest.Builder builder = ScanRequest.newBuilder();
458     builder.setNumberOfRows(numberOfRows);
459     builder.setCloseScanner(closeScanner);
460     builder.setScannerId(scannerId);
461     builder.setNextCallSeq(nextCallSeq);
462     return builder.build();
463   }
464 
465   /**
466    * Create a protocol buffer bulk load request
467    *
468    * @param familyPaths
469    * @param regionName
470    * @param assignSeqNum
471    * @return a bulk load request
472    */
473   public static BulkLoadHFileRequest buildBulkLoadHFileRequest(
474       final List<Pair<byte[], String>> familyPaths,
475       final byte[] regionName, boolean assignSeqNum) {
476     BulkLoadHFileRequest.Builder builder = BulkLoadHFileRequest.newBuilder();
477     RegionSpecifier region = buildRegionSpecifier(
478       RegionSpecifierType.REGION_NAME, regionName);
479     builder.setRegion(region);
480     FamilyPath.Builder familyPathBuilder = FamilyPath.newBuilder();
481     for (Pair<byte[], String> familyPath: familyPaths) {
482       familyPathBuilder.setFamily(HBaseZeroCopyByteString.wrap(familyPath.getFirst()));
483       familyPathBuilder.setPath(familyPath.getSecond());
484       builder.addFamilyPath(familyPathBuilder.build());
485     }
486     builder.setAssignSeqNum(assignSeqNum);
487     return builder.build();
488   }
489 
490   /**
491    * Create a protocol buffer multi request for a list of actions.
492    * Propagates Actions original index.
493    *
494    * @param regionName
495    * @param actions
496    * @return a multi request
497    * @throws IOException
498    */
499   public static <R> RegionAction.Builder buildRegionAction(final byte[] regionName,
500       final List<Action<R>> actions, final RegionAction.Builder regionActionBuilder,
501       final ClientProtos.Action.Builder actionBuilder,
502       final MutationProto.Builder mutationBuilder)
503   throws IOException {
504     for (Action<R> action: actions) {
505       Row row = action.getAction();
506       actionBuilder.clear();
507       actionBuilder.setIndex(action.getOriginalIndex());
508       mutationBuilder.clear();
509       if (row instanceof Get) {
510         Get g = (Get)row;
511         regionActionBuilder.addAction(actionBuilder.setGet(ProtobufUtil.toGet(g)));
512       } else if (row instanceof Put) {
513         regionActionBuilder.addAction(actionBuilder.
514           setMutation(ProtobufUtil.toMutation(MutationType.PUT, (Put)row, mutationBuilder)));
515       } else if (row instanceof Delete) {
516         regionActionBuilder.addAction(actionBuilder.
517           setMutation(ProtobufUtil.toMutation(MutationType.DELETE, (Delete)row, mutationBuilder)));
518       } else if (row instanceof Append) {
519         regionActionBuilder.addAction(actionBuilder.
520           setMutation(ProtobufUtil.toMutation(MutationType.APPEND, (Append)row, mutationBuilder)));
521       } else if (row instanceof Increment) {
522         regionActionBuilder.addAction(actionBuilder.
523           setMutation(ProtobufUtil.toMutation((Increment)row, mutationBuilder)));
524       } else if (row instanceof RowMutations) {
525         throw new UnsupportedOperationException("No RowMutations in multi calls; use mutateRow");
526       } else {
527         throw new DoNotRetryIOException("Multi doesn't support " + row.getClass().getName());
528       }
529     }
530     return regionActionBuilder;
531   }
532 
533   /**
534    * Create a protocol buffer multirequest with NO data for a list of actions (data is carried
535    * otherwise than via protobuf).  This means it just notes attributes, whether to write the
536    * WAL, etc., and the presence in protobuf serves as place holder for the data which is
537    * coming along otherwise.  Note that Get is different.  It does not contain 'data' and is always
538    * carried by protobuf.  We return references to the data by adding them to the passed in
539    * <code>data</code> param.
540    *
541    * <p>Propagates Actions original index.
542    *
543    * @param regionName
544    * @param actions
545    * @param cells Place to stuff references to actual data.
546    * @return a multi request that does not carry any data.
547    * @throws IOException
548    */
549   public static <R> RegionAction.Builder buildNoDataRegionAction(final byte[] regionName,
550       final List<Action<R>> actions, final List<CellScannable> cells,
551       final RegionAction.Builder regionActionBuilder,
552       final ClientProtos.Action.Builder actionBuilder,
553       final MutationProto.Builder mutationBuilder)
554   throws IOException {
555     RegionAction.Builder builder =
556       getRegionActionBuilderWithRegion(RegionAction.newBuilder(), regionName);
557     for (Action<R> action: actions) {
558       Row row = action.getAction();
559       actionBuilder.clear();
560       actionBuilder.setIndex(action.getOriginalIndex());
561       mutationBuilder.clear();
562       if (row instanceof Get) {
563         Get g = (Get)row;
564         builder.addAction(actionBuilder.setGet(ProtobufUtil.toGet(g)));
565       } else if (row instanceof Put) {
566         Put p = (Put)row;
567         cells.add(p);
568         builder.addAction(actionBuilder.
569           setMutation(ProtobufUtil.toMutationNoData(MutationType.PUT, p, mutationBuilder)));
570       } else if (row instanceof Delete) {
571         Delete d = (Delete)row;
572         int size = d.size();
573         // Note that a legitimate Delete may have a size of zero; i.e. a Delete that has nothing
574         // in it but the row to delete.  In this case, the current implementation does not make
575         // a KeyValue to represent a delete-of-all-the-row until we serialize... For such cases
576         // where the size returned is zero, we will send the Delete fully pb'd rather than have
577         // metadata only in the pb and then send the kv along the side in cells.
578         if (size > 0) {
579           cells.add(d);
580           builder.addAction(actionBuilder.
581             setMutation(ProtobufUtil.toMutationNoData(MutationType.DELETE, d, mutationBuilder)));
582         } else {
583           builder.addAction(actionBuilder.
584             setMutation(ProtobufUtil.toMutation(MutationType.DELETE, d, mutationBuilder)));
585         }
586       } else if (row instanceof Append) {
587         Append a = (Append)row;
588         cells.add(a);
589         builder.addAction(actionBuilder.
590           setMutation(ProtobufUtil.toMutationNoData(MutationType.APPEND, a, mutationBuilder)));
591       } else if (row instanceof Increment) {
592         Increment i = (Increment)row;
593         cells.add(i);
594         builder.addAction(actionBuilder.
595           setMutation(ProtobufUtil.toMutationNoData(MutationType.INCREMENT, i, mutationBuilder)));
596       } else if (row instanceof RowMutations) {
597         continue; // ignore RowMutations
598       } else {
599         throw new DoNotRetryIOException("Multi doesn't support " + row.getClass().getName());
600       }
601     }
602     return builder;
603   }
604 
605 // End utilities for Client
606 //Start utilities for Admin
607 
608   /**
609    * Create a protocol buffer GetRegionInfoRequest for a given region name
610    *
611    * @param regionName the name of the region to get info
612    * @return a protocol buffer GetRegionInfoRequest
613    */
614   public static GetRegionInfoRequest
615       buildGetRegionInfoRequest(final byte[] regionName) {
616     return buildGetRegionInfoRequest(regionName, false);
617   }
618 
619   /**
620    * Create a protocol buffer GetRegionInfoRequest for a given region name
621    *
622    * @param regionName the name of the region to get info
623    * @param includeCompactionState indicate if the compaction state is requested
624    * @return a protocol buffer GetRegionInfoRequest
625    */
626   public static GetRegionInfoRequest
627       buildGetRegionInfoRequest(final byte[] regionName,
628         final boolean includeCompactionState) {
629     GetRegionInfoRequest.Builder builder = GetRegionInfoRequest.newBuilder();
630     RegionSpecifier region = buildRegionSpecifier(
631       RegionSpecifierType.REGION_NAME, regionName);
632     builder.setRegion(region);
633     if (includeCompactionState) {
634       builder.setCompactionState(includeCompactionState);
635     }
636     return builder.build();
637   }
638 
639  /**
640   * Create a protocol buffer GetStoreFileRequest for a given region name
641   *
642   * @param regionName the name of the region to get info
643   * @param family the family to get store file list
644   * @return a protocol buffer GetStoreFileRequest
645   */
646  public static GetStoreFileRequest
647      buildGetStoreFileRequest(final byte[] regionName, final byte[] family) {
648    GetStoreFileRequest.Builder builder = GetStoreFileRequest.newBuilder();
649    RegionSpecifier region = buildRegionSpecifier(
650      RegionSpecifierType.REGION_NAME, regionName);
651    builder.setRegion(region);
652    builder.addFamily(HBaseZeroCopyByteString.wrap(family));
653    return builder.build();
654  }
655 
656  /**
657   * Create a protocol buffer GetOnlineRegionRequest
658   *
659   * @return a protocol buffer GetOnlineRegionRequest
660   */
661  public static GetOnlineRegionRequest buildGetOnlineRegionRequest() {
662    return GetOnlineRegionRequest.newBuilder().build();
663  }
664 
665  /**
666   * Create a protocol buffer FlushRegionRequest for a given region name
667   *
668   * @param regionName the name of the region to get info
669   * @return a protocol buffer FlushRegionRequest
670   */
671  public static FlushRegionRequest
672      buildFlushRegionRequest(final byte[] regionName) {
673    FlushRegionRequest.Builder builder = FlushRegionRequest.newBuilder();
674    RegionSpecifier region = buildRegionSpecifier(
675      RegionSpecifierType.REGION_NAME, regionName);
676    builder.setRegion(region);
677    return builder.build();
678  }
679 
680  /**
681   * Create a protocol buffer OpenRegionRequest to open a list of regions
682   *
683   * @param regionOpenInfos info of a list of regions to open
684   * @return a protocol buffer OpenRegionRequest
685   */
686  public static OpenRegionRequest
687      buildOpenRegionRequest(final List<Triple<HRegionInfo, Integer,
688          List<ServerName>>> regionOpenInfos) {
689    OpenRegionRequest.Builder builder = OpenRegionRequest.newBuilder();
690    for (Triple<HRegionInfo, Integer, List<ServerName>> regionOpenInfo: regionOpenInfos) {
691      Integer second = regionOpenInfo.getSecond();
692      int versionOfOfflineNode = second == null ? -1 : second.intValue();
693      builder.addOpenInfo(buildRegionOpenInfo(
694        regionOpenInfo.getFirst(), versionOfOfflineNode, regionOpenInfo.getThird()));
695    }
696    return builder.build();
697  }
698 
699  /**
700   * Create a protocol buffer OpenRegionRequest for a given region
701   *
702   * @param server the serverName for the RPC
703   * @param region the region to open
704   * @param versionOfOfflineNode that needs to be present in the offline node
705   * @param favoredNodes
706   * @return a protocol buffer OpenRegionRequest
707   */
708  public static OpenRegionRequest buildOpenRegionRequest(ServerName server,
709      final HRegionInfo region, final int versionOfOfflineNode, List<ServerName> favoredNodes) {
710    OpenRegionRequest.Builder builder = OpenRegionRequest.newBuilder();
711    builder.addOpenInfo(buildRegionOpenInfo(region, versionOfOfflineNode, favoredNodes));
712    if (server != null) {
713      builder.setServerStartCode(server.getStartcode());
714    }
715    return builder.build();
716  }
717 
718  /**
719   * Create a protocol buffer UpdateFavoredNodesRequest to update a list of favorednode mappings
720   * @param updateRegionInfos
721   * @return a protocol buffer UpdateFavoredNodesRequest
722   */
723  public static UpdateFavoredNodesRequest buildUpdateFavoredNodesRequest(
724      final List<Pair<HRegionInfo, List<ServerName>>> updateRegionInfos) {
725    UpdateFavoredNodesRequest.Builder ubuilder = UpdateFavoredNodesRequest.newBuilder();
726    for (Pair<HRegionInfo, List<ServerName>> pair : updateRegionInfos) {
727      RegionUpdateInfo.Builder builder = RegionUpdateInfo.newBuilder();
728      builder.setRegion(HRegionInfo.convert(pair.getFirst()));
729      for (ServerName server : pair.getSecond()) {
730        builder.addFavoredNodes(ProtobufUtil.toServerName(server));
731      }
732      ubuilder.addUpdateInfo(builder.build());
733    }
734    return ubuilder.build();
735  }
736 
737  /**
738   * Create a CloseRegionRequest for a given region name
739   *
740   * @param regionName the name of the region to close
741   * @param transitionInZK indicator if to transition in ZK
742   * @return a CloseRegionRequest
743   */
744  public static CloseRegionRequest buildCloseRegionRequest(ServerName server,
745      final byte[] regionName, final boolean transitionInZK) {
746    CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
747    RegionSpecifier region = buildRegionSpecifier(
748      RegionSpecifierType.REGION_NAME, regionName);
749    builder.setRegion(region);
750    builder.setTransitionInZK(transitionInZK);
751    if (server != null) {
752      builder.setServerStartCode(server.getStartcode());
753    }
754    return builder.build();
755  }
756 
757   public static CloseRegionRequest buildCloseRegionRequest(ServerName server,
758     final byte[] regionName, final int versionOfClosingNode,
759     ServerName destinationServer, final boolean transitionInZK) {
760     CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
761     RegionSpecifier region = buildRegionSpecifier(
762       RegionSpecifierType.REGION_NAME, regionName);
763     builder.setRegion(region);
764     builder.setVersionOfClosingNode(versionOfClosingNode);
765     builder.setTransitionInZK(transitionInZK);
766     if (destinationServer != null){
767       builder.setDestinationServer(ProtobufUtil.toServerName( destinationServer) );
768     }
769     if (server != null) {
770       builder.setServerStartCode(server.getStartcode());
771     }
772     return builder.build();
773   }
774 
775  /**
776   * Create a CloseRegionRequest for a given encoded region name
777   *
778   * @param encodedRegionName the name of the region to close
779   * @param transitionInZK indicator if to transition in ZK
780   * @return a CloseRegionRequest
781   */
782  public static CloseRegionRequest
783      buildCloseRegionRequest(ServerName server, final String encodedRegionName,
784        final boolean transitionInZK) {
785    CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
786    RegionSpecifier region = buildRegionSpecifier(
787      RegionSpecifierType.ENCODED_REGION_NAME,
788      Bytes.toBytes(encodedRegionName));
789    builder.setRegion(region);
790    builder.setTransitionInZK(transitionInZK);
791    if (server != null) {
792      builder.setServerStartCode(server.getStartcode());
793    }
794    return builder.build();
795  }
796 
797  /**
798   * Create a SplitRegionRequest for a given region name
799   *
800   * @param regionName the name of the region to split
801   * @param splitPoint the split point
802   * @return a SplitRegionRequest
803   */
804  public static SplitRegionRequest buildSplitRegionRequest(
805      final byte[] regionName, final byte[] splitPoint) {
806    SplitRegionRequest.Builder builder = SplitRegionRequest.newBuilder();
807    RegionSpecifier region = buildRegionSpecifier(
808      RegionSpecifierType.REGION_NAME, regionName);
809    builder.setRegion(region);
810    if (splitPoint != null) {
811      builder.setSplitPoint(HBaseZeroCopyByteString.wrap(splitPoint));
812    }
813    return builder.build();
814  }
815 
816   /**
817    * Create a MergeRegionsRequest for the given regions
818    * @param regionA name of region a
819    * @param regionB name of region b
820    * @param forcible true if it is a compulsory merge
821    * @return a MergeRegionsRequest
822    */
823   public static MergeRegionsRequest buildMergeRegionsRequest(
824       final byte[] regionA, final byte[] regionB, final boolean forcible) {
825     MergeRegionsRequest.Builder builder = MergeRegionsRequest.newBuilder();
826     RegionSpecifier regionASpecifier = buildRegionSpecifier(
827         RegionSpecifierType.REGION_NAME, regionA);
828     RegionSpecifier regionBSpecifier = buildRegionSpecifier(
829         RegionSpecifierType.REGION_NAME, regionB);
830     builder.setRegionA(regionASpecifier);
831     builder.setRegionB(regionBSpecifier);
832     builder.setForcible(forcible);
833     return builder.build();
834   }
835 
836  /**
837   * Create a  CompactRegionRequest for a given region name
838   *
839   * @param regionName the name of the region to get info
840   * @param major indicator if it is a major compaction
841   * @return a CompactRegionRequest
842   */
843  public static CompactRegionRequest buildCompactRegionRequest(
844      final byte[] regionName, final boolean major, final byte [] family) {
845    CompactRegionRequest.Builder builder = CompactRegionRequest.newBuilder();
846    RegionSpecifier region = buildRegionSpecifier(
847      RegionSpecifierType.REGION_NAME, regionName);
848    builder.setRegion(region);
849    builder.setMajor(major);
850    if (family != null) {
851      builder.setFamily(HBaseZeroCopyByteString.wrap(family));
852    }
853    return builder.build();
854  }
855 
856  /**
857   * @see {@link #buildRollWALWriterRequest()
858   */
859  private static RollWALWriterRequest ROLL_WAL_WRITER_REQUEST =
860      RollWALWriterRequest.newBuilder().build();
861 
862   /**
863   * Create a new RollWALWriterRequest
864   *
865   * @return a ReplicateWALEntryRequest
866   */
867  public static RollWALWriterRequest buildRollWALWriterRequest() {
868    return ROLL_WAL_WRITER_REQUEST;
869  }
870 
871  /**
872   * @see {@link #buildGetServerInfoRequest()}
873   */
874  private static GetServerInfoRequest GET_SERVER_INFO_REQUEST =
875    GetServerInfoRequest.newBuilder().build();
876 
877  /**
878   * Create a new GetServerInfoRequest
879   *
880   * @return a GetServerInfoRequest
881   */
882  public static GetServerInfoRequest buildGetServerInfoRequest() {
883    return GET_SERVER_INFO_REQUEST;
884  }
885 
886  /**
887   * Create a new StopServerRequest
888   *
889   * @param reason the reason to stop the server
890   * @return a StopServerRequest
891   */
892  public static StopServerRequest buildStopServerRequest(final String reason) {
893    StopServerRequest.Builder builder = StopServerRequest.newBuilder();
894    builder.setReason(reason);
895    return builder.build();
896  }
897 
898 //End utilities for Admin
899 
900   /**
901    * Convert a byte array to a protocol buffer RegionSpecifier
902    *
903    * @param type the region specifier type
904    * @param value the region specifier byte array value
905    * @return a protocol buffer RegionSpecifier
906    */
907   public static RegionSpecifier buildRegionSpecifier(
908       final RegionSpecifierType type, final byte[] value) {
909     RegionSpecifier.Builder regionBuilder = RegionSpecifier.newBuilder();
910     regionBuilder.setValue(HBaseZeroCopyByteString.wrap(value));
911     regionBuilder.setType(type);
912     return regionBuilder.build();
913   }
914 
915   /**
916    * Create a protocol buffer Condition
917    *
918    * @param row
919    * @param family
920    * @param qualifier
921    * @param comparator
922    * @param compareType
923    * @return a Condition
924    * @throws IOException
925    */
926   private static Condition buildCondition(final byte[] row,
927       final byte[] family, final byte [] qualifier,
928       final ByteArrayComparable comparator,
929       final CompareType compareType) throws IOException {
930     Condition.Builder builder = Condition.newBuilder();
931     builder.setRow(HBaseZeroCopyByteString.wrap(row));
932     builder.setFamily(HBaseZeroCopyByteString.wrap(family));
933     builder.setQualifier(HBaseZeroCopyByteString.wrap(qualifier));
934     builder.setComparator(ProtobufUtil.toComparator(comparator));
935     builder.setCompareType(compareType);
936     return builder.build();
937   }
938 
939   /**
940    * Create a protocol buffer AddColumnRequest
941    *
942    * @param tableName
943    * @param column
944    * @return an AddColumnRequest
945    */
946   public static AddColumnRequest buildAddColumnRequest(
947       final TableName tableName, final HColumnDescriptor column) {
948     AddColumnRequest.Builder builder = AddColumnRequest.newBuilder();
949     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
950     builder.setColumnFamilies(column.convert());
951     return builder.build();
952   }
953 
954   /**
955    * Create a protocol buffer DeleteColumnRequest
956    *
957    * @param tableName
958    * @param columnName
959    * @return a DeleteColumnRequest
960    */
961   public static DeleteColumnRequest buildDeleteColumnRequest(
962       final TableName tableName, final byte [] columnName) {
963     DeleteColumnRequest.Builder builder = DeleteColumnRequest.newBuilder();
964     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
965     builder.setColumnName(HBaseZeroCopyByteString.wrap(columnName));
966     return builder.build();
967   }
968 
969   /**
970    * Create a protocol buffer ModifyColumnRequest
971    *
972    * @param tableName
973    * @param column
974    * @return an ModifyColumnRequest
975    */
976   public static ModifyColumnRequest buildModifyColumnRequest(
977       final TableName tableName, final HColumnDescriptor column) {
978     ModifyColumnRequest.Builder builder = ModifyColumnRequest.newBuilder();
979     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
980     builder.setColumnFamilies(column.convert());
981     return builder.build();
982   }
983 
984   /**
985    * Create a protocol buffer MoveRegionRequest
986    *
987    * @param encodedRegionName
988    * @param destServerName
989    * @return A MoveRegionRequest
990    * @throws DeserializationException
991    */
992   public static MoveRegionRequest buildMoveRegionRequest(
993       final byte [] encodedRegionName, final byte [] destServerName) throws
994       DeserializationException {
995 	MoveRegionRequest.Builder builder = MoveRegionRequest.newBuilder();
996     builder.setRegion(
997       buildRegionSpecifier(RegionSpecifierType.ENCODED_REGION_NAME,encodedRegionName));
998     if (destServerName != null) {
999       builder.setDestServerName(
1000         ProtobufUtil.toServerName(ServerName.valueOf(Bytes.toString(destServerName))));
1001     }
1002     return builder.build();
1003   }
1004 
1005   public static DispatchMergingRegionsRequest buildDispatchMergingRegionsRequest(
1006       final byte[] encodedNameOfRegionA, final byte[] encodedNameOfRegionB,
1007       final boolean forcible) throws DeserializationException {
1008     DispatchMergingRegionsRequest.Builder builder = DispatchMergingRegionsRequest.newBuilder();
1009     builder.setRegionA(buildRegionSpecifier(
1010         RegionSpecifierType.ENCODED_REGION_NAME, encodedNameOfRegionA));
1011     builder.setRegionB(buildRegionSpecifier(
1012         RegionSpecifierType.ENCODED_REGION_NAME, encodedNameOfRegionB));
1013     builder.setForcible(forcible);
1014     return builder.build();
1015   }
1016 
1017   /**
1018    * Create a protocol buffer AssignRegionRequest
1019    *
1020    * @param regionName
1021    * @return an AssignRegionRequest
1022    */
1023   public static AssignRegionRequest buildAssignRegionRequest(final byte [] regionName) {
1024     AssignRegionRequest.Builder builder = AssignRegionRequest.newBuilder();
1025     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1026     return builder.build();
1027   }
1028 
1029   /**
1030    * Creates a protocol buffer UnassignRegionRequest
1031    *
1032    * @param regionName
1033    * @param force
1034    * @return an UnassignRegionRequest
1035    */
1036   public static UnassignRegionRequest buildUnassignRegionRequest(
1037       final byte [] regionName, final boolean force) {
1038     UnassignRegionRequest.Builder builder = UnassignRegionRequest.newBuilder();
1039     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1040     builder.setForce(force);
1041     return builder.build();
1042   }
1043 
1044   /**
1045    * Creates a protocol buffer OfflineRegionRequest
1046    *
1047    * @param regionName
1048    * @return an OfflineRegionRequest
1049    */
1050   public static OfflineRegionRequest buildOfflineRegionRequest(final byte [] regionName) {
1051     OfflineRegionRequest.Builder builder = OfflineRegionRequest.newBuilder();
1052     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1053     return builder.build();
1054   }
1055 
1056   /**
1057    * Creates a protocol buffer DeleteTableRequest
1058    *
1059    * @param tableName
1060    * @return a DeleteTableRequest
1061    */
1062   public static DeleteTableRequest buildDeleteTableRequest(final TableName tableName) {
1063     DeleteTableRequest.Builder builder = DeleteTableRequest.newBuilder();
1064     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1065     return builder.build();
1066   }
1067 
1068   /**
1069    * Creates a protocol buffer EnableTableRequest
1070    *
1071    * @param tableName
1072    * @return an EnableTableRequest
1073    */
1074   public static EnableTableRequest buildEnableTableRequest(final TableName tableName) {
1075     EnableTableRequest.Builder builder = EnableTableRequest.newBuilder();
1076     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1077     return builder.build();
1078   }
1079 
1080   /**
1081    * Creates a protocol buffer DisableTableRequest
1082    *
1083    * @param tableName
1084    * @return a DisableTableRequest
1085    */
1086   public static DisableTableRequest buildDisableTableRequest(final TableName tableName) {
1087     DisableTableRequest.Builder builder = DisableTableRequest.newBuilder();
1088     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1089     return builder.build();
1090   }
1091 
1092   /**
1093    * Creates a protocol buffer CreateTableRequest
1094    *
1095    * @param hTableDesc
1096    * @param splitKeys
1097    * @return a CreateTableRequest
1098    */
1099   public static CreateTableRequest buildCreateTableRequest(
1100       final HTableDescriptor hTableDesc, final byte [][] splitKeys) {
1101     CreateTableRequest.Builder builder = CreateTableRequest.newBuilder();
1102     builder.setTableSchema(hTableDesc.convert());
1103     if (splitKeys != null) {
1104       for (byte [] splitKey : splitKeys) {
1105         builder.addSplitKeys(HBaseZeroCopyByteString.wrap(splitKey));
1106       }
1107     }
1108     return builder.build();
1109   }
1110 
1111 
1112   /**
1113    * Creates a protocol buffer ModifyTableRequest
1114    *
1115    * @param tableName
1116    * @param hTableDesc
1117    * @return a ModifyTableRequest
1118    */
1119   public static ModifyTableRequest buildModifyTableRequest(
1120       final TableName tableName, final HTableDescriptor hTableDesc) {
1121     ModifyTableRequest.Builder builder = ModifyTableRequest.newBuilder();
1122     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1123     builder.setTableSchema(hTableDesc.convert());
1124     return builder.build();
1125   }
1126 
1127   /**
1128    * Creates a protocol buffer GetSchemaAlterStatusRequest
1129    *
1130    * @param tableName
1131    * @return a GetSchemaAlterStatusRequest
1132    */
1133   public static GetSchemaAlterStatusRequest buildGetSchemaAlterStatusRequest(
1134       final TableName tableName) {
1135     GetSchemaAlterStatusRequest.Builder builder = GetSchemaAlterStatusRequest.newBuilder();
1136     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1137     return builder.build();
1138   }
1139 
1140   /**
1141    * Creates a protocol buffer GetTableDescriptorsRequest
1142    *
1143    * @param tableNames
1144    * @return a GetTableDescriptorsRequest
1145    */
1146   public static GetTableDescriptorsRequest buildGetTableDescriptorsRequest(
1147       final List<TableName> tableNames) {
1148     GetTableDescriptorsRequest.Builder builder = GetTableDescriptorsRequest.newBuilder();
1149     if (tableNames != null) {
1150       for (TableName tableName : tableNames) {
1151         builder.addTableNames(ProtobufUtil.toProtoTableName(tableName));
1152       }
1153     }
1154     return builder.build();
1155   }
1156 
1157   /**
1158    * Creates a protocol buffer GetTableDescriptorsRequest for a single table
1159    *
1160    * @param tableName the table name
1161    * @return a GetTableDescriptorsRequest
1162    */
1163   public static GetTableDescriptorsRequest buildGetTableDescriptorsRequest(
1164       final TableName tableName) {
1165     return GetTableDescriptorsRequest.newBuilder()
1166       .addTableNames(ProtobufUtil.toProtoTableName(tableName))
1167       .build();
1168   }
1169 
1170   /**
1171    * Creates a protocol buffer IsMasterRunningRequest
1172    *
1173    * @return a IsMasterRunningRequest
1174    */
1175   public static IsMasterRunningRequest buildIsMasterRunningRequest() {
1176     return IsMasterRunningRequest.newBuilder().build();
1177   }
1178 
1179   /**
1180    * Creates a protocol buffer BalanceRequest
1181    *
1182    * @return a BalanceRequest
1183    */
1184   public static BalanceRequest buildBalanceRequest() {
1185     return BalanceRequest.newBuilder().build();
1186   }
1187 
1188   /**
1189    * Creates a protocol buffer SetBalancerRunningRequest
1190    *
1191    * @param on
1192    * @param synchronous
1193    * @return a SetBalancerRunningRequest
1194    */
1195   public static SetBalancerRunningRequest buildSetBalancerRunningRequest(boolean on, boolean synchronous) {
1196     return SetBalancerRunningRequest.newBuilder().setOn(on).setSynchronous(synchronous).build();
1197   }
1198 
1199   /**
1200    * @see {@link #buildGetClusterStatusRequest}
1201    */
1202   private static final GetClusterStatusRequest GET_CLUSTER_STATUS_REQUEST =
1203       GetClusterStatusRequest.newBuilder().build();
1204 
1205   /**
1206    * Creates a protocol buffer GetClusterStatusRequest
1207    *
1208    * @return A GetClusterStatusRequest
1209    */
1210   public static GetClusterStatusRequest buildGetClusterStatusRequest() {
1211     return GET_CLUSTER_STATUS_REQUEST;
1212   }
1213 
1214   /**
1215    * @see {@link #buildCatalogScanRequest}
1216    */
1217   private static final RunCatalogScanRequest CATALOG_SCAN_REQUEST =
1218     RunCatalogScanRequest.newBuilder().build();
1219 
1220   /**
1221    * Creates a request for running a catalog scan
1222    * @return A {@link RunCatalogScanRequest}
1223    */
1224   public static RunCatalogScanRequest buildCatalogScanRequest() {
1225     return CATALOG_SCAN_REQUEST;
1226   }
1227 
1228   /**
1229    * Creates a request for enabling/disabling the catalog janitor
1230    * @return A {@link EnableCatalogJanitorRequest}
1231    */
1232   public static EnableCatalogJanitorRequest buildEnableCatalogJanitorRequest(boolean enable) {
1233     return EnableCatalogJanitorRequest.newBuilder().setEnable(enable).build();
1234   }
1235 
1236   /**
1237    * @see {@link #buildIsCatalogJanitorEnabledRequest()}
1238    */
1239   private static final IsCatalogJanitorEnabledRequest IS_CATALOG_JANITOR_ENABLED_REQUEST =
1240     IsCatalogJanitorEnabledRequest.newBuilder().build();
1241 
1242   /**
1243    * Creates a request for querying the master whether the catalog janitor is enabled
1244    * @return A {@link IsCatalogJanitorEnabledRequest}
1245    */
1246   public static IsCatalogJanitorEnabledRequest buildIsCatalogJanitorEnabledRequest() {
1247     return IS_CATALOG_JANITOR_ENABLED_REQUEST;
1248   }
1249 
1250   /**
1251    * Creates a request for querying the master the last flushed sequence Id for a region
1252    * @param regionName
1253    * @return A {@link GetLastFlushedSequenceIdRequest}
1254    */
1255   public static GetLastFlushedSequenceIdRequest buildGetLastFlushedSequenceIdRequest(
1256       byte[] regionName) {
1257     return GetLastFlushedSequenceIdRequest.newBuilder().setRegionName(
1258         HBaseZeroCopyByteString.wrap(regionName)).build();
1259   }
1260 
1261   /**
1262    * Create a request to grant user permissions.
1263    *
1264    * @param username the short user name who to grant permissions
1265    * @param actions the permissions to be granted
1266    * @return A {@link AccessControlProtos} GrantRequest
1267    */
1268   public static AccessControlProtos.GrantRequest buildGrantRequest(
1269       String username, AccessControlProtos.Permission.Action... actions) {
1270     AccessControlProtos.Permission.Builder ret =
1271         AccessControlProtos.Permission.newBuilder();
1272     AccessControlProtos.GlobalPermission.Builder permissionBuilder =
1273         AccessControlProtos.GlobalPermission.newBuilder();
1274     for (AccessControlProtos.Permission.Action a : actions) {
1275       permissionBuilder.addAction(a);
1276     }
1277     ret.setType(AccessControlProtos.Permission.Type.Global)
1278        .setGlobalPermission(permissionBuilder);
1279     return AccessControlProtos.GrantRequest.newBuilder()
1280       .setUserPermission(
1281           AccessControlProtos.UserPermission.newBuilder()
1282               .setUser(ByteString.copyFromUtf8(username))
1283               .setPermission(ret)
1284       ).build();
1285   }
1286 
1287   /**
1288    * Create a request to grant user permissions.
1289    *
1290    * @param username the short user name who to grant permissions
1291    * @param tableName optional table name the permissions apply
1292    * @param family optional column family
1293    * @param qualifier optional qualifier
1294    * @param actions the permissions to be granted
1295    * @return A {@link AccessControlProtos} GrantRequest
1296    */
1297   public static AccessControlProtos.GrantRequest buildGrantRequest(
1298       String username, TableName tableName, byte[] family, byte[] qualifier,
1299       AccessControlProtos.Permission.Action... actions) {
1300     AccessControlProtos.Permission.Builder ret =
1301         AccessControlProtos.Permission.newBuilder();
1302     AccessControlProtos.TablePermission.Builder permissionBuilder =
1303         AccessControlProtos.TablePermission.newBuilder();
1304     for (AccessControlProtos.Permission.Action a : actions) {
1305       permissionBuilder.addAction(a);
1306     }
1307     if (tableName == null) {
1308       throw new NullPointerException("TableName cannot be null");
1309     }
1310     permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1311 
1312     if (family != null) {
1313       permissionBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
1314     }
1315     if (qualifier != null) {
1316       permissionBuilder.setQualifier(HBaseZeroCopyByteString.wrap(qualifier));
1317     }
1318     ret.setType(AccessControlProtos.Permission.Type.Table)
1319        .setTablePermission(permissionBuilder);
1320     return AccessControlProtos.GrantRequest.newBuilder()
1321       .setUserPermission(
1322           AccessControlProtos.UserPermission.newBuilder()
1323               .setUser(ByteString.copyFromUtf8(username))
1324               .setPermission(ret)
1325       ).build();
1326   }
1327 
1328   /**
1329    * Create a request to grant user permissions.
1330    *
1331    * @param username the short user name who to grant permissions
1332    * @param namespace optional table name the permissions apply
1333    * @param actions the permissions to be granted
1334    * @return A {@link AccessControlProtos} GrantRequest
1335    */
1336   public static AccessControlProtos.GrantRequest buildGrantRequest(
1337       String username, String namespace,
1338       AccessControlProtos.Permission.Action... actions) {
1339     AccessControlProtos.Permission.Builder ret =
1340         AccessControlProtos.Permission.newBuilder();
1341     AccessControlProtos.NamespacePermission.Builder permissionBuilder =
1342         AccessControlProtos.NamespacePermission.newBuilder();
1343     for (AccessControlProtos.Permission.Action a : actions) {
1344       permissionBuilder.addAction(a);
1345     }
1346     if (namespace != null) {
1347       permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace));
1348     }
1349     ret.setType(AccessControlProtos.Permission.Type.Namespace)
1350        .setNamespacePermission(permissionBuilder);
1351     return AccessControlProtos.GrantRequest.newBuilder()
1352       .setUserPermission(
1353           AccessControlProtos.UserPermission.newBuilder()
1354               .setUser(ByteString.copyFromUtf8(username))
1355               .setPermission(ret)
1356       ).build();
1357   }
1358 
1359   /**
1360    * Create a request to revoke user permissions.
1361    *
1362    * @param username the short user name whose permissions to be revoked
1363    * @param actions the permissions to be revoked
1364    * @return A {@link AccessControlProtos} RevokeRequest
1365    */
1366   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1367       String username, AccessControlProtos.Permission.Action... actions) {
1368     AccessControlProtos.Permission.Builder ret =
1369         AccessControlProtos.Permission.newBuilder();
1370     AccessControlProtos.GlobalPermission.Builder permissionBuilder =
1371         AccessControlProtos.GlobalPermission.newBuilder();
1372     for (AccessControlProtos.Permission.Action a : actions) {
1373       permissionBuilder.addAction(a);
1374     }
1375     ret.setType(AccessControlProtos.Permission.Type.Global)
1376        .setGlobalPermission(permissionBuilder);
1377     return AccessControlProtos.RevokeRequest.newBuilder()
1378       .setUserPermission(
1379           AccessControlProtos.UserPermission.newBuilder()
1380               .setUser(ByteString.copyFromUtf8(username))
1381               .setPermission(ret)
1382       ).build();
1383   }
1384 
1385   /**
1386    * Create a request to revoke user permissions.
1387    *
1388    * @param username the short user name whose permissions to be revoked
1389    * @param tableName optional table name the permissions apply
1390    * @param family optional column family
1391    * @param qualifier optional qualifier
1392    * @param actions the permissions to be revoked
1393    * @return A {@link AccessControlProtos} RevokeRequest
1394    */
1395   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1396       String username, TableName tableName, byte[] family, byte[] qualifier,
1397       AccessControlProtos.Permission.Action... actions) {
1398     AccessControlProtos.Permission.Builder ret =
1399         AccessControlProtos.Permission.newBuilder();
1400     AccessControlProtos.TablePermission.Builder permissionBuilder =
1401         AccessControlProtos.TablePermission.newBuilder();
1402     for (AccessControlProtos.Permission.Action a : actions) {
1403       permissionBuilder.addAction(a);
1404     }
1405     if (tableName != null) {
1406       permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1407     }
1408     if (family != null) {
1409       permissionBuilder.setFamily(HBaseZeroCopyByteString.wrap(family));
1410     }
1411     if (qualifier != null) {
1412       permissionBuilder.setQualifier(HBaseZeroCopyByteString.wrap(qualifier));
1413     }
1414     ret.setType(AccessControlProtos.Permission.Type.Table)
1415        .setTablePermission(permissionBuilder);
1416     return AccessControlProtos.RevokeRequest.newBuilder()
1417       .setUserPermission(
1418           AccessControlProtos.UserPermission.newBuilder()
1419               .setUser(ByteString.copyFromUtf8(username))
1420               .setPermission(ret)
1421       ).build();
1422   }
1423 
1424   /**
1425    * Create a request to revoke user permissions.
1426    *
1427    * @param username the short user name whose permissions to be revoked
1428    * @param namespace optional table name the permissions apply
1429    * @param actions the permissions to be revoked
1430    * @return A {@link AccessControlProtos} RevokeRequest
1431    */
1432   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1433       String username, String namespace,
1434       AccessControlProtos.Permission.Action... actions) {
1435     AccessControlProtos.Permission.Builder ret =
1436         AccessControlProtos.Permission.newBuilder();
1437     AccessControlProtos.NamespacePermission.Builder permissionBuilder =
1438         AccessControlProtos.NamespacePermission.newBuilder();
1439     for (AccessControlProtos.Permission.Action a : actions) {
1440       permissionBuilder.addAction(a);
1441     }
1442     if (namespace != null) {
1443       permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace));
1444     }
1445     ret.setType(AccessControlProtos.Permission.Type.Namespace)
1446        .setNamespacePermission(permissionBuilder);
1447     return AccessControlProtos.RevokeRequest.newBuilder()
1448       .setUserPermission(
1449           AccessControlProtos.UserPermission.newBuilder()
1450               .setUser(ByteString.copyFromUtf8(username))
1451               .setPermission(ret)
1452       ).build();
1453   }
1454 
1455   /**
1456    * Create a RegionOpenInfo based on given region info and version of offline node
1457    */
1458   private static RegionOpenInfo buildRegionOpenInfo(
1459       final HRegionInfo region, final int versionOfOfflineNode,
1460       final List<ServerName> favoredNodes) {
1461     RegionOpenInfo.Builder builder = RegionOpenInfo.newBuilder();
1462     builder.setRegion(HRegionInfo.convert(region));
1463     if (versionOfOfflineNode >= 0) {
1464       builder.setVersionOfOfflineNode(versionOfOfflineNode);
1465     }
1466     if (favoredNodes != null) {
1467       for (ServerName server : favoredNodes) {
1468         builder.addFavoredNodes(ProtobufUtil.toServerName(server));
1469       }
1470     }
1471     return builder.build();
1472   }
1473 }