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