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