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