View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.protobuf;
19  
20  import java.io.IOException;
21  import java.util.List;
22  
23  import org.apache.hadoop.hbase.util.ByteStringer;
24  
25  import org.apache.hadoop.classification.InterfaceAudience;
26  import org.apache.hadoop.hbase.CellScannable;
27  import org.apache.hadoop.hbase.DoNotRetryIOException;
28  import org.apache.hadoop.hbase.HColumnDescriptor;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.HRegionInfo;
31  import org.apache.hadoop.hbase.HTableDescriptor;
32  import org.apache.hadoop.hbase.ServerName;
33  import org.apache.hadoop.hbase.TableName;
34  import org.apache.hadoop.hbase.client.Action;
35  import org.apache.hadoop.hbase.client.Append;
36  import org.apache.hadoop.hbase.client.Delete;
37  import org.apache.hadoop.hbase.client.Durability;
38  import org.apache.hadoop.hbase.client.Get;
39  import org.apache.hadoop.hbase.client.Increment;
40  import org.apache.hadoop.hbase.client.Mutation;
41  import org.apache.hadoop.hbase.client.Put;
42  import org.apache.hadoop.hbase.client.RegionCoprocessorServiceExec;
43  import org.apache.hadoop.hbase.client.Row;
44  import org.apache.hadoop.hbase.client.RowMutations;
45  import org.apache.hadoop.hbase.client.Scan;
46  import org.apache.hadoop.hbase.exceptions.DeserializationException;
47  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
48  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
49  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
50  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CompactRegionRequest;
51  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.FlushRegionRequest;
52  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
53  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
54  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
55  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
56  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsRequest;
57  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
58  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest.RegionOpenInfo;
59  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterRequest;
60  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
61  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
62  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest;
63  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest.RegionUpdateInfo;
64  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
65  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
66  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest.FamilyPath;
67  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Column;
68  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Condition;
69  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
70  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutateRequest;
71  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
72  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue;
73  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue.QualifierValue;
74  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
75  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.RegionAction;
76  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
77  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.CompareType;
78  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
79  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
80  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AddColumnRequest;
81  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AssignRegionRequest;
82  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BalanceRequest;
83  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
84  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteColumnRequest;
85  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DeleteTableRequest;
86  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DisableTableRequest;
87  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.DispatchMergingRegionsRequest;
88  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest;
89  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.EnableTableRequest;
90  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetClusterStatusRequest;
91  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest;
92  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsRequest;
93  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest;
94  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.IsMasterRunningRequest;
95  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyColumnRequest;
96  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ModifyTableRequest;
97  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MoveRegionRequest;
98  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.OfflineRegionRequest;
99  import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.RunCatalogScanRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.SetBalancerRunningRequest;
101 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.TruncateTableRequest;
102 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.UnassignRegionRequest;
103 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.GetLastFlushedSequenceIdRequest;
104 import org.apache.hadoop.hbase.util.Bytes;
105 import org.apache.hadoop.hbase.util.Pair;
106 
107 import com.google.protobuf.ByteString;
108 
109 import static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.*;
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(ByteStringer.wrap(family));
142     ClientProtos.Get.Builder getBuilder =
143       ClientProtos.Get.newBuilder();
144     getBuilder.setRow(ByteStringer.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(ByteStringer.wrap(row));
190     mutateBuilder.setMutateType(MutationType.INCREMENT);
191     mutateBuilder.setDurability(ProtobufUtil.toDurability(durability));
192     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
193     columnBuilder.setFamily(ByteStringer.wrap(family));
194     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
195     valueBuilder.setValue(ByteStringer.wrap(Bytes.toBytes(amount)));
196     valueBuilder.setQualifier(ByteStringer.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(ByteStringer.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(ByteStringer.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(ByteStringer.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 server the serverName for the RPC
707   * @param regionOpenInfos info of a list of regions to open
708   * @param openForReplay
709   * @return a protocol buffer OpenRegionRequest
710   */
711  public static OpenRegionRequest
712      buildOpenRegionRequest(ServerName server, final List<Pair<HRegionInfo,
713          List<ServerName>>> regionOpenInfos, Boolean openForReplay) {
714    OpenRegionRequest.Builder builder = OpenRegionRequest.newBuilder();
715    for (Pair<HRegionInfo, List<ServerName>> regionOpenInfo: regionOpenInfos) {
716      builder.addOpenInfo(buildRegionOpenInfo(regionOpenInfo.getFirst(),
717        regionOpenInfo.getSecond(), openForReplay));
718    }
719    if (server != null) {
720      builder.setServerStartCode(server.getStartcode());
721    }
722    return builder.build();
723  }
724 
725  /**
726   * Create a protocol buffer OpenRegionRequest for a given region
727   *
728   * @param server the serverName for the RPC
729   * @param region the region to open
730   * @param favoredNodes
731   * @param openForReplay
732   * @return a protocol buffer OpenRegionRequest
733   */
734  public static OpenRegionRequest buildOpenRegionRequest(ServerName server,
735      final HRegionInfo region, List<ServerName> favoredNodes,
736      Boolean openForReplay) {
737    OpenRegionRequest.Builder builder = OpenRegionRequest.newBuilder();
738    builder.addOpenInfo(buildRegionOpenInfo(region, favoredNodes,
739      openForReplay));
740    if (server != null) {
741      builder.setServerStartCode(server.getStartcode());
742    }
743    return builder.build();
744  }
745 
746  /**
747   * Create a protocol buffer UpdateFavoredNodesRequest to update a list of favorednode mappings
748   * @param updateRegionInfos
749   * @return a protocol buffer UpdateFavoredNodesRequest
750   */
751  public static UpdateFavoredNodesRequest buildUpdateFavoredNodesRequest(
752      final List<Pair<HRegionInfo, List<ServerName>>> updateRegionInfos) {
753    UpdateFavoredNodesRequest.Builder ubuilder = UpdateFavoredNodesRequest.newBuilder();
754    for (Pair<HRegionInfo, List<ServerName>> pair : updateRegionInfos) {
755      RegionUpdateInfo.Builder builder = RegionUpdateInfo.newBuilder();
756      builder.setRegion(HRegionInfo.convert(pair.getFirst()));
757      for (ServerName server : pair.getSecond()) {
758        builder.addFavoredNodes(ProtobufUtil.toServerName(server));
759      }
760      ubuilder.addUpdateInfo(builder.build());
761    }
762    return ubuilder.build();
763  }
764 
765  /**
766   * Create a CloseRegionRequest for a given region name
767   *
768   * @param regionName the name of the region to close
769   * @return a CloseRegionRequest
770   */
771  public static CloseRegionRequest buildCloseRegionRequest(ServerName server,
772      final byte[] regionName) {
773    return buildCloseRegionRequest(server, regionName, null);
774  }
775 
776   public static CloseRegionRequest buildCloseRegionRequest(ServerName server,
777     final byte[] regionName, ServerName destinationServer) {
778     CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
779     RegionSpecifier region = buildRegionSpecifier(
780       RegionSpecifierType.REGION_NAME, regionName);
781     builder.setRegion(region);
782     if (destinationServer != null){
783       builder.setDestinationServer(ProtobufUtil.toServerName(destinationServer));
784     }
785     if (server != null) {
786       builder.setServerStartCode(server.getStartcode());
787     }
788     return builder.build();
789   }
790 
791  /**
792   * Create a CloseRegionRequest for a given encoded region name
793   *
794   * @param encodedRegionName the name of the region to close
795   * @return a CloseRegionRequest
796   */
797  public static CloseRegionRequest
798      buildCloseRegionRequest(ServerName server, final String encodedRegionName) {
799    CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder();
800    RegionSpecifier region = buildRegionSpecifier(
801      RegionSpecifierType.ENCODED_REGION_NAME,
802      Bytes.toBytes(encodedRegionName));
803    builder.setRegion(region);
804    if (server != null) {
805      builder.setServerStartCode(server.getStartcode());
806    }
807    return builder.build();
808  }
809 
810  /**
811   * Create a SplitRegionRequest for a given region name
812   *
813   * @param regionName the name of the region to split
814   * @param splitPoint the split point
815   * @return a SplitRegionRequest
816   */
817  public static SplitRegionRequest buildSplitRegionRequest(
818      final byte[] regionName, final byte[] splitPoint) {
819    SplitRegionRequest.Builder builder = SplitRegionRequest.newBuilder();
820    RegionSpecifier region = buildRegionSpecifier(
821      RegionSpecifierType.REGION_NAME, regionName);
822    builder.setRegion(region);
823    if (splitPoint != null) {
824      builder.setSplitPoint(ByteStringer.wrap(splitPoint));
825    }
826    return builder.build();
827  }
828 
829   /**
830    * Create a MergeRegionsRequest for the given regions
831    * @param regionA name of region a
832    * @param regionB name of region b
833    * @param forcible true if it is a compulsory merge
834    * @return a MergeRegionsRequest
835    */
836   public static MergeRegionsRequest buildMergeRegionsRequest(
837       final byte[] regionA, final byte[] regionB, final boolean forcible) {
838     MergeRegionsRequest.Builder builder = MergeRegionsRequest.newBuilder();
839     RegionSpecifier regionASpecifier = buildRegionSpecifier(
840         RegionSpecifierType.REGION_NAME, regionA);
841     RegionSpecifier regionBSpecifier = buildRegionSpecifier(
842         RegionSpecifierType.REGION_NAME, regionB);
843     builder.setRegionA(regionASpecifier);
844     builder.setRegionB(regionBSpecifier);
845     builder.setForcible(forcible);
846     return builder.build();
847   }
848 
849  /**
850   * Create a  CompactRegionRequest for a given region name
851   *
852   * @param regionName the name of the region to get info
853   * @param major indicator if it is a major compaction
854   * @return a CompactRegionRequest
855   */
856  public static CompactRegionRequest buildCompactRegionRequest(
857      final byte[] regionName, final boolean major, final byte [] family) {
858    CompactRegionRequest.Builder builder = CompactRegionRequest.newBuilder();
859    RegionSpecifier region = buildRegionSpecifier(
860      RegionSpecifierType.REGION_NAME, regionName);
861    builder.setRegion(region);
862    builder.setMajor(major);
863    if (family != null) {
864      builder.setFamily(ByteStringer.wrap(family));
865    }
866    return builder.build();
867  }
868 
869  /**
870   * @see {@link #buildRollWALWriterRequest()
871   */
872  private static RollWALWriterRequest ROLL_WAL_WRITER_REQUEST =
873      RollWALWriterRequest.newBuilder().build();
874 
875   /**
876   * Create a new RollWALWriterRequest
877   *
878   * @return a ReplicateWALEntryRequest
879   */
880  public static RollWALWriterRequest buildRollWALWriterRequest() {
881    return ROLL_WAL_WRITER_REQUEST;
882  }
883 
884  /**
885   * @see {@link #buildGetServerInfoRequest()}
886   */
887  private static GetServerInfoRequest GET_SERVER_INFO_REQUEST =
888    GetServerInfoRequest.newBuilder().build();
889 
890  /**
891   * Create a new GetServerInfoRequest
892   *
893   * @return a GetServerInfoRequest
894   */
895  public static GetServerInfoRequest buildGetServerInfoRequest() {
896    return GET_SERVER_INFO_REQUEST;
897  }
898 
899  /**
900   * Create a new StopServerRequest
901   *
902   * @param reason the reason to stop the server
903   * @return a StopServerRequest
904   */
905  public static StopServerRequest buildStopServerRequest(final String reason) {
906    StopServerRequest.Builder builder = StopServerRequest.newBuilder();
907    builder.setReason(reason);
908    return builder.build();
909  }
910 
911 //End utilities for Admin
912 
913   /**
914    * Convert a byte array to a protocol buffer RegionSpecifier
915    *
916    * @param type the region specifier type
917    * @param value the region specifier byte array value
918    * @return a protocol buffer RegionSpecifier
919    */
920   public static RegionSpecifier buildRegionSpecifier(
921       final RegionSpecifierType type, final byte[] value) {
922     RegionSpecifier.Builder regionBuilder = RegionSpecifier.newBuilder();
923     regionBuilder.setValue(ByteStringer.wrap(value));
924     regionBuilder.setType(type);
925     return regionBuilder.build();
926   }
927 
928   /**
929    * Create a protocol buffer Condition
930    *
931    * @param row
932    * @param family
933    * @param qualifier
934    * @param comparator
935    * @param compareType
936    * @return a Condition
937    * @throws IOException
938    */
939   private static Condition buildCondition(final byte[] row,
940       final byte[] family, final byte [] qualifier,
941       final ByteArrayComparable comparator,
942       final CompareType compareType) throws IOException {
943     Condition.Builder builder = Condition.newBuilder();
944     builder.setRow(ByteStringer.wrap(row));
945     builder.setFamily(ByteStringer.wrap(family));
946     builder.setQualifier(ByteStringer.wrap(qualifier));
947     builder.setComparator(ProtobufUtil.toComparator(comparator));
948     builder.setCompareType(compareType);
949     return builder.build();
950   }
951 
952   /**
953    * Create a protocol buffer AddColumnRequest
954    *
955    * @param tableName
956    * @param column
957    * @return an AddColumnRequest
958    */
959   public static AddColumnRequest buildAddColumnRequest(
960       final TableName tableName, final HColumnDescriptor column) {
961     AddColumnRequest.Builder builder = AddColumnRequest.newBuilder();
962     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
963     builder.setColumnFamilies(column.convert());
964     return builder.build();
965   }
966 
967   /**
968    * Create a protocol buffer DeleteColumnRequest
969    *
970    * @param tableName
971    * @param columnName
972    * @return a DeleteColumnRequest
973    */
974   public static DeleteColumnRequest buildDeleteColumnRequest(
975       final TableName tableName, final byte [] columnName) {
976     DeleteColumnRequest.Builder builder = DeleteColumnRequest.newBuilder();
977     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
978     builder.setColumnName(ByteStringer.wrap(columnName));
979     return builder.build();
980   }
981 
982   /**
983    * Create a protocol buffer ModifyColumnRequest
984    *
985    * @param tableName
986    * @param column
987    * @return an ModifyColumnRequest
988    */
989   public static ModifyColumnRequest buildModifyColumnRequest(
990       final TableName tableName, final HColumnDescriptor column) {
991     ModifyColumnRequest.Builder builder = ModifyColumnRequest.newBuilder();
992     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
993     builder.setColumnFamilies(column.convert());
994     return builder.build();
995   }
996 
997   /**
998    * Create a protocol buffer MoveRegionRequest
999    *
1000    * @param encodedRegionName
1001    * @param destServerName
1002    * @return A MoveRegionRequest
1003    * @throws DeserializationException
1004    */
1005   public static MoveRegionRequest buildMoveRegionRequest(
1006       final byte [] encodedRegionName, final byte [] destServerName) throws
1007       DeserializationException {
1008 	MoveRegionRequest.Builder builder = MoveRegionRequest.newBuilder();
1009     builder.setRegion(
1010       buildRegionSpecifier(RegionSpecifierType.ENCODED_REGION_NAME,encodedRegionName));
1011     if (destServerName != null) {
1012       builder.setDestServerName(
1013         ProtobufUtil.toServerName(ServerName.valueOf(Bytes.toString(destServerName))));
1014     }
1015     return builder.build();
1016   }
1017 
1018   public static DispatchMergingRegionsRequest buildDispatchMergingRegionsRequest(
1019       final byte[] encodedNameOfRegionA, final byte[] encodedNameOfRegionB,
1020       final boolean forcible) throws DeserializationException {
1021     DispatchMergingRegionsRequest.Builder builder = DispatchMergingRegionsRequest.newBuilder();
1022     builder.setRegionA(buildRegionSpecifier(
1023         RegionSpecifierType.ENCODED_REGION_NAME, encodedNameOfRegionA));
1024     builder.setRegionB(buildRegionSpecifier(
1025         RegionSpecifierType.ENCODED_REGION_NAME, encodedNameOfRegionB));
1026     builder.setForcible(forcible);
1027     return builder.build();
1028   }
1029 
1030   /**
1031    * Create a protocol buffer AssignRegionRequest
1032    *
1033    * @param regionName
1034    * @return an AssignRegionRequest
1035    */
1036   public static AssignRegionRequest buildAssignRegionRequest(final byte [] regionName) {
1037     AssignRegionRequest.Builder builder = AssignRegionRequest.newBuilder();
1038     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1039     return builder.build();
1040   }
1041 
1042   /**
1043    * Creates a protocol buffer UnassignRegionRequest
1044    *
1045    * @param regionName
1046    * @param force
1047    * @return an UnassignRegionRequest
1048    */
1049   public static UnassignRegionRequest buildUnassignRegionRequest(
1050       final byte [] regionName, final boolean force) {
1051     UnassignRegionRequest.Builder builder = UnassignRegionRequest.newBuilder();
1052     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1053     builder.setForce(force);
1054     return builder.build();
1055   }
1056 
1057   /**
1058    * Creates a protocol buffer OfflineRegionRequest
1059    *
1060    * @param regionName
1061    * @return an OfflineRegionRequest
1062    */
1063   public static OfflineRegionRequest buildOfflineRegionRequest(final byte [] regionName) {
1064     OfflineRegionRequest.Builder builder = OfflineRegionRequest.newBuilder();
1065     builder.setRegion(buildRegionSpecifier(RegionSpecifierType.REGION_NAME,regionName));
1066     return builder.build();
1067   }
1068 
1069   /**
1070    * Creates a protocol buffer DeleteTableRequest
1071    *
1072    * @param tableName
1073    * @return a DeleteTableRequest
1074    */
1075   public static DeleteTableRequest buildDeleteTableRequest(final TableName tableName) {
1076     DeleteTableRequest.Builder builder = DeleteTableRequest.newBuilder();
1077     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1078     return builder.build();
1079   }
1080 
1081   /**
1082    * Creates a protocol buffer TruncateTableRequest
1083    *
1084    * @param tableName name of table to truncate
1085    * @param preserveSplits True if the splits should be preserved
1086    * @return a TruncateTableRequest
1087    */
1088   public static TruncateTableRequest buildTruncateTableRequest(final TableName tableName,
1089         boolean preserveSplits) {
1090     TruncateTableRequest.Builder builder = TruncateTableRequest.newBuilder();
1091     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1092     builder.setPreserveSplits(preserveSplits);
1093     return builder.build();
1094   }
1095 
1096   /**
1097    * Creates a protocol buffer EnableTableRequest
1098    *
1099    * @param tableName
1100    * @return an EnableTableRequest
1101    */
1102   public static EnableTableRequest buildEnableTableRequest(final TableName tableName) {
1103     EnableTableRequest.Builder builder = EnableTableRequest.newBuilder();
1104     builder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1105     return builder.build();
1106   }
1107 
1108   /**
1109    * Creates a protocol buffer DisableTableRequest
1110    *
1111    * @param tableName
1112    * @return a DisableTableRequest
1113    */
1114   public static DisableTableRequest buildDisableTableRequest(final TableName tableName) {
1115     DisableTableRequest.Builder builder = DisableTableRequest.newBuilder();
1116     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1117     return builder.build();
1118   }
1119 
1120   /**
1121    * Creates a protocol buffer CreateTableRequest
1122    *
1123    * @param hTableDesc
1124    * @param splitKeys
1125    * @return a CreateTableRequest
1126    */
1127   public static CreateTableRequest buildCreateTableRequest(
1128       final HTableDescriptor hTableDesc, final byte [][] splitKeys) {
1129     CreateTableRequest.Builder builder = CreateTableRequest.newBuilder();
1130     builder.setTableSchema(hTableDesc.convert());
1131     if (splitKeys != null) {
1132       for (byte [] splitKey : splitKeys) {
1133         builder.addSplitKeys(ByteStringer.wrap(splitKey));
1134       }
1135     }
1136     return builder.build();
1137   }
1138 
1139 
1140   /**
1141    * Creates a protocol buffer ModifyTableRequest
1142    *
1143    * @param tableName
1144    * @param hTableDesc
1145    * @return a ModifyTableRequest
1146    */
1147   public static ModifyTableRequest buildModifyTableRequest(
1148       final TableName tableName, final HTableDescriptor hTableDesc) {
1149     ModifyTableRequest.Builder builder = ModifyTableRequest.newBuilder();
1150     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1151     builder.setTableSchema(hTableDesc.convert());
1152     return builder.build();
1153   }
1154 
1155   /**
1156    * Creates a protocol buffer GetSchemaAlterStatusRequest
1157    *
1158    * @param tableName
1159    * @return a GetSchemaAlterStatusRequest
1160    */
1161   public static GetSchemaAlterStatusRequest buildGetSchemaAlterStatusRequest(
1162       final TableName tableName) {
1163     GetSchemaAlterStatusRequest.Builder builder = GetSchemaAlterStatusRequest.newBuilder();
1164     builder.setTableName(ProtobufUtil.toProtoTableName((tableName)));
1165     return builder.build();
1166   }
1167 
1168   /**
1169    * Creates a protocol buffer GetTableDescriptorsRequest
1170    *
1171    * @param tableNames
1172    * @return a GetTableDescriptorsRequest
1173    */
1174   public static GetTableDescriptorsRequest buildGetTableDescriptorsRequest(
1175       final List<TableName> tableNames) {
1176     GetTableDescriptorsRequest.Builder builder = GetTableDescriptorsRequest.newBuilder();
1177     if (tableNames != null) {
1178       for (TableName tableName : tableNames) {
1179         builder.addTableNames(ProtobufUtil.toProtoTableName(tableName));
1180       }
1181     }
1182     return builder.build();
1183   }
1184 
1185   /**
1186    * Creates a protocol buffer GetTableStateRequest
1187    *
1188    * @param tableName table to get request for
1189    * @return a GetTableStateRequest
1190    */
1191   public static GetTableStateRequest buildGetTableStateRequest(
1192           final TableName tableName) {
1193     return GetTableStateRequest.newBuilder()
1194             .setTableName(ProtobufUtil.toProtoTableName(tableName))
1195             .build();
1196   }
1197 
1198   /**
1199    * Creates a protocol buffer GetTableDescriptorsRequest for a single table
1200    *
1201    * @param tableName the table name
1202    * @return a GetTableDescriptorsRequest
1203    */
1204   public static GetTableDescriptorsRequest buildGetTableDescriptorsRequest(
1205       final TableName tableName) {
1206     return GetTableDescriptorsRequest.newBuilder()
1207       .addTableNames(ProtobufUtil.toProtoTableName(tableName))
1208       .build();
1209   }
1210 
1211   /**
1212    * Creates a protocol buffer IsMasterRunningRequest
1213    *
1214    * @return a IsMasterRunningRequest
1215    */
1216   public static IsMasterRunningRequest buildIsMasterRunningRequest() {
1217     return IsMasterRunningRequest.newBuilder().build();
1218   }
1219 
1220   /**
1221    * Creates a protocol buffer BalanceRequest
1222    *
1223    * @return a BalanceRequest
1224    */
1225   public static BalanceRequest buildBalanceRequest() {
1226     return BalanceRequest.newBuilder().build();
1227   }
1228 
1229   /**
1230    * Creates a protocol buffer SetBalancerRunningRequest
1231    *
1232    * @param on
1233    * @param synchronous
1234    * @return a SetBalancerRunningRequest
1235    */
1236   public static SetBalancerRunningRequest buildSetBalancerRunningRequest(boolean on, boolean synchronous) {
1237     return SetBalancerRunningRequest.newBuilder().setOn(on).setSynchronous(synchronous).build();
1238   }
1239 
1240   /**
1241    * @see {@link #buildGetClusterStatusRequest}
1242    */
1243   private static final GetClusterStatusRequest GET_CLUSTER_STATUS_REQUEST =
1244       GetClusterStatusRequest.newBuilder().build();
1245 
1246   /**
1247    * Creates a protocol buffer GetClusterStatusRequest
1248    *
1249    * @return A GetClusterStatusRequest
1250    */
1251   public static GetClusterStatusRequest buildGetClusterStatusRequest() {
1252     return GET_CLUSTER_STATUS_REQUEST;
1253   }
1254 
1255   /**
1256    * @see {@link #buildCatalogScanRequest}
1257    */
1258   private static final RunCatalogScanRequest CATALOG_SCAN_REQUEST =
1259     RunCatalogScanRequest.newBuilder().build();
1260 
1261   /**
1262    * Creates a request for running a catalog scan
1263    * @return A {@link RunCatalogScanRequest}
1264    */
1265   public static RunCatalogScanRequest buildCatalogScanRequest() {
1266     return CATALOG_SCAN_REQUEST;
1267   }
1268 
1269   /**
1270    * Creates a request for enabling/disabling the catalog janitor
1271    * @return A {@link EnableCatalogJanitorRequest}
1272    */
1273   public static EnableCatalogJanitorRequest buildEnableCatalogJanitorRequest(boolean enable) {
1274     return EnableCatalogJanitorRequest.newBuilder().setEnable(enable).build();
1275   }
1276 
1277   /**
1278    * @see {@link #buildIsCatalogJanitorEnabledRequest()}
1279    */
1280   private static final IsCatalogJanitorEnabledRequest IS_CATALOG_JANITOR_ENABLED_REQUEST =
1281     IsCatalogJanitorEnabledRequest.newBuilder().build();
1282 
1283   /**
1284    * Creates a request for querying the master whether the catalog janitor is enabled
1285    * @return A {@link IsCatalogJanitorEnabledRequest}
1286    */
1287   public static IsCatalogJanitorEnabledRequest buildIsCatalogJanitorEnabledRequest() {
1288     return IS_CATALOG_JANITOR_ENABLED_REQUEST;
1289   }
1290 
1291   /**
1292    * Creates a request for querying the master the last flushed sequence Id for a region
1293    * @param regionName
1294    * @return A {@link GetLastFlushedSequenceIdRequest}
1295    */
1296   public static GetLastFlushedSequenceIdRequest buildGetLastFlushedSequenceIdRequest(
1297       byte[] regionName) {
1298     return GetLastFlushedSequenceIdRequest.newBuilder().setRegionName(
1299         ByteStringer.wrap(regionName)).build();
1300   }
1301 
1302   /**
1303    * Create a request to grant user permissions.
1304    *
1305    * @param username the short user name who to grant permissions
1306    * @param actions the permissions to be granted
1307    * @return A {@link AccessControlProtos} GrantRequest
1308    */
1309   public static AccessControlProtos.GrantRequest buildGrantRequest(
1310       String username, AccessControlProtos.Permission.Action... actions) {
1311     AccessControlProtos.Permission.Builder ret =
1312         AccessControlProtos.Permission.newBuilder();
1313     AccessControlProtos.GlobalPermission.Builder permissionBuilder =
1314         AccessControlProtos.GlobalPermission.newBuilder();
1315     for (AccessControlProtos.Permission.Action a : actions) {
1316       permissionBuilder.addAction(a);
1317     }
1318     ret.setType(AccessControlProtos.Permission.Type.Global)
1319        .setGlobalPermission(permissionBuilder);
1320     return AccessControlProtos.GrantRequest.newBuilder()
1321       .setUserPermission(
1322           AccessControlProtos.UserPermission.newBuilder()
1323               .setUser(ByteString.copyFromUtf8(username))
1324               .setPermission(ret)
1325       ).build();
1326   }
1327 
1328   /**
1329    * Create a request to grant user permissions.
1330    *
1331    * @param username the short user name who to grant permissions
1332    * @param tableName optional table name the permissions apply
1333    * @param family optional column family
1334    * @param qualifier optional qualifier
1335    * @param actions the permissions to be granted
1336    * @return A {@link AccessControlProtos} GrantRequest
1337    */
1338   public static AccessControlProtos.GrantRequest buildGrantRequest(
1339       String username, TableName tableName, byte[] family, byte[] qualifier,
1340       AccessControlProtos.Permission.Action... actions) {
1341     AccessControlProtos.Permission.Builder ret =
1342         AccessControlProtos.Permission.newBuilder();
1343     AccessControlProtos.TablePermission.Builder permissionBuilder =
1344         AccessControlProtos.TablePermission.newBuilder();
1345     for (AccessControlProtos.Permission.Action a : actions) {
1346       permissionBuilder.addAction(a);
1347     }
1348     if (tableName == null) {
1349       throw new NullPointerException("TableName cannot be null");
1350     }
1351     permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1352 
1353     if (family != null) {
1354       permissionBuilder.setFamily(ByteStringer.wrap(family));
1355     }
1356     if (qualifier != null) {
1357       permissionBuilder.setQualifier(ByteStringer.wrap(qualifier));
1358     }
1359     ret.setType(AccessControlProtos.Permission.Type.Table)
1360        .setTablePermission(permissionBuilder);
1361     return AccessControlProtos.GrantRequest.newBuilder()
1362       .setUserPermission(
1363           AccessControlProtos.UserPermission.newBuilder()
1364               .setUser(ByteString.copyFromUtf8(username))
1365               .setPermission(ret)
1366       ).build();
1367   }
1368 
1369   /**
1370    * Create a request to grant user permissions.
1371    *
1372    * @param username the short user name who to grant permissions
1373    * @param namespace optional table name the permissions apply
1374    * @param actions the permissions to be granted
1375    * @return A {@link AccessControlProtos} GrantRequest
1376    */
1377   public static AccessControlProtos.GrantRequest buildGrantRequest(
1378       String username, String namespace,
1379       AccessControlProtos.Permission.Action... actions) {
1380     AccessControlProtos.Permission.Builder ret =
1381         AccessControlProtos.Permission.newBuilder();
1382     AccessControlProtos.NamespacePermission.Builder permissionBuilder =
1383         AccessControlProtos.NamespacePermission.newBuilder();
1384     for (AccessControlProtos.Permission.Action a : actions) {
1385       permissionBuilder.addAction(a);
1386     }
1387     if (namespace != null) {
1388       permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace));
1389     }
1390     ret.setType(AccessControlProtos.Permission.Type.Namespace)
1391        .setNamespacePermission(permissionBuilder);
1392     return AccessControlProtos.GrantRequest.newBuilder()
1393       .setUserPermission(
1394           AccessControlProtos.UserPermission.newBuilder()
1395               .setUser(ByteString.copyFromUtf8(username))
1396               .setPermission(ret)
1397       ).build();
1398   }
1399 
1400   /**
1401    * Create a request to revoke user permissions.
1402    *
1403    * @param username the short user name whose permissions to be revoked
1404    * @param actions the permissions to be revoked
1405    * @return A {@link AccessControlProtos} RevokeRequest
1406    */
1407   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1408       String username, AccessControlProtos.Permission.Action... actions) {
1409     AccessControlProtos.Permission.Builder ret =
1410         AccessControlProtos.Permission.newBuilder();
1411     AccessControlProtos.GlobalPermission.Builder permissionBuilder =
1412         AccessControlProtos.GlobalPermission.newBuilder();
1413     for (AccessControlProtos.Permission.Action a : actions) {
1414       permissionBuilder.addAction(a);
1415     }
1416     ret.setType(AccessControlProtos.Permission.Type.Global)
1417        .setGlobalPermission(permissionBuilder);
1418     return AccessControlProtos.RevokeRequest.newBuilder()
1419       .setUserPermission(
1420           AccessControlProtos.UserPermission.newBuilder()
1421               .setUser(ByteString.copyFromUtf8(username))
1422               .setPermission(ret)
1423       ).build();
1424   }
1425 
1426   /**
1427    * Create a request to revoke user permissions.
1428    *
1429    * @param username the short user name whose permissions to be revoked
1430    * @param tableName optional table name the permissions apply
1431    * @param family optional column family
1432    * @param qualifier optional qualifier
1433    * @param actions the permissions to be revoked
1434    * @return A {@link AccessControlProtos} RevokeRequest
1435    */
1436   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1437       String username, TableName tableName, byte[] family, byte[] qualifier,
1438       AccessControlProtos.Permission.Action... actions) {
1439     AccessControlProtos.Permission.Builder ret =
1440         AccessControlProtos.Permission.newBuilder();
1441     AccessControlProtos.TablePermission.Builder permissionBuilder =
1442         AccessControlProtos.TablePermission.newBuilder();
1443     for (AccessControlProtos.Permission.Action a : actions) {
1444       permissionBuilder.addAction(a);
1445     }
1446     if (tableName != null) {
1447       permissionBuilder.setTableName(ProtobufUtil.toProtoTableName(tableName));
1448     }
1449     if (family != null) {
1450       permissionBuilder.setFamily(ByteStringer.wrap(family));
1451     }
1452     if (qualifier != null) {
1453       permissionBuilder.setQualifier(ByteStringer.wrap(qualifier));
1454     }
1455     ret.setType(AccessControlProtos.Permission.Type.Table)
1456        .setTablePermission(permissionBuilder);
1457     return AccessControlProtos.RevokeRequest.newBuilder()
1458       .setUserPermission(
1459           AccessControlProtos.UserPermission.newBuilder()
1460               .setUser(ByteString.copyFromUtf8(username))
1461               .setPermission(ret)
1462       ).build();
1463   }
1464 
1465   /**
1466    * Create a request to revoke user permissions.
1467    *
1468    * @param username the short user name whose permissions to be revoked
1469    * @param namespace optional table name the permissions apply
1470    * @param actions the permissions to be revoked
1471    * @return A {@link AccessControlProtos} RevokeRequest
1472    */
1473   public static AccessControlProtos.RevokeRequest buildRevokeRequest(
1474       String username, String namespace,
1475       AccessControlProtos.Permission.Action... actions) {
1476     AccessControlProtos.Permission.Builder ret =
1477         AccessControlProtos.Permission.newBuilder();
1478     AccessControlProtos.NamespacePermission.Builder permissionBuilder =
1479         AccessControlProtos.NamespacePermission.newBuilder();
1480     for (AccessControlProtos.Permission.Action a : actions) {
1481       permissionBuilder.addAction(a);
1482     }
1483     if (namespace != null) {
1484       permissionBuilder.setNamespaceName(ByteString.copyFromUtf8(namespace));
1485     }
1486     ret.setType(AccessControlProtos.Permission.Type.Namespace)
1487        .setNamespacePermission(permissionBuilder);
1488     return AccessControlProtos.RevokeRequest.newBuilder()
1489       .setUserPermission(
1490           AccessControlProtos.UserPermission.newBuilder()
1491               .setUser(ByteString.copyFromUtf8(username))
1492               .setPermission(ret)
1493       ).build();
1494   }
1495 
1496   /**
1497    * Create a RegionOpenInfo based on given region info and version of offline node
1498    */
1499   private static RegionOpenInfo buildRegionOpenInfo(
1500       final HRegionInfo region,
1501       final List<ServerName> favoredNodes, Boolean openForReplay) {
1502     RegionOpenInfo.Builder builder = RegionOpenInfo.newBuilder();
1503     builder.setRegion(HRegionInfo.convert(region));
1504     if (favoredNodes != null) {
1505       for (ServerName server : favoredNodes) {
1506         builder.addFavoredNodes(ProtobufUtil.toServerName(server));
1507       }
1508     }
1509     if(openForReplay != null) {
1510       builder.setOpenForDistributedLogReplay(openForReplay);
1511     }
1512     return builder.build();
1513   }
1514 }