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  
21  import static org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME;
22  
23  import java.io.ByteArrayOutputStream;
24  import java.io.IOException;
25  import java.lang.reflect.Constructor;
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  import java.lang.reflect.ParameterizedType;
29  import java.lang.reflect.Type;
30  import java.nio.ByteBuffer;
31  import java.util.ArrayList;
32  import java.util.Collection;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Map.Entry;
37  import java.util.NavigableSet;
38  import java.util.concurrent.TimeUnit;
39  
40  import org.apache.hadoop.hbase.classification.InterfaceAudience;
41  import org.apache.hadoop.conf.Configuration;
42  import org.apache.hadoop.fs.Path;
43  import org.apache.hadoop.hbase.Cell;
44  import org.apache.hadoop.hbase.CellScanner;
45  import org.apache.hadoop.hbase.CellUtil;
46  import org.apache.hadoop.hbase.DoNotRetryIOException;
47  import org.apache.hadoop.hbase.HBaseConfiguration;
48  import org.apache.hadoop.hbase.HConstants;
49  import org.apache.hadoop.hbase.HRegionInfo;
50  import org.apache.hadoop.hbase.HTableDescriptor;
51  import org.apache.hadoop.hbase.KeyValue;
52  import org.apache.hadoop.hbase.NamespaceDescriptor;
53  import org.apache.hadoop.hbase.ServerName;
54  import org.apache.hadoop.hbase.TableName;
55  import org.apache.hadoop.hbase.Tag;
56  import org.apache.hadoop.hbase.client.Append;
57  import org.apache.hadoop.hbase.client.Consistency;
58  import org.apache.hadoop.hbase.client.Delete;
59  import org.apache.hadoop.hbase.client.Durability;
60  import org.apache.hadoop.hbase.client.Get;
61  import org.apache.hadoop.hbase.client.Increment;
62  import org.apache.hadoop.hbase.client.Mutation;
63  import org.apache.hadoop.hbase.client.Put;
64  import org.apache.hadoop.hbase.client.Result;
65  import org.apache.hadoop.hbase.client.Scan;
66  import org.apache.hadoop.hbase.client.metrics.ScanMetrics;
67  import org.apache.hadoop.hbase.exceptions.DeserializationException;
68  import org.apache.hadoop.hbase.filter.ByteArrayComparable;
69  import org.apache.hadoop.hbase.filter.Filter;
70  import org.apache.hadoop.hbase.io.TimeRange;
71  import org.apache.hadoop.hbase.protobuf.ProtobufMagic;
72  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos;
73  import org.apache.hadoop.hbase.protobuf.generated.AccessControlProtos.AccessControlService;
74  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
75  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionRequest;
76  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.CloseRegionResponse;
77  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionRequest;
78  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetOnlineRegionResponse;
79  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoRequest;
80  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetRegionInfoResponse;
81  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoRequest;
82  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetServerInfoResponse;
83  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileRequest;
84  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.GetStoreFileResponse;
85  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.MergeRegionsRequest;
86  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.OpenRegionRequest;
87  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ServerInfo;
88  import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
89  import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
90  import org.apache.hadoop.hbase.protobuf.generated.CellProtos;
91  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
92  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
93  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileResponse;
94  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ClientService;
95  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.Column;
96  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceCall;
97  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceRequest;
98  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.CoprocessorServiceResponse;
99  import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetRequest;
100 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.GetResponse;
101 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto;
102 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue;
103 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.ColumnValue.QualifierValue;
104 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.DeleteType;
105 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.MutationProto.MutationType;
106 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.ScanRequest;
107 import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos.RegionLoad;
108 import org.apache.hadoop.hbase.protobuf.generated.ComparatorProtos;
109 import org.apache.hadoop.hbase.protobuf.generated.FilterProtos;
110 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
111 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameBytesPair;
112 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
113 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier;
114 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType;
115 import org.apache.hadoop.hbase.protobuf.generated.MapReduceProtos;
116 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.CreateTableRequest;
117 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.GetTableDescriptorsResponse;
118 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.MasterService;
119 import org.apache.hadoop.hbase.protobuf.generated.QuotaProtos;
120 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest;
121 import org.apache.hadoop.hbase.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;
122 import org.apache.hadoop.hbase.protobuf.generated.WALProtos;
123 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.CompactionDescriptor;
124 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor;
125 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.FlushDescriptor.FlushAction;
126 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor;
127 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.RegionEventDescriptor.EventType;
128 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.BulkLoadDescriptor;
129 import org.apache.hadoop.hbase.protobuf.generated.WALProtos.StoreDescriptor;
130 import org.apache.hadoop.hbase.quotas.QuotaScope;
131 import org.apache.hadoop.hbase.quotas.QuotaType;
132 import org.apache.hadoop.hbase.quotas.ThrottleType;
133 import org.apache.hadoop.hbase.security.access.Permission;
134 import org.apache.hadoop.hbase.security.access.TablePermission;
135 import org.apache.hadoop.hbase.security.access.UserPermission;
136 import org.apache.hadoop.hbase.security.token.AuthenticationTokenIdentifier;
137 import org.apache.hadoop.hbase.security.visibility.Authorizations;
138 import org.apache.hadoop.hbase.security.visibility.CellVisibility;
139 import org.apache.hadoop.hbase.util.ByteStringer;
140 import org.apache.hadoop.hbase.util.Bytes;
141 import org.apache.hadoop.hbase.util.DynamicClassLoader;
142 import org.apache.hadoop.hbase.util.ExceptionUtil;
143 import org.apache.hadoop.hbase.util.Methods;
144 import org.apache.hadoop.hbase.util.Pair;
145 import org.apache.hadoop.io.Text;
146 import org.apache.hadoop.ipc.RemoteException;
147 import org.apache.hadoop.security.token.Token;
148 
149 import com.google.common.collect.ArrayListMultimap;
150 import com.google.common.collect.ListMultimap;
151 import com.google.common.collect.Lists;
152 import com.google.protobuf.ByteString;
153 import com.google.protobuf.InvalidProtocolBufferException;
154 import com.google.protobuf.Message;
155 import com.google.protobuf.Parser;
156 import com.google.protobuf.RpcChannel;
157 import com.google.protobuf.Service;
158 import com.google.protobuf.ServiceException;
159 import com.google.protobuf.TextFormat;
160 
161 /**
162  * Protobufs utility.
163  */
164 @edu.umd.cs.findbugs.annotations.SuppressWarnings(value="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED",
165   justification="None. Address sometime.")
166 @InterfaceAudience.Private // TODO: some clients (Hive, etc) use this class
167 public final class ProtobufUtil {
168 
169   private ProtobufUtil() {
170   }
171 
172   /**
173    * Primitive type to class mapping.
174    */
175   private final static Map<String, Class<?>>
176     PRIMITIVES = new HashMap<String, Class<?>>();
177 
178   /**
179    * Many results are simple: no cell, exists true or false. To save on object creations,
180    *  we reuse them across calls.
181    */
182   private final static Cell[] EMPTY_CELL_ARRAY = new Cell[]{};
183   private final static Result EMPTY_RESULT = Result.create(EMPTY_CELL_ARRAY);
184   private final static Result EMPTY_RESULT_EXISTS_TRUE = Result.create(null, true);
185   private final static Result EMPTY_RESULT_EXISTS_FALSE = Result.create(null, false);
186   private final static Result EMPTY_RESULT_STALE = Result.create(EMPTY_CELL_ARRAY, null, true);
187   private final static Result EMPTY_RESULT_EXISTS_TRUE_STALE
188     = Result.create((Cell[])null, true, true);
189   private final static Result EMPTY_RESULT_EXISTS_FALSE_STALE
190     = Result.create((Cell[])null, false, true);
191 
192   private final static ClientProtos.Result EMPTY_RESULT_PB;
193   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE;
194   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE;
195   private final static ClientProtos.Result EMPTY_RESULT_PB_STALE;
196   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE_STALE;
197   private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE_STALE;
198 
199 
200   static {
201     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
202 
203     builder.setExists(true);
204     builder.setAssociatedCellCount(0);
205     EMPTY_RESULT_PB_EXISTS_TRUE =  builder.build();
206 
207     builder.setStale(true);
208     EMPTY_RESULT_PB_EXISTS_TRUE_STALE = builder.build();
209     builder.clear();
210 
211     builder.setExists(false);
212     builder.setAssociatedCellCount(0);
213     EMPTY_RESULT_PB_EXISTS_FALSE =  builder.build();
214     builder.setStale(true);
215     EMPTY_RESULT_PB_EXISTS_FALSE_STALE = builder.build();
216 
217     builder.clear();
218     builder.setAssociatedCellCount(0);
219     EMPTY_RESULT_PB =  builder.build();
220     builder.setStale(true);
221     EMPTY_RESULT_PB_STALE = builder.build();
222   }
223 
224   /**
225    * Dynamic class loader to load filter/comparators
226    */
227   private final static ClassLoader CLASS_LOADER;
228 
229   static {
230     ClassLoader parent = ProtobufUtil.class.getClassLoader();
231     Configuration conf = HBaseConfiguration.create();
232     CLASS_LOADER = new DynamicClassLoader(conf, parent);
233 
234     PRIMITIVES.put(Boolean.TYPE.getName(), Boolean.TYPE);
235     PRIMITIVES.put(Byte.TYPE.getName(), Byte.TYPE);
236     PRIMITIVES.put(Character.TYPE.getName(), Character.TYPE);
237     PRIMITIVES.put(Short.TYPE.getName(), Short.TYPE);
238     PRIMITIVES.put(Integer.TYPE.getName(), Integer.TYPE);
239     PRIMITIVES.put(Long.TYPE.getName(), Long.TYPE);
240     PRIMITIVES.put(Float.TYPE.getName(), Float.TYPE);
241     PRIMITIVES.put(Double.TYPE.getName(), Double.TYPE);
242     PRIMITIVES.put(Void.TYPE.getName(), Void.TYPE);
243   }
244 
245   /**
246    * Prepend the passed bytes with four bytes of magic, {@link ProtobufMagic#PB_MAGIC},
247    * to flag what follows as a protobuf in hbase.  Prepend these bytes to all content written to
248    * znodes, etc.
249    * @param bytes Bytes to decorate
250    * @return The passed <code>bytes</codes> with magic prepended (Creates a new
251    * byte array that is <code>bytes.length</code> plus {@link ProtobufMagic#PB_MAGIC}.length.
252    */
253   public static byte [] prependPBMagic(final byte [] bytes) {
254     return Bytes.add(ProtobufMagic.PB_MAGIC, bytes);
255   }
256 
257   /**
258    * @param bytes Bytes to check.
259    * @return True if passed <code>bytes</code> has {@link ProtobufMagic#PB_MAGIC} for a prefix.
260    */
261   public static boolean isPBMagicPrefix(final byte [] bytes) {
262     if (bytes == null) return false;
263     return isPBMagicPrefix(bytes, 0, bytes.length);
264   }
265 
266   /**
267    * @param bytes Bytes to check.
268    * @return True if passed <code>bytes</code> has {@link ProtobufMagic#PB_MAGIC} for a prefix.
269    */
270   public static boolean isPBMagicPrefix(final byte [] bytes, int offset, int len) {
271     if (bytes == null || len < ProtobufMagic.PB_MAGIC.length) return false;
272     return Bytes.compareTo(ProtobufMagic.PB_MAGIC, 0, ProtobufMagic.PB_MAGIC.length,
273       bytes, offset, ProtobufMagic.PB_MAGIC.length) == 0;
274   }
275 
276   /**
277    * @param bytes
278    * @throws DeserializationException if we are missing the pb magic prefix
279    */
280   public static void expectPBMagicPrefix(final byte [] bytes) throws DeserializationException {
281     if (!isPBMagicPrefix(bytes)) {
282       throw new DeserializationException("Missing pb magic " +
283           Bytes.toString(ProtobufMagic.PB_MAGIC) + " prefix");
284     }
285   }
286 
287   /**
288    * @return Length of {@link ProtobufMagic#PB_MAGIC}
289    */
290   public static int lengthOfPBMagic() {
291     return ProtobufMagic.PB_MAGIC.length;
292   }
293 
294   /**
295    * Return the IOException thrown by the remote server wrapped in
296    * ServiceException as cause.
297    *
298    * @param se ServiceException that wraps IO exception thrown by the server
299    * @return Exception wrapped in ServiceException or
300    *   a new IOException that wraps the unexpected ServiceException.
301    */
302   public static IOException getRemoteException(ServiceException se) {
303     Throwable e = se.getCause();
304     if (e == null) {
305       return new IOException(se);
306     }
307     if (ExceptionUtil.isInterrupt(e)) {
308       return ExceptionUtil.asInterrupt(e);
309     }
310     if (e instanceof RemoteException) {
311       e = ((RemoteException) e).unwrapRemoteException();
312     }
313     return e instanceof IOException ? (IOException) e : new IOException(se);
314   }
315 
316   /**
317    * Convert a ServerName to a protocol buffer ServerName
318    *
319    * @param serverName the ServerName to convert
320    * @return the converted protocol buffer ServerName
321    * @see #toServerName(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ServerName)
322    */
323   public static HBaseProtos.ServerName
324       toServerName(final ServerName serverName) {
325     if (serverName == null) return null;
326     HBaseProtos.ServerName.Builder builder =
327       HBaseProtos.ServerName.newBuilder();
328     builder.setHostName(serverName.getHostname());
329     if (serverName.getPort() >= 0) {
330       builder.setPort(serverName.getPort());
331     }
332     if (serverName.getStartcode() >= 0) {
333       builder.setStartCode(serverName.getStartcode());
334     }
335     return builder.build();
336   }
337 
338   /**
339    * Convert a protocol buffer ServerName to a ServerName
340    *
341    * @param proto the protocol buffer ServerName to convert
342    * @return the converted ServerName
343    */
344   public static ServerName toServerName(final HBaseProtos.ServerName proto) {
345     if (proto == null) return null;
346     String hostName = proto.getHostName();
347     long startCode = -1;
348     int port = -1;
349     if (proto.hasPort()) {
350       port = proto.getPort();
351     }
352     if (proto.hasStartCode()) {
353       startCode = proto.getStartCode();
354     }
355     return ServerName.valueOf(hostName, port, startCode);
356   }
357 
358   /**
359    * Get HTableDescriptor[] from GetTableDescriptorsResponse protobuf
360    *
361    * @param proto the GetTableDescriptorsResponse
362    * @return HTableDescriptor[]
363    */
364   public static HTableDescriptor[] getHTableDescriptorArray(GetTableDescriptorsResponse proto) {
365     if (proto == null) return null;
366 
367     HTableDescriptor[] ret = new HTableDescriptor[proto.getTableSchemaCount()];
368     for (int i = 0; i < proto.getTableSchemaCount(); ++i) {
369       ret[i] = HTableDescriptor.convert(proto.getTableSchema(i));
370     }
371     return ret;
372   }
373 
374   /**
375    * get the split keys in form "byte [][]" from a CreateTableRequest proto
376    *
377    * @param proto the CreateTableRequest
378    * @return the split keys
379    */
380   public static byte [][] getSplitKeysArray(final CreateTableRequest proto) {
381     byte [][] splitKeys = new byte[proto.getSplitKeysCount()][];
382     for (int i = 0; i < proto.getSplitKeysCount(); ++i) {
383       splitKeys[i] = proto.getSplitKeys(i).toByteArray();
384     }
385     return splitKeys;
386   }
387 
388   /**
389    * Convert a protobuf Durability into a client Durability
390    */
391   public static Durability toDurability(
392       final ClientProtos.MutationProto.Durability proto) {
393     switch(proto) {
394     case USE_DEFAULT:
395       return Durability.USE_DEFAULT;
396     case SKIP_WAL:
397       return Durability.SKIP_WAL;
398     case ASYNC_WAL:
399       return Durability.ASYNC_WAL;
400     case SYNC_WAL:
401       return Durability.SYNC_WAL;
402     case FSYNC_WAL:
403       return Durability.FSYNC_WAL;
404     default:
405       return Durability.USE_DEFAULT;
406     }
407   }
408 
409   /**
410    * Convert a client Durability into a protbuf Durability
411    */
412   public static ClientProtos.MutationProto.Durability toDurability(
413       final Durability d) {
414     switch(d) {
415     case USE_DEFAULT:
416       return ClientProtos.MutationProto.Durability.USE_DEFAULT;
417     case SKIP_WAL:
418       return ClientProtos.MutationProto.Durability.SKIP_WAL;
419     case ASYNC_WAL:
420       return ClientProtos.MutationProto.Durability.ASYNC_WAL;
421     case SYNC_WAL:
422       return ClientProtos.MutationProto.Durability.SYNC_WAL;
423     case FSYNC_WAL:
424       return ClientProtos.MutationProto.Durability.FSYNC_WAL;
425     default:
426       return ClientProtos.MutationProto.Durability.USE_DEFAULT;
427     }
428   }
429 
430   /**
431    * Convert a protocol buffer Get to a client Get
432    *
433    * @param proto the protocol buffer Get to convert
434    * @return the converted client Get
435    * @throws IOException
436    */
437   public static Get toGet(
438       final ClientProtos.Get proto) throws IOException {
439     if (proto == null) return null;
440     byte[] row = proto.getRow().toByteArray();
441     Get get = new Get(row);
442     if (proto.hasCacheBlocks()) {
443       get.setCacheBlocks(proto.getCacheBlocks());
444     }
445     if (proto.hasMaxVersions()) {
446       get.setMaxVersions(proto.getMaxVersions());
447     }
448     if (proto.hasStoreLimit()) {
449       get.setMaxResultsPerColumnFamily(proto.getStoreLimit());
450     }
451     if (proto.hasStoreOffset()) {
452       get.setRowOffsetPerColumnFamily(proto.getStoreOffset());
453     }
454     if (proto.hasTimeRange()) {
455       HBaseProtos.TimeRange timeRange = proto.getTimeRange();
456       long minStamp = 0;
457       long maxStamp = Long.MAX_VALUE;
458       if (timeRange.hasFrom()) {
459         minStamp = timeRange.getFrom();
460       }
461       if (timeRange.hasTo()) {
462         maxStamp = timeRange.getTo();
463       }
464       get.setTimeRange(minStamp, maxStamp);
465     }
466     if (proto.hasFilter()) {
467       FilterProtos.Filter filter = proto.getFilter();
468       get.setFilter(ProtobufUtil.toFilter(filter));
469     }
470     for (NameBytesPair attribute: proto.getAttributeList()) {
471       get.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
472     }
473     if (proto.getColumnCount() > 0) {
474       for (Column column: proto.getColumnList()) {
475         byte[] family = column.getFamily().toByteArray();
476         if (column.getQualifierCount() > 0) {
477           for (ByteString qualifier: column.getQualifierList()) {
478             get.addColumn(family, qualifier.toByteArray());
479           }
480         } else {
481           get.addFamily(family);
482         }
483       }
484     }
485     if (proto.hasExistenceOnly() && proto.getExistenceOnly()){
486       get.setCheckExistenceOnly(true);
487     }
488     if (proto.hasClosestRowBefore() && proto.getClosestRowBefore()){
489       get.setClosestRowBefore(true);
490     }
491     if (proto.hasConsistency()) {
492       get.setConsistency(toConsistency(proto.getConsistency()));
493     }
494     return get;
495   }
496 
497   public static Consistency toConsistency(ClientProtos.Consistency consistency) {
498     switch (consistency) {
499       case STRONG : return Consistency.STRONG;
500       case TIMELINE : return Consistency.TIMELINE;
501       default : return Consistency.STRONG;
502     }
503   }
504 
505   public static ClientProtos.Consistency toConsistency(Consistency consistency) {
506     switch (consistency) {
507       case STRONG : return ClientProtos.Consistency.STRONG;
508       case TIMELINE : return ClientProtos.Consistency.TIMELINE;
509       default : return ClientProtos.Consistency.STRONG;
510     }
511   }
512 
513   /**
514    * Convert a protocol buffer Mutate to a Put.
515    *
516    * @param proto The protocol buffer MutationProto to convert
517    * @return A client Put.
518    * @throws IOException
519    */
520   public static Put toPut(final MutationProto proto)
521   throws IOException {
522     return toPut(proto, null);
523   }
524 
525   /**
526    * Convert a protocol buffer Mutate to a Put.
527    *
528    * @param proto The protocol buffer MutationProto to convert
529    * @param cellScanner If non-null, the Cell data that goes with this proto.
530    * @return A client Put.
531    * @throws IOException
532    */
533   public static Put toPut(final MutationProto proto, final CellScanner cellScanner)
534   throws IOException {
535     // TODO: Server-side at least why do we convert back to the Client types?  Why not just pb it?
536     MutationType type = proto.getMutateType();
537     assert type == MutationType.PUT: type.name();
538     long timestamp = proto.hasTimestamp()? proto.getTimestamp(): HConstants.LATEST_TIMESTAMP;
539     Put put = null;
540     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
541     if (cellCount > 0) {
542       // The proto has metadata only and the data is separate to be found in the cellScanner.
543       if (cellScanner == null) {
544         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
545             toShortString(proto));
546       }
547       for (int i = 0; i < cellCount; i++) {
548         if (!cellScanner.advance()) {
549           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
550             " no cell returned: " + toShortString(proto));
551         }
552         Cell cell = cellScanner.current();
553         if (put == null) {
554           put = new Put(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp);
555         }
556         put.add(cell);
557       }
558     } else {
559       if (proto.hasRow()) {
560         put = new Put(proto.getRow().asReadOnlyByteBuffer(), timestamp);
561       } else {
562         throw new IllegalArgumentException("row cannot be null");
563       }
564       // The proto has the metadata and the data itself
565       for (ColumnValue column: proto.getColumnValueList()) {
566         byte[] family = column.getFamily().toByteArray();
567         for (QualifierValue qv: column.getQualifierValueList()) {
568           if (!qv.hasValue()) {
569             throw new DoNotRetryIOException(
570                 "Missing required field: qualifier value");
571           }
572           ByteBuffer qualifier =
573               qv.hasQualifier() ? qv.getQualifier().asReadOnlyByteBuffer() : null;
574           ByteBuffer value =
575               qv.hasValue() ? qv.getValue().asReadOnlyByteBuffer() : null;
576           long ts = timestamp;
577           if (qv.hasTimestamp()) {
578             ts = qv.getTimestamp();
579           }
580           byte[] tags;
581           if (qv.hasTags()) {
582             tags = qv.getTags().toByteArray();
583             Object[] array = Tag.asList(tags, 0, (short)tags.length).toArray();
584             Tag[] tagArray = new Tag[array.length];
585             for(int i = 0; i< array.length; i++) {
586               tagArray[i] = (Tag)array[i];
587             }
588             if(qv.hasDeleteType()) {
589               byte[] qual = qv.hasQualifier() ? qv.getQualifier().toByteArray() : null;
590               put.add(new KeyValue(proto.getRow().toByteArray(), family, qual, ts,
591                   fromDeleteType(qv.getDeleteType()), null, tags));
592             } else {
593               put.addImmutable(family, qualifier, ts, value, tagArray);
594             }
595           } else {
596             if(qv.hasDeleteType()) {
597               byte[] qual = qv.hasQualifier() ? qv.getQualifier().toByteArray() : null;
598               put.add(new KeyValue(proto.getRow().toByteArray(), family, qual, ts,
599                   fromDeleteType(qv.getDeleteType())));
600             } else{
601               put.addImmutable(family, qualifier, ts, value);
602             }
603           }
604         }
605       }
606     }
607     put.setDurability(toDurability(proto.getDurability()));
608     for (NameBytesPair attribute: proto.getAttributeList()) {
609       put.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
610     }
611     return put;
612   }
613 
614   /**
615    * Convert a protocol buffer Mutate to a Delete
616    *
617    * @param proto the protocol buffer Mutate to convert
618    * @return the converted client Delete
619    * @throws IOException
620    */
621   public static Delete toDelete(final MutationProto proto)
622   throws IOException {
623     return toDelete(proto, null);
624   }
625 
626   /**
627    * Convert a protocol buffer Mutate to a Delete
628    *
629    * @param proto the protocol buffer Mutate to convert
630    * @param cellScanner if non-null, the data that goes with this delete.
631    * @return the converted client Delete
632    * @throws IOException
633    */
634   public static Delete toDelete(final MutationProto proto, final CellScanner cellScanner)
635   throws IOException {
636     MutationType type = proto.getMutateType();
637     assert type == MutationType.DELETE : type.name();
638     byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null;
639     long timestamp = HConstants.LATEST_TIMESTAMP;
640     if (proto.hasTimestamp()) {
641       timestamp = proto.getTimestamp();
642     }
643     Delete delete = null;
644     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
645     if (cellCount > 0) {
646       // The proto has metadata only and the data is separate to be found in the cellScanner.
647       if (cellScanner == null) {
648         // TextFormat should be fine for a Delete since it carries no data, just coordinates.
649         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
650           TextFormat.shortDebugString(proto));
651       }
652       for (int i = 0; i < cellCount; i++) {
653         if (!cellScanner.advance()) {
654           // TextFormat should be fine for a Delete since it carries no data, just coordinates.
655           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
656             " no cell returned: " + TextFormat.shortDebugString(proto));
657         }
658         Cell cell = cellScanner.current();
659         if (delete == null) {
660           delete =
661             new Delete(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp);
662         }
663         delete.addDeleteMarker(cell);
664       }
665     } else {
666       delete = new Delete(row, timestamp);
667       for (ColumnValue column: proto.getColumnValueList()) {
668         byte[] family = column.getFamily().toByteArray();
669         for (QualifierValue qv: column.getQualifierValueList()) {
670           DeleteType deleteType = qv.getDeleteType();
671           byte[] qualifier = null;
672           if (qv.hasQualifier()) {
673             qualifier = qv.getQualifier().toByteArray();
674           }
675           long ts = HConstants.LATEST_TIMESTAMP;
676           if (qv.hasTimestamp()) {
677             ts = qv.getTimestamp();
678           }
679           if (deleteType == DeleteType.DELETE_ONE_VERSION) {
680             delete.deleteColumn(family, qualifier, ts);
681           } else if (deleteType == DeleteType.DELETE_MULTIPLE_VERSIONS) {
682             delete.deleteColumns(family, qualifier, ts);
683           } else if (deleteType == DeleteType.DELETE_FAMILY_VERSION) {
684             delete.deleteFamilyVersion(family, ts);
685           } else {
686             delete.deleteFamily(family, ts);
687           }
688         }
689       }
690     }
691     delete.setDurability(toDurability(proto.getDurability()));
692     for (NameBytesPair attribute: proto.getAttributeList()) {
693       delete.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
694     }
695     return delete;
696   }
697 
698   /**
699    * Convert a protocol buffer Mutate to an Append
700    * @param cellScanner
701    * @param proto the protocol buffer Mutate to convert
702    * @return the converted client Append
703    * @throws IOException
704    */
705   public static Append toAppend(final MutationProto proto, final CellScanner cellScanner)
706   throws IOException {
707     MutationType type = proto.getMutateType();
708     assert type == MutationType.APPEND : type.name();
709     byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null;
710     Append append = null;
711     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
712     if (cellCount > 0) {
713       // The proto has metadata only and the data is separate to be found in the cellScanner.
714       if (cellScanner == null) {
715         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
716           toShortString(proto));
717       }
718       for (int i = 0; i < cellCount; i++) {
719         if (!cellScanner.advance()) {
720           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
721             " no cell returned: " + toShortString(proto));
722         }
723         Cell cell = cellScanner.current();
724         if (append == null) {
725           append = new Append(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
726         }
727         append.add(cell);
728       }
729     } else {
730       append = new Append(row);
731       for (ColumnValue column: proto.getColumnValueList()) {
732         byte[] family = column.getFamily().toByteArray();
733         for (QualifierValue qv: column.getQualifierValueList()) {
734           byte[] qualifier = qv.getQualifier().toByteArray();
735           if (!qv.hasValue()) {
736             throw new DoNotRetryIOException(
737               "Missing required field: qualifier value");
738           }
739           byte[] value = qv.getValue().toByteArray();
740           byte[] tags = null;
741           if (qv.hasTags()) {
742             tags = qv.getTags().toByteArray();
743           }
744           append.add(CellUtil.createCell(row, family, qualifier, qv.getTimestamp(),
745               KeyValue.Type.Put, value, tags));
746         }
747       }
748     }
749     append.setDurability(toDurability(proto.getDurability()));
750     for (NameBytesPair attribute: proto.getAttributeList()) {
751       append.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
752     }
753     return append;
754   }
755 
756   /**
757    * Convert a MutateRequest to Mutation
758    *
759    * @param proto the protocol buffer Mutate to convert
760    * @return the converted Mutation
761    * @throws IOException
762    */
763   public static Mutation toMutation(final MutationProto proto) throws IOException {
764     MutationType type = proto.getMutateType();
765     if (type == MutationType.APPEND) {
766       return toAppend(proto, null);
767     }
768     if (type == MutationType.DELETE) {
769       return toDelete(proto, null);
770     }
771     if (type == MutationType.PUT) {
772       return toPut(proto, null);
773     }
774     throw new IOException("Unknown mutation type " + type);
775   }
776 
777   /**
778    * Convert a protocol buffer Mutate to an Increment
779    *
780    * @param proto the protocol buffer Mutate to convert
781    * @return the converted client Increment
782    * @throws IOException
783    */
784   public static Increment toIncrement(final MutationProto proto, final CellScanner cellScanner)
785   throws IOException {
786     MutationType type = proto.getMutateType();
787     assert type == MutationType.INCREMENT : type.name();
788     byte [] row = proto.hasRow()? proto.getRow().toByteArray(): null;
789     Increment increment = null;
790     int cellCount = proto.hasAssociatedCellCount()? proto.getAssociatedCellCount(): 0;
791     if (cellCount > 0) {
792       // The proto has metadata only and the data is separate to be found in the cellScanner.
793       if (cellScanner == null) {
794         throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " +
795           TextFormat.shortDebugString(proto));
796       }
797       for (int i = 0; i < cellCount; i++) {
798         if (!cellScanner.advance()) {
799           throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i +
800             " no cell returned: " + TextFormat.shortDebugString(proto));
801         }
802         Cell cell = cellScanner.current();
803         if (increment == null) {
804           increment = new Increment(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength());
805         }
806         increment.add(cell);
807       }
808     } else {
809       increment = new Increment(row);
810       for (ColumnValue column: proto.getColumnValueList()) {
811         byte[] family = column.getFamily().toByteArray();
812         for (QualifierValue qv: column.getQualifierValueList()) {
813           byte[] qualifier = qv.getQualifier().toByteArray();
814           if (!qv.hasValue()) {
815             throw new DoNotRetryIOException("Missing required field: qualifier value");
816           }
817           byte[] value = qv.getValue().toByteArray();
818           byte[] tags = null;
819           if (qv.hasTags()) {
820             tags = qv.getTags().toByteArray();
821           }
822           increment.add(CellUtil.createCell(row, family, qualifier, qv.getTimestamp(),
823               KeyValue.Type.Put, value, tags));
824         }
825       }
826     }
827     if (proto.hasTimeRange()) {
828       HBaseProtos.TimeRange timeRange = proto.getTimeRange();
829       long minStamp = 0;
830       long maxStamp = Long.MAX_VALUE;
831       if (timeRange.hasFrom()) {
832         minStamp = timeRange.getFrom();
833       }
834       if (timeRange.hasTo()) {
835         maxStamp = timeRange.getTo();
836       }
837       increment.setTimeRange(minStamp, maxStamp);
838     }
839     increment.setDurability(toDurability(proto.getDurability()));
840     for (NameBytesPair attribute : proto.getAttributeList()) {
841       increment.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
842     }
843     return increment;
844   }
845 
846   /**
847    * Convert a client Scan to a protocol buffer Scan
848    *
849    * @param scan the client Scan to convert
850    * @return the converted protocol buffer Scan
851    * @throws IOException
852    */
853   public static ClientProtos.Scan toScan(
854       final Scan scan) throws IOException {
855     ClientProtos.Scan.Builder scanBuilder =
856       ClientProtos.Scan.newBuilder();
857     scanBuilder.setCacheBlocks(scan.getCacheBlocks());
858     if (scan.getBatch() > 0) {
859       scanBuilder.setBatchSize(scan.getBatch());
860     }
861     if (scan.getMaxResultSize() > 0) {
862       scanBuilder.setMaxResultSize(scan.getMaxResultSize());
863     }
864     if (scan.isSmall()) {
865       scanBuilder.setSmall(scan.isSmall());
866     }
867     Boolean loadColumnFamiliesOnDemand = scan.getLoadColumnFamiliesOnDemandValue();
868     if (loadColumnFamiliesOnDemand != null) {
869       scanBuilder.setLoadColumnFamiliesOnDemand(loadColumnFamiliesOnDemand.booleanValue());
870     }
871     scanBuilder.setMaxVersions(scan.getMaxVersions());
872     TimeRange timeRange = scan.getTimeRange();
873     if (!timeRange.isAllTime()) {
874       HBaseProtos.TimeRange.Builder timeRangeBuilder =
875         HBaseProtos.TimeRange.newBuilder();
876       timeRangeBuilder.setFrom(timeRange.getMin());
877       timeRangeBuilder.setTo(timeRange.getMax());
878       scanBuilder.setTimeRange(timeRangeBuilder.build());
879     }
880     Map<String, byte[]> attributes = scan.getAttributesMap();
881     if (!attributes.isEmpty()) {
882       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
883       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
884         attributeBuilder.setName(attribute.getKey());
885         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
886         scanBuilder.addAttribute(attributeBuilder.build());
887       }
888     }
889     byte[] startRow = scan.getStartRow();
890     if (startRow != null && startRow.length > 0) {
891       scanBuilder.setStartRow(ByteStringer.wrap(startRow));
892     }
893     byte[] stopRow = scan.getStopRow();
894     if (stopRow != null && stopRow.length > 0) {
895       scanBuilder.setStopRow(ByteStringer.wrap(stopRow));
896     }
897     if (scan.hasFilter()) {
898       scanBuilder.setFilter(ProtobufUtil.toFilter(scan.getFilter()));
899     }
900     if (scan.hasFamilies()) {
901       Column.Builder columnBuilder = Column.newBuilder();
902       for (Map.Entry<byte[],NavigableSet<byte []>>
903           family: scan.getFamilyMap().entrySet()) {
904         columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
905         NavigableSet<byte []> qualifiers = family.getValue();
906         columnBuilder.clearQualifier();
907         if (qualifiers != null && qualifiers.size() > 0) {
908           for (byte [] qualifier: qualifiers) {
909             columnBuilder.addQualifier(ByteStringer.wrap(qualifier));
910           }
911         }
912         scanBuilder.addColumn(columnBuilder.build());
913       }
914     }
915     if (scan.getMaxResultsPerColumnFamily() >= 0) {
916       scanBuilder.setStoreLimit(scan.getMaxResultsPerColumnFamily());
917     }
918     if (scan.getRowOffsetPerColumnFamily() > 0) {
919       scanBuilder.setStoreOffset(scan.getRowOffsetPerColumnFamily());
920     }
921     if (scan.isReversed()) {
922       scanBuilder.setReversed(scan.isReversed());
923     }
924     if (scan.getConsistency() == Consistency.TIMELINE) {
925       scanBuilder.setConsistency(toConsistency(scan.getConsistency()));
926     }
927     if (scan.getCaching() > 0) {
928       scanBuilder.setCaching(scan.getCaching());
929     }
930     return scanBuilder.build();
931   }
932 
933   /**
934    * Convert a protocol buffer Scan to a client Scan
935    *
936    * @param proto the protocol buffer Scan to convert
937    * @return the converted client Scan
938    * @throws IOException
939    */
940   public static Scan toScan(
941       final ClientProtos.Scan proto) throws IOException {
942     byte [] startRow = HConstants.EMPTY_START_ROW;
943     byte [] stopRow  = HConstants.EMPTY_END_ROW;
944     if (proto.hasStartRow()) {
945       startRow = proto.getStartRow().toByteArray();
946     }
947     if (proto.hasStopRow()) {
948       stopRow = proto.getStopRow().toByteArray();
949     }
950     Scan scan = new Scan(startRow, stopRow);
951     if (proto.hasCacheBlocks()) {
952       scan.setCacheBlocks(proto.getCacheBlocks());
953     }
954     if (proto.hasMaxVersions()) {
955       scan.setMaxVersions(proto.getMaxVersions());
956     }
957     if (proto.hasStoreLimit()) {
958       scan.setMaxResultsPerColumnFamily(proto.getStoreLimit());
959     }
960     if (proto.hasStoreOffset()) {
961       scan.setRowOffsetPerColumnFamily(proto.getStoreOffset());
962     }
963     if (proto.hasLoadColumnFamiliesOnDemand()) {
964       scan.setLoadColumnFamiliesOnDemand(proto.getLoadColumnFamiliesOnDemand());
965     }
966     if (proto.hasTimeRange()) {
967       HBaseProtos.TimeRange timeRange = proto.getTimeRange();
968       long minStamp = 0;
969       long maxStamp = Long.MAX_VALUE;
970       if (timeRange.hasFrom()) {
971         minStamp = timeRange.getFrom();
972       }
973       if (timeRange.hasTo()) {
974         maxStamp = timeRange.getTo();
975       }
976       scan.setTimeRange(minStamp, maxStamp);
977     }
978     if (proto.hasFilter()) {
979       FilterProtos.Filter filter = proto.getFilter();
980       scan.setFilter(ProtobufUtil.toFilter(filter));
981     }
982     if (proto.hasBatchSize()) {
983       scan.setBatch(proto.getBatchSize());
984     }
985     if (proto.hasMaxResultSize()) {
986       scan.setMaxResultSize(proto.getMaxResultSize());
987     }
988     if (proto.hasSmall()) {
989       scan.setSmall(proto.getSmall());
990     }
991     for (NameBytesPair attribute: proto.getAttributeList()) {
992       scan.setAttribute(attribute.getName(), attribute.getValue().toByteArray());
993     }
994     if (proto.getColumnCount() > 0) {
995       for (Column column: proto.getColumnList()) {
996         byte[] family = column.getFamily().toByteArray();
997         if (column.getQualifierCount() > 0) {
998           for (ByteString qualifier: column.getQualifierList()) {
999             scan.addColumn(family, qualifier.toByteArray());
1000           }
1001         } else {
1002           scan.addFamily(family);
1003         }
1004       }
1005     }
1006     if (proto.hasReversed()) {
1007       scan.setReversed(proto.getReversed());
1008     }
1009     if (proto.hasConsistency()) {
1010       scan.setConsistency(toConsistency(proto.getConsistency()));
1011     }
1012     if (proto.hasCaching()) {
1013       scan.setCaching(proto.getCaching());
1014     }
1015     return scan;
1016   }
1017 
1018   /**
1019    * Create a protocol buffer Get based on a client Get.
1020    *
1021    * @param get the client Get
1022    * @return a protocol buffer Get
1023    * @throws IOException
1024    */
1025   public static ClientProtos.Get toGet(
1026       final Get get) throws IOException {
1027     ClientProtos.Get.Builder builder =
1028       ClientProtos.Get.newBuilder();
1029     builder.setRow(ByteStringer.wrap(get.getRow()));
1030     builder.setCacheBlocks(get.getCacheBlocks());
1031     builder.setMaxVersions(get.getMaxVersions());
1032     if (get.getFilter() != null) {
1033       builder.setFilter(ProtobufUtil.toFilter(get.getFilter()));
1034     }
1035     TimeRange timeRange = get.getTimeRange();
1036     if (!timeRange.isAllTime()) {
1037       HBaseProtos.TimeRange.Builder timeRangeBuilder =
1038         HBaseProtos.TimeRange.newBuilder();
1039       timeRangeBuilder.setFrom(timeRange.getMin());
1040       timeRangeBuilder.setTo(timeRange.getMax());
1041       builder.setTimeRange(timeRangeBuilder.build());
1042     }
1043     Map<String, byte[]> attributes = get.getAttributesMap();
1044     if (!attributes.isEmpty()) {
1045       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1046       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
1047         attributeBuilder.setName(attribute.getKey());
1048         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1049         builder.addAttribute(attributeBuilder.build());
1050       }
1051     }
1052     if (get.hasFamilies()) {
1053       Column.Builder columnBuilder = Column.newBuilder();
1054       Map<byte[], NavigableSet<byte[]>> families = get.getFamilyMap();
1055       for (Map.Entry<byte[], NavigableSet<byte[]>> family: families.entrySet()) {
1056         NavigableSet<byte[]> qualifiers = family.getValue();
1057         columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1058         columnBuilder.clearQualifier();
1059         if (qualifiers != null && qualifiers.size() > 0) {
1060           for (byte[] qualifier: qualifiers) {
1061             columnBuilder.addQualifier(ByteStringer.wrap(qualifier));
1062           }
1063         }
1064         builder.addColumn(columnBuilder.build());
1065       }
1066     }
1067     if (get.getMaxResultsPerColumnFamily() >= 0) {
1068       builder.setStoreLimit(get.getMaxResultsPerColumnFamily());
1069     }
1070     if (get.getRowOffsetPerColumnFamily() > 0) {
1071       builder.setStoreOffset(get.getRowOffsetPerColumnFamily());
1072     }
1073     if (get.isCheckExistenceOnly()){
1074       builder.setExistenceOnly(true);
1075     }
1076     if (get.isClosestRowBefore()){
1077       builder.setClosestRowBefore(true);
1078     }
1079     if (get.getConsistency() != null && get.getConsistency() != Consistency.STRONG) {
1080       builder.setConsistency(toConsistency(get.getConsistency()));
1081     }
1082 
1083     return builder.build();
1084   }
1085 
1086   /**
1087    * Convert a client Increment to a protobuf Mutate.
1088    *
1089    * @param increment
1090    * @return the converted mutate
1091    */
1092   public static MutationProto toMutation(
1093     final Increment increment, final MutationProto.Builder builder, long nonce) {
1094     builder.setRow(ByteStringer.wrap(increment.getRow()));
1095     builder.setMutateType(MutationType.INCREMENT);
1096     builder.setDurability(toDurability(increment.getDurability()));
1097     if (nonce != HConstants.NO_NONCE) {
1098       builder.setNonce(nonce);
1099     }
1100     TimeRange timeRange = increment.getTimeRange();
1101     if (!timeRange.isAllTime()) {
1102       HBaseProtos.TimeRange.Builder timeRangeBuilder =
1103         HBaseProtos.TimeRange.newBuilder();
1104       timeRangeBuilder.setFrom(timeRange.getMin());
1105       timeRangeBuilder.setTo(timeRange.getMax());
1106       builder.setTimeRange(timeRangeBuilder.build());
1107     }
1108     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
1109     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
1110     for (Map.Entry<byte[], List<Cell>> family: increment.getFamilyCellMap().entrySet()) {
1111       columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1112       columnBuilder.clearQualifierValue();
1113       List<Cell> values = family.getValue();
1114       if (values != null && values.size() > 0) {
1115         for (Cell cell: values) {
1116           valueBuilder.clear();
1117           valueBuilder.setQualifier(ByteStringer.wrap(
1118               cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
1119           valueBuilder.setValue(ByteStringer.wrap(
1120               cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
1121           if (cell.getTagsLength() > 0) {
1122             valueBuilder.setTags(ByteStringer.wrap(cell.getTagsArray(),
1123                 cell.getTagsOffset(), cell.getTagsLength()));
1124           }
1125           columnBuilder.addQualifierValue(valueBuilder.build());
1126         }
1127       }
1128       builder.addColumnValue(columnBuilder.build());
1129     }
1130     Map<String, byte[]> attributes = increment.getAttributesMap();
1131     if (!attributes.isEmpty()) {
1132       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1133       for (Map.Entry<String, byte[]> attribute : attributes.entrySet()) {
1134         attributeBuilder.setName(attribute.getKey());
1135         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1136         builder.addAttribute(attributeBuilder.build());
1137       }
1138     }
1139     return builder.build();
1140   }
1141 
1142   public static MutationProto toMutation(final MutationType type, final Mutation mutation)
1143     throws IOException {
1144     return toMutation(type, mutation, HConstants.NO_NONCE);
1145   }
1146 
1147   /**
1148    * Create a protocol buffer Mutate based on a client Mutation
1149    *
1150    * @param type
1151    * @param mutation
1152    * @return a protobuf'd Mutation
1153    * @throws IOException
1154    */
1155   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1156     final long nonce) throws IOException {
1157     return toMutation(type, mutation, MutationProto.newBuilder(), nonce);
1158   }
1159 
1160   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1161       MutationProto.Builder builder) throws IOException {
1162     return toMutation(type, mutation, builder, HConstants.NO_NONCE);
1163   }
1164 
1165   @SuppressWarnings("deprecation")
1166   public static MutationProto toMutation(final MutationType type, final Mutation mutation,
1167       MutationProto.Builder builder, long nonce)
1168   throws IOException {
1169     builder = getMutationBuilderAndSetCommonFields(type, mutation, builder);
1170     if (nonce != HConstants.NO_NONCE) {
1171       builder.setNonce(nonce);
1172     }
1173     ColumnValue.Builder columnBuilder = ColumnValue.newBuilder();
1174     QualifierValue.Builder valueBuilder = QualifierValue.newBuilder();
1175     for (Map.Entry<byte[],List<Cell>> family: mutation.getFamilyCellMap().entrySet()) {
1176       columnBuilder.clear();
1177       columnBuilder.setFamily(ByteStringer.wrap(family.getKey()));
1178       for (Cell cell: family.getValue()) {
1179         valueBuilder.clear();
1180         valueBuilder.setQualifier(ByteStringer.wrap(
1181             cell.getQualifierArray(), cell.getQualifierOffset(), cell.getQualifierLength()));
1182         valueBuilder.setValue(ByteStringer.wrap(
1183             cell.getValueArray(), cell.getValueOffset(), cell.getValueLength()));
1184         valueBuilder.setTimestamp(cell.getTimestamp());
1185         if(cell.getTagsLength() > 0) {
1186           valueBuilder.setTags(ByteStringer.wrap(cell.getTagsArray(), cell.getTagsOffset(),
1187               cell.getTagsLength()));
1188         }
1189         if (type == MutationType.DELETE || (type == MutationType.PUT && CellUtil.isDelete(cell))) {
1190           KeyValue.Type keyValueType = KeyValue.Type.codeToType(cell.getTypeByte());
1191           valueBuilder.setDeleteType(toDeleteType(keyValueType));
1192         }
1193         columnBuilder.addQualifierValue(valueBuilder.build());
1194       }
1195       builder.addColumnValue(columnBuilder.build());
1196     }
1197     return builder.build();
1198   }
1199 
1200   /**
1201    * Create a protocol buffer MutationProto based on a client Mutation. Does NOT include data.
1202    * Understanding is that the Cell will be transported other than via protobuf.
1203    * @param type
1204    * @param mutation
1205    * @param builder
1206    * @return a protobuf'd Mutation
1207    * @throws IOException
1208    */
1209   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation,
1210       final MutationProto.Builder builder)  throws IOException {
1211     return toMutationNoData(type, mutation, builder, HConstants.NO_NONCE);
1212   }
1213 
1214   /**
1215    * Create a protocol buffer MutationProto based on a client Mutation.  Does NOT include data.
1216    * Understanding is that the Cell will be transported other than via protobuf.
1217    * @param type
1218    * @param mutation
1219    * @return a protobuf'd Mutation
1220    * @throws IOException
1221    */
1222   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation)
1223   throws IOException {
1224     MutationProto.Builder builder =  MutationProto.newBuilder();
1225     return toMutationNoData(type, mutation, builder);
1226   }
1227 
1228   public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation,
1229       final MutationProto.Builder builder, long nonce) throws IOException {
1230     getMutationBuilderAndSetCommonFields(type, mutation, builder);
1231     builder.setAssociatedCellCount(mutation.size());
1232     if (nonce != HConstants.NO_NONCE) {
1233       builder.setNonce(nonce);
1234     }
1235     return builder.build();
1236   }
1237 
1238   /**
1239    * Code shared by {@link #toMutation(MutationType, Mutation)} and
1240    * {@link #toMutationNoData(MutationType, Mutation)}
1241    * @param type
1242    * @param mutation
1243    * @return A partly-filled out protobuf'd Mutation.
1244    */
1245   private static MutationProto.Builder getMutationBuilderAndSetCommonFields(final MutationType type,
1246       final Mutation mutation, MutationProto.Builder builder) {
1247     builder.setRow(ByteStringer.wrap(mutation.getRow()));
1248     builder.setMutateType(type);
1249     builder.setDurability(toDurability(mutation.getDurability()));
1250     builder.setTimestamp(mutation.getTimeStamp());
1251     Map<String, byte[]> attributes = mutation.getAttributesMap();
1252     if (!attributes.isEmpty()) {
1253       NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder();
1254       for (Map.Entry<String, byte[]> attribute: attributes.entrySet()) {
1255         attributeBuilder.setName(attribute.getKey());
1256         attributeBuilder.setValue(ByteStringer.wrap(attribute.getValue()));
1257         builder.addAttribute(attributeBuilder.build());
1258       }
1259     }
1260     return builder;
1261   }
1262 
1263   /**
1264    * Convert a client Result to a protocol buffer Result
1265    *
1266    * @param result the client Result to convert
1267    * @return the converted protocol buffer Result
1268    */
1269   public static ClientProtos.Result toResult(final Result result) {
1270     if (result.getExists() != null) {
1271       return toResult(result.getExists(), result.isStale());
1272     }
1273 
1274     Cell[] cells = result.rawCells();
1275     if (cells == null || cells.length == 0) {
1276       return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB;
1277     }
1278 
1279     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
1280     for (Cell c : cells) {
1281       builder.addCell(toCell(c));
1282     }
1283 
1284     builder.setStale(result.isStale());
1285 
1286     return builder.build();
1287   }
1288 
1289   /**
1290    * Convert a client Result to a protocol buffer Result
1291    *
1292    * @param existence the client existence to send
1293    * @return the converted protocol buffer Result
1294    */
1295   public static ClientProtos.Result toResult(final boolean existence, boolean stale) {
1296     if (stale){
1297       return existence ? EMPTY_RESULT_PB_EXISTS_TRUE_STALE : EMPTY_RESULT_PB_EXISTS_FALSE_STALE;
1298     } else {
1299       return existence ? EMPTY_RESULT_PB_EXISTS_TRUE : EMPTY_RESULT_PB_EXISTS_FALSE;
1300     }
1301   }
1302 
1303   /**
1304    * Convert a client Result to a protocol buffer Result.
1305    * The pb Result does not include the Cell data.  That is for transport otherwise.
1306    *
1307    * @param result the client Result to convert
1308    * @return the converted protocol buffer Result
1309    */
1310   public static ClientProtos.Result toResultNoData(final Result result) {
1311     if (result.getExists() != null) return toResult(result.getExists(), result.isStale());
1312     int size = result.size();
1313     if (size == 0) return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB;
1314     ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder();
1315     builder.setAssociatedCellCount(size);
1316     builder.setStale(result.isStale());
1317     return builder.build();
1318   }
1319 
1320   /**
1321    * Convert a protocol buffer Result to a client Result
1322    *
1323    * @param proto the protocol buffer Result to convert
1324    * @return the converted client Result
1325    */
1326   public static Result toResult(final ClientProtos.Result proto) {
1327     if (proto.hasExists()) {
1328       if (proto.getStale()) {
1329         return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE :EMPTY_RESULT_EXISTS_FALSE_STALE;
1330       }
1331       return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE;
1332     }
1333 
1334     List<CellProtos.Cell> values = proto.getCellList();
1335     if (values.isEmpty()){
1336       return proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT;
1337     }
1338 
1339     List<Cell> cells = new ArrayList<Cell>(values.size());
1340     for (CellProtos.Cell c : values) {
1341       cells.add(toCell(c));
1342     }
1343     return Result.create(cells, null, proto.getStale());
1344   }
1345 
1346   /**
1347    * Convert a protocol buffer Result to a client Result
1348    *
1349    * @param proto the protocol buffer Result to convert
1350    * @param scanner Optional cell scanner.
1351    * @return the converted client Result
1352    * @throws IOException
1353    */
1354   public static Result toResult(final ClientProtos.Result proto, final CellScanner scanner)
1355   throws IOException {
1356     List<CellProtos.Cell> values = proto.getCellList();
1357 
1358     if (proto.hasExists()) {
1359       if ((values != null && !values.isEmpty()) ||
1360           (proto.hasAssociatedCellCount() && proto.getAssociatedCellCount() > 0)) {
1361         throw new IllegalArgumentException("bad proto: exists with cells is no allowed " + proto);
1362       }
1363       if (proto.getStale()) {
1364         return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE :EMPTY_RESULT_EXISTS_FALSE_STALE;
1365       }
1366       return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE;
1367     }
1368 
1369     // TODO: Unit test that has some Cells in scanner and some in the proto.
1370     List<Cell> cells = null;
1371     if (proto.hasAssociatedCellCount()) {
1372       int count = proto.getAssociatedCellCount();
1373       cells = new ArrayList<Cell>(count + values.size());
1374       for (int i = 0; i < count; i++) {
1375         if (!scanner.advance()) throw new IOException("Failed get " + i + " of " + count);
1376         cells.add(scanner.current());
1377       }
1378     }
1379 
1380     if (!values.isEmpty()){
1381       if (cells == null) cells = new ArrayList<Cell>(values.size());
1382       for (CellProtos.Cell c: values) {
1383         cells.add(toCell(c));
1384       }
1385     }
1386 
1387     return (cells == null || cells.isEmpty())
1388         ? (proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT)
1389         : Result.create(cells, null, proto.getStale());
1390   }
1391 
1392 
1393   /**
1394    * Convert a ByteArrayComparable to a protocol buffer Comparator
1395    *
1396    * @param comparator the ByteArrayComparable to convert
1397    * @return the converted protocol buffer Comparator
1398    */
1399   public static ComparatorProtos.Comparator toComparator(ByteArrayComparable comparator) {
1400     ComparatorProtos.Comparator.Builder builder = ComparatorProtos.Comparator.newBuilder();
1401     builder.setName(comparator.getClass().getName());
1402     builder.setSerializedComparator(ByteStringer.wrap(comparator.toByteArray()));
1403     return builder.build();
1404   }
1405 
1406   /**
1407    * Convert a protocol buffer Comparator to a ByteArrayComparable
1408    *
1409    * @param proto the protocol buffer Comparator to convert
1410    * @return the converted ByteArrayComparable
1411    */
1412   @SuppressWarnings("unchecked")
1413   public static ByteArrayComparable toComparator(ComparatorProtos.Comparator proto)
1414   throws IOException {
1415     String type = proto.getName();
1416     String funcName = "parseFrom";
1417     byte [] value = proto.getSerializedComparator().toByteArray();
1418     try {
1419       Class<? extends ByteArrayComparable> c =
1420         (Class<? extends ByteArrayComparable>)Class.forName(type, true, CLASS_LOADER);
1421       Method parseFrom = c.getMethod(funcName, byte[].class);
1422       if (parseFrom == null) {
1423         throw new IOException("Unable to locate function: " + funcName + " in type: " + type);
1424       }
1425       return (ByteArrayComparable)parseFrom.invoke(null, value);
1426     } catch (Exception e) {
1427       throw new IOException(e);
1428     }
1429   }
1430 
1431   /**
1432    * Convert a protocol buffer Filter to a client Filter
1433    *
1434    * @param proto the protocol buffer Filter to convert
1435    * @return the converted Filter
1436    */
1437   @SuppressWarnings("unchecked")
1438   public static Filter toFilter(FilterProtos.Filter proto) throws IOException {
1439     String type = proto.getName();
1440     final byte [] value = proto.getSerializedFilter().toByteArray();
1441     String funcName = "parseFrom";
1442     try {
1443       Class<? extends Filter> c =
1444         (Class<? extends Filter>)Class.forName(type, true, CLASS_LOADER);
1445       Method parseFrom = c.getMethod(funcName, byte[].class);
1446       if (parseFrom == null) {
1447         throw new IOException("Unable to locate function: " + funcName + " in type: " + type);
1448       }
1449       return (Filter)parseFrom.invoke(c, value);
1450     } catch (Exception e) {
1451       // Either we couldn't instantiate the method object, or "parseFrom" failed.
1452       // In either case, let's not retry.
1453       throw new DoNotRetryIOException(e);
1454     }
1455   }
1456 
1457   /**
1458    * Convert a client Filter to a protocol buffer Filter
1459    *
1460    * @param filter the Filter to convert
1461    * @return the converted protocol buffer Filter
1462    */
1463   public static FilterProtos.Filter toFilter(Filter filter) throws IOException {
1464     FilterProtos.Filter.Builder builder = FilterProtos.Filter.newBuilder();
1465     builder.setName(filter.getClass().getName());
1466     builder.setSerializedFilter(ByteStringer.wrap(filter.toByteArray()));
1467     return builder.build();
1468   }
1469 
1470   /**
1471    * Convert a delete KeyValue type to protocol buffer DeleteType.
1472    *
1473    * @param type
1474    * @return protocol buffer DeleteType
1475    * @throws IOException
1476    */
1477   public static DeleteType toDeleteType(
1478       KeyValue.Type type) throws IOException {
1479     switch (type) {
1480     case Delete:
1481       return DeleteType.DELETE_ONE_VERSION;
1482     case DeleteColumn:
1483       return DeleteType.DELETE_MULTIPLE_VERSIONS;
1484     case DeleteFamily:
1485       return DeleteType.DELETE_FAMILY;
1486     case DeleteFamilyVersion:
1487       return DeleteType.DELETE_FAMILY_VERSION;
1488     default:
1489         throw new IOException("Unknown delete type: " + type);
1490     }
1491   }
1492 
1493   /**
1494    * Convert a protocol buffer DeleteType to delete KeyValue type.
1495    *
1496    * @param type The DeleteType
1497    * @return The type.
1498    * @throws IOException
1499    */
1500   public static KeyValue.Type fromDeleteType(
1501       DeleteType type) throws IOException {
1502     switch (type) {
1503     case DELETE_ONE_VERSION:
1504       return KeyValue.Type.Delete;
1505     case DELETE_MULTIPLE_VERSIONS:
1506       return KeyValue.Type.DeleteColumn;
1507     case DELETE_FAMILY:
1508       return KeyValue.Type.DeleteFamily;
1509     case DELETE_FAMILY_VERSION:
1510       return KeyValue.Type.DeleteFamilyVersion;
1511     default:
1512       throw new IOException("Unknown delete type: " + type);
1513     }
1514   }
1515 
1516   /**
1517    * Convert a stringified protocol buffer exception Parameter to a Java Exception
1518    *
1519    * @param parameter the protocol buffer Parameter to convert
1520    * @return the converted Exception
1521    * @throws IOException if failed to deserialize the parameter
1522    */
1523   @SuppressWarnings("unchecked")
1524   public static Throwable toException(final NameBytesPair parameter) throws IOException {
1525     if (parameter == null || !parameter.hasValue()) return null;
1526     String desc = parameter.getValue().toStringUtf8();
1527     String type = parameter.getName();
1528     try {
1529       Class<? extends Throwable> c =
1530         (Class<? extends Throwable>)Class.forName(type, true, CLASS_LOADER);
1531       Constructor<? extends Throwable> cn = null;
1532       try {
1533         cn = c.getDeclaredConstructor(String.class);
1534         return cn.newInstance(desc);
1535       } catch (NoSuchMethodException e) {
1536         // Could be a raw RemoteException. See HBASE-8987.
1537         cn = c.getDeclaredConstructor(String.class, String.class);
1538         return cn.newInstance(type, desc);
1539       }
1540     } catch (Exception e) {
1541       throw new IOException(e);
1542     }
1543   }
1544 
1545 // Start helpers for Client
1546 
1547   /**
1548    * A helper to get a row of the closet one before using client protocol.
1549    *
1550    * @param client
1551    * @param regionName
1552    * @param row
1553    * @param family
1554    * @return the row or the closestRowBefore if it doesn't exist
1555    * @throws IOException
1556    * @deprecated since 0.99 - use reversed scanner instead.
1557    */
1558   @Deprecated
1559   public static Result getRowOrBefore(final ClientService.BlockingInterface client,
1560       final byte[] regionName, final byte[] row,
1561       final byte[] family) throws IOException {
1562     GetRequest request =
1563       RequestConverter.buildGetRowOrBeforeRequest(
1564         regionName, row, family);
1565     try {
1566       GetResponse response = client.get(null, request);
1567       if (!response.hasResult()) return null;
1568       return toResult(response.getResult());
1569     } catch (ServiceException se) {
1570       throw getRemoteException(se);
1571     }
1572   }
1573 
1574   /**
1575    * A helper to bulk load a list of HFiles using client protocol.
1576    *
1577    * @param client
1578    * @param familyPaths
1579    * @param regionName
1580    * @param assignSeqNum
1581    * @return true if all are loaded
1582    * @throws IOException
1583    */
1584   public static boolean bulkLoadHFile(final ClientService.BlockingInterface client,
1585       final List<Pair<byte[], String>> familyPaths,
1586       final byte[] regionName, boolean assignSeqNum) throws IOException {
1587     BulkLoadHFileRequest request =
1588       RequestConverter.buildBulkLoadHFileRequest(familyPaths, regionName, assignSeqNum);
1589     try {
1590       BulkLoadHFileResponse response =
1591         client.bulkLoadHFile(null, request);
1592       return response.getLoaded();
1593     } catch (ServiceException se) {
1594       throw getRemoteException(se);
1595     }
1596   }
1597 
1598   public static CoprocessorServiceResponse execService(final ClientService.BlockingInterface client,
1599       final CoprocessorServiceCall call, final byte[] regionName) throws IOException {
1600     CoprocessorServiceRequest request = CoprocessorServiceRequest.newBuilder()
1601         .setCall(call).setRegion(
1602             RequestConverter.buildRegionSpecifier(REGION_NAME, regionName)).build();
1603     try {
1604       CoprocessorServiceResponse response =
1605           client.execService(null, request);
1606       return response;
1607     } catch (ServiceException se) {
1608       throw getRemoteException(se);
1609     }
1610   }
1611 
1612   public static CoprocessorServiceResponse execService(
1613     final MasterService.BlockingInterface client, final CoprocessorServiceCall call)
1614   throws IOException {
1615     CoprocessorServiceRequest request = CoprocessorServiceRequest.newBuilder()
1616         .setCall(call).setRegion(
1617             RequestConverter.buildRegionSpecifier(REGION_NAME, HConstants.EMPTY_BYTE_ARRAY)).build();
1618     try {
1619       CoprocessorServiceResponse response =
1620           client.execMasterService(null, request);
1621       return response;
1622     } catch (ServiceException se) {
1623       throw getRemoteException(se);
1624     }
1625   }
1626 
1627   /**
1628    * Make a region server endpoint call
1629    * @param client
1630    * @param call
1631    * @return CoprocessorServiceResponse
1632    * @throws IOException
1633    */
1634   public static CoprocessorServiceResponse execRegionServerService(
1635       final ClientService.BlockingInterface client, final CoprocessorServiceCall call)
1636       throws IOException {
1637     CoprocessorServiceRequest request =
1638         CoprocessorServiceRequest
1639             .newBuilder()
1640             .setCall(call)
1641             .setRegion(
1642               RequestConverter.buildRegionSpecifier(REGION_NAME, HConstants.EMPTY_BYTE_ARRAY))
1643             .build();
1644     try {
1645       CoprocessorServiceResponse response = client.execRegionServerService(null, request);
1646       return response;
1647     } catch (ServiceException se) {
1648       throw getRemoteException(se);
1649     }
1650   }
1651 
1652   @SuppressWarnings("unchecked")
1653   public static <T extends Service> T newServiceStub(Class<T> service, RpcChannel channel)
1654       throws Exception {
1655     return (T)Methods.call(service, null, "newStub",
1656         new Class[]{ RpcChannel.class }, new Object[]{ channel });
1657   }
1658 
1659 // End helpers for Client
1660 // Start helpers for Admin
1661 
1662   /**
1663    * A helper to retrieve region info given a region name
1664    * using admin protocol.
1665    *
1666    * @param admin
1667    * @param regionName
1668    * @return the retrieved region info
1669    * @throws IOException
1670    */
1671   public static HRegionInfo getRegionInfo(final AdminService.BlockingInterface admin,
1672       final byte[] regionName) throws IOException {
1673     try {
1674       GetRegionInfoRequest request =
1675         RequestConverter.buildGetRegionInfoRequest(regionName);
1676       GetRegionInfoResponse response =
1677         admin.getRegionInfo(null, request);
1678       return HRegionInfo.convert(response.getRegionInfo());
1679     } catch (ServiceException se) {
1680       throw getRemoteException(se);
1681     }
1682   }
1683 
1684   /**
1685    * A helper to close a region given a region name
1686    * using admin protocol.
1687    *
1688    * @param admin
1689    * @param regionName
1690    * @throws IOException
1691    */
1692   public static void closeRegion(final AdminService.BlockingInterface admin,
1693       final ServerName server, final byte[] regionName) throws IOException {
1694     CloseRegionRequest closeRegionRequest =
1695       RequestConverter.buildCloseRegionRequest(server, regionName);
1696     try {
1697       admin.closeRegion(null, closeRegionRequest);
1698     } catch (ServiceException se) {
1699       throw getRemoteException(se);
1700     }
1701   }
1702 
1703   /**
1704    * A helper to close a region given a region name
1705    * using admin protocol.
1706    *
1707    * @param admin
1708    * @param regionName
1709    * @return true if the region is closed
1710    * @throws IOException
1711    */
1712   public static boolean closeRegion(final AdminService.BlockingInterface admin,
1713       final ServerName server, final byte[] regionName,
1714       final ServerName destinationServer) throws IOException {
1715     CloseRegionRequest closeRegionRequest =
1716       RequestConverter.buildCloseRegionRequest(server,
1717         regionName, destinationServer);
1718     try {
1719       CloseRegionResponse response = admin.closeRegion(null, closeRegionRequest);
1720       return ResponseConverter.isClosed(response);
1721     } catch (ServiceException se) {
1722       throw getRemoteException(se);
1723     }
1724   }
1725 
1726 
1727   /**
1728    * A helper to open a region using admin protocol.
1729    * @param admin
1730    * @param region
1731    * @throws IOException
1732    */
1733   public static void openRegion(final AdminService.BlockingInterface admin,
1734       ServerName server, final HRegionInfo region) throws IOException {
1735     OpenRegionRequest request =
1736       RequestConverter.buildOpenRegionRequest(server, region, null, null);
1737     try {
1738       admin.openRegion(null, request);
1739     } catch (ServiceException se) {
1740       throw ProtobufUtil.getRemoteException(se);
1741     }
1742   }
1743 
1744   /**
1745    * A helper to get the all the online regions on a region
1746    * server using admin protocol.
1747    *
1748    * @param admin
1749    * @return a list of online region info
1750    * @throws IOException
1751    */
1752   public static List<HRegionInfo> getOnlineRegions(final AdminService.BlockingInterface admin)
1753   throws IOException {
1754     GetOnlineRegionRequest request = RequestConverter.buildGetOnlineRegionRequest();
1755     GetOnlineRegionResponse response = null;
1756     try {
1757       response = admin.getOnlineRegion(null, request);
1758     } catch (ServiceException se) {
1759       throw getRemoteException(se);
1760     }
1761     return getRegionInfos(response);
1762   }
1763 
1764   /**
1765    * Get the list of region info from a GetOnlineRegionResponse
1766    *
1767    * @param proto the GetOnlineRegionResponse
1768    * @return the list of region info or null if <code>proto</code> is null
1769    */
1770   static List<HRegionInfo> getRegionInfos(final GetOnlineRegionResponse proto) {
1771     if (proto == null) return null;
1772     List<HRegionInfo> regionInfos = new ArrayList<HRegionInfo>();
1773     for (RegionInfo regionInfo: proto.getRegionInfoList()) {
1774       regionInfos.add(HRegionInfo.convert(regionInfo));
1775     }
1776     return regionInfos;
1777   }
1778 
1779   /**
1780    * A helper to get the info of a region server using admin protocol.
1781    *
1782    * @param admin
1783    * @return the server name
1784    * @throws IOException
1785    */
1786   public static ServerInfo getServerInfo(final AdminService.BlockingInterface admin)
1787   throws IOException {
1788     GetServerInfoRequest request = RequestConverter.buildGetServerInfoRequest();
1789     try {
1790       GetServerInfoResponse response = admin.getServerInfo(null, request);
1791       return response.getServerInfo();
1792     } catch (ServiceException se) {
1793       throw getRemoteException(se);
1794     }
1795   }
1796 
1797   /**
1798    * A helper to get the list of files of a column family
1799    * on a given region using admin protocol.
1800    *
1801    * @param admin
1802    * @param regionName
1803    * @param family
1804    * @return the list of store files
1805    * @throws IOException
1806    */
1807   public static List<String> getStoreFiles(final AdminService.BlockingInterface admin,
1808       final byte[] regionName, final byte[] family)
1809   throws IOException {
1810     GetStoreFileRequest request =
1811       RequestConverter.buildGetStoreFileRequest(regionName, family);
1812     try {
1813       GetStoreFileResponse response = admin.getStoreFile(null, request);
1814       return response.getStoreFileList();
1815     } catch (ServiceException se) {
1816       throw ProtobufUtil.getRemoteException(se);
1817     }
1818   }
1819 
1820   /**
1821    * A helper to split a region using admin protocol.
1822    *
1823    * @param admin
1824    * @param hri
1825    * @param splitPoint
1826    * @throws IOException
1827    */
1828   public static void split(final AdminService.BlockingInterface admin,
1829       final HRegionInfo hri, byte[] splitPoint) throws IOException {
1830     SplitRegionRequest request =
1831       RequestConverter.buildSplitRegionRequest(hri.getRegionName(), splitPoint);
1832     try {
1833       admin.splitRegion(null, request);
1834     } catch (ServiceException se) {
1835       throw ProtobufUtil.getRemoteException(se);
1836     }
1837   }
1838 
1839   /**
1840    * A helper to merge regions using admin protocol. Send request to
1841    * regionserver.
1842    * @param admin
1843    * @param region_a
1844    * @param region_b
1845    * @param forcible true if do a compulsory merge, otherwise we will only merge
1846    *          two adjacent regions
1847    * @throws IOException
1848    */
1849   public static void mergeRegions(final AdminService.BlockingInterface admin,
1850       final HRegionInfo region_a, final HRegionInfo region_b,
1851       final boolean forcible) throws IOException {
1852     MergeRegionsRequest request = RequestConverter.buildMergeRegionsRequest(
1853         region_a.getRegionName(), region_b.getRegionName(),forcible);
1854     try {
1855       admin.mergeRegions(null, request);
1856     } catch (ServiceException se) {
1857       throw ProtobufUtil.getRemoteException(se);
1858     }
1859   }
1860 
1861 // End helpers for Admin
1862 
1863   /*
1864    * Get the total (read + write) requests from a RegionLoad pb
1865    * @param rl - RegionLoad pb
1866    * @return total (read + write) requests
1867    */
1868   public static long getTotalRequestsCount(RegionLoad rl) {
1869     if (rl == null) {
1870       return 0;
1871     }
1872 
1873     return rl.getReadRequestsCount() + rl.getWriteRequestsCount();
1874   }
1875 
1876 
1877   /**
1878    * @param m Message to get delimited pb serialization of (with pb magic prefix)
1879    */
1880   public static byte [] toDelimitedByteArray(final Message m) throws IOException {
1881     // Allocate arbitrary big size so we avoid resizing.
1882     ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
1883     baos.write(ProtobufMagic.PB_MAGIC);
1884     m.writeDelimitedTo(baos);
1885     return baos.toByteArray();
1886   }
1887 
1888   /**
1889    * Converts a Permission proto to a client Permission object.
1890    *
1891    * @param proto the protobuf Permission
1892    * @return the converted Permission
1893    */
1894   public static Permission toPermission(AccessControlProtos.Permission proto) {
1895     if (proto.getType() != AccessControlProtos.Permission.Type.Global) {
1896       return toTablePermission(proto);
1897     } else {
1898       List<Permission.Action> actions = toPermissionActions(proto.getGlobalPermission().getActionList());
1899       return new Permission(actions.toArray(new Permission.Action[actions.size()]));
1900     }
1901   }
1902 
1903   /**
1904    * Converts a Permission proto to a client TablePermission object.
1905    *
1906    * @param proto the protobuf Permission
1907    * @return the converted TablePermission
1908    */
1909   public static TablePermission toTablePermission(AccessControlProtos.Permission proto) {
1910     if(proto.getType() == AccessControlProtos.Permission.Type.Global) {
1911       AccessControlProtos.GlobalPermission perm = proto.getGlobalPermission();
1912       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1913 
1914       return new TablePermission(null, null, null,
1915           actions.toArray(new Permission.Action[actions.size()]));
1916     }
1917     if(proto.getType() == AccessControlProtos.Permission.Type.Namespace) {
1918       AccessControlProtos.NamespacePermission perm = proto.getNamespacePermission();
1919       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1920 
1921       if(!proto.hasNamespacePermission()) {
1922         throw new IllegalStateException("Namespace must not be empty in NamespacePermission");
1923       }
1924       String namespace = perm.getNamespaceName().toStringUtf8();
1925       return new TablePermission(namespace, actions.toArray(new Permission.Action[actions.size()]));
1926     }
1927     if(proto.getType() == AccessControlProtos.Permission.Type.Table) {
1928       AccessControlProtos.TablePermission perm = proto.getTablePermission();
1929       List<Permission.Action> actions = toPermissionActions(perm.getActionList());
1930 
1931       byte[] qualifier = null;
1932       byte[] family = null;
1933       TableName table = null;
1934 
1935       if (!perm.hasTableName()) {
1936         throw new IllegalStateException("TableName cannot be empty");
1937       }
1938       table = ProtobufUtil.toTableName(perm.getTableName());
1939 
1940       if (perm.hasFamily()) family = perm.getFamily().toByteArray();
1941       if (perm.hasQualifier()) qualifier = perm.getQualifier().toByteArray();
1942 
1943       return new TablePermission(table, family, qualifier,
1944           actions.toArray(new Permission.Action[actions.size()]));
1945     }
1946     throw new IllegalStateException("Unrecognize Perm Type: "+proto.getType());
1947   }
1948 
1949   /**
1950    * Convert a client Permission to a Permission proto
1951    *
1952    * @param perm the client Permission
1953    * @return the protobuf Permission
1954    */
1955   public static AccessControlProtos.Permission toPermission(Permission perm) {
1956     AccessControlProtos.Permission.Builder ret = AccessControlProtos.Permission.newBuilder();
1957     if (perm instanceof TablePermission) {
1958       TablePermission tablePerm = (TablePermission)perm;
1959       if(tablePerm.hasNamespace()) {
1960         ret.setType(AccessControlProtos.Permission.Type.Namespace);
1961 
1962         AccessControlProtos.NamespacePermission.Builder builder =
1963             AccessControlProtos.NamespacePermission.newBuilder();
1964         builder.setNamespaceName(ByteString.copyFromUtf8(tablePerm.getNamespace()));
1965         Permission.Action actions[] = perm.getActions();
1966         if (actions != null) {
1967           for (Permission.Action a : actions) {
1968             builder.addAction(toPermissionAction(a));
1969           }
1970         }
1971         ret.setNamespacePermission(builder);
1972         return ret.build();
1973       } else if (tablePerm.hasTable()) {
1974         ret.setType(AccessControlProtos.Permission.Type.Table);
1975 
1976         AccessControlProtos.TablePermission.Builder builder =
1977             AccessControlProtos.TablePermission.newBuilder();
1978         builder.setTableName(ProtobufUtil.toProtoTableName(tablePerm.getTableName()));
1979         if (tablePerm.hasFamily()) {
1980           builder.setFamily(ByteStringer.wrap(tablePerm.getFamily()));
1981         }
1982         if (tablePerm.hasQualifier()) {
1983           builder.setQualifier(ByteStringer.wrap(tablePerm.getQualifier()));
1984         }
1985         Permission.Action actions[] = perm.getActions();
1986         if (actions != null) {
1987           for (Permission.Action a : actions) {
1988             builder.addAction(toPermissionAction(a));
1989           }
1990         }
1991         ret.setTablePermission(builder);
1992         return ret.build();
1993       }
1994     }
1995 
1996     ret.setType(AccessControlProtos.Permission.Type.Global);
1997 
1998     AccessControlProtos.GlobalPermission.Builder builder =
1999         AccessControlProtos.GlobalPermission.newBuilder();
2000     Permission.Action actions[] = perm.getActions();
2001     if (actions != null) {
2002       for (Permission.Action a: actions) {
2003         builder.addAction(toPermissionAction(a));
2004       }
2005     }
2006     ret.setGlobalPermission(builder);
2007     return ret.build();
2008   }
2009 
2010   /**
2011    * Converts a list of Permission.Action proto to a list of client Permission.Action objects.
2012    *
2013    * @param protoActions the list of protobuf Actions
2014    * @return the converted list of Actions
2015    */
2016   public static List<Permission.Action> toPermissionActions(
2017       List<AccessControlProtos.Permission.Action> protoActions) {
2018     List<Permission.Action> actions = new ArrayList<Permission.Action>(protoActions.size());
2019     for (AccessControlProtos.Permission.Action a : protoActions) {
2020       actions.add(toPermissionAction(a));
2021     }
2022     return actions;
2023   }
2024 
2025   /**
2026    * Converts a Permission.Action proto to a client Permission.Action object.
2027    *
2028    * @param action the protobuf Action
2029    * @return the converted Action
2030    */
2031   public static Permission.Action toPermissionAction(
2032       AccessControlProtos.Permission.Action action) {
2033     switch (action) {
2034       case READ:
2035         return Permission.Action.READ;
2036       case WRITE:
2037         return Permission.Action.WRITE;
2038       case EXEC:
2039         return Permission.Action.EXEC;
2040       case CREATE:
2041         return Permission.Action.CREATE;
2042       case ADMIN:
2043         return Permission.Action.ADMIN;
2044     }
2045     throw new IllegalArgumentException("Unknown action value "+action.name());
2046   }
2047 
2048   /**
2049    * Convert a client Permission.Action to a Permission.Action proto
2050    *
2051    * @param action the client Action
2052    * @return the protobuf Action
2053    */
2054   public static AccessControlProtos.Permission.Action toPermissionAction(
2055       Permission.Action action) {
2056     switch (action) {
2057       case READ:
2058         return AccessControlProtos.Permission.Action.READ;
2059       case WRITE:
2060         return AccessControlProtos.Permission.Action.WRITE;
2061       case EXEC:
2062         return AccessControlProtos.Permission.Action.EXEC;
2063       case CREATE:
2064         return AccessControlProtos.Permission.Action.CREATE;
2065       case ADMIN:
2066         return AccessControlProtos.Permission.Action.ADMIN;
2067     }
2068     throw new IllegalArgumentException("Unknown action value "+action.name());
2069   }
2070 
2071   /**
2072    * Convert a client user permission to a user permission proto
2073    *
2074    * @param perm the client UserPermission
2075    * @return the protobuf UserPermission
2076    */
2077   public static AccessControlProtos.UserPermission toUserPermission(UserPermission perm) {
2078     return AccessControlProtos.UserPermission.newBuilder()
2079         .setUser(ByteStringer.wrap(perm.getUser()))
2080         .setPermission(toPermission(perm))
2081         .build();
2082   }
2083 
2084   /**
2085    * Converts a user permission proto to a client user permission object.
2086    *
2087    * @param proto the protobuf UserPermission
2088    * @return the converted UserPermission
2089    */
2090   public static UserPermission toUserPermission(AccessControlProtos.UserPermission proto) {
2091     return new UserPermission(proto.getUser().toByteArray(),
2092         toTablePermission(proto.getPermission()));
2093   }
2094 
2095   /**
2096    * Convert a ListMultimap<String, TablePermission> where key is username
2097    * to a protobuf UserPermission
2098    *
2099    * @param perm the list of user and table permissions
2100    * @return the protobuf UserTablePermissions
2101    */
2102   public static AccessControlProtos.UsersAndPermissions toUserTablePermissions(
2103       ListMultimap<String, TablePermission> perm) {
2104     AccessControlProtos.UsersAndPermissions.Builder builder =
2105                   AccessControlProtos.UsersAndPermissions.newBuilder();
2106     for (Map.Entry<String, Collection<TablePermission>> entry : perm.asMap().entrySet()) {
2107       AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder =
2108                   AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder();
2109       userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
2110       for (TablePermission tablePerm: entry.getValue()) {
2111         userPermBuilder.addPermissions(toPermission(tablePerm));
2112       }
2113       builder.addUserPermissions(userPermBuilder.build());
2114     }
2115     return builder.build();
2116   }
2117 
2118   /**
2119    * A utility used to grant a user global permissions.
2120    * <p>
2121    * It's also called by the shell, in case you want to find references.
2122    *
2123    * @param protocol the AccessControlService protocol proxy
2124    * @param userShortName the short name of the user to grant permissions
2125    * @param actions the permissions to be granted
2126    * @throws ServiceException
2127    */
2128   public static void grant(AccessControlService.BlockingInterface protocol,
2129       String userShortName, Permission.Action... actions) throws ServiceException {
2130     List<AccessControlProtos.Permission.Action> permActions =
2131         Lists.newArrayListWithCapacity(actions.length);
2132     for (Permission.Action a : actions) {
2133       permActions.add(ProtobufUtil.toPermissionAction(a));
2134     }
2135     AccessControlProtos.GrantRequest request = RequestConverter.
2136       buildGrantRequest(userShortName, permActions.toArray(
2137         new AccessControlProtos.Permission.Action[actions.length]));
2138     protocol.grant(null, request);
2139   }
2140 
2141   /**
2142    * A utility used to grant a user table permissions. The permissions will
2143    * be for a table table/column family/qualifier.
2144    * <p>
2145    * It's also called by the shell, in case you want to find references.
2146    *
2147    * @param protocol the AccessControlService protocol proxy
2148    * @param userShortName the short name of the user to grant permissions
2149    * @param tableName optional table name
2150    * @param f optional column family
2151    * @param q optional qualifier
2152    * @param actions the permissions to be granted
2153    * @throws ServiceException
2154    */
2155   public static void grant(AccessControlService.BlockingInterface protocol,
2156       String userShortName, TableName tableName, byte[] f, byte[] q,
2157       Permission.Action... actions) throws ServiceException {
2158     List<AccessControlProtos.Permission.Action> permActions =
2159         Lists.newArrayListWithCapacity(actions.length);
2160     for (Permission.Action a : actions) {
2161       permActions.add(ProtobufUtil.toPermissionAction(a));
2162     }
2163     AccessControlProtos.GrantRequest request = RequestConverter.
2164       buildGrantRequest(userShortName, tableName, f, q, permActions.toArray(
2165         new AccessControlProtos.Permission.Action[actions.length]));
2166     protocol.grant(null, request);
2167   }
2168 
2169   /**
2170    * A utility used to grant a user namespace permissions.
2171    * <p>
2172    * It's also called by the shell, in case you want to find references.
2173    *
2174    * @param protocol the AccessControlService protocol proxy
2175    * @param namespace the short name of the user to grant permissions
2176    * @param actions the permissions to be granted
2177    * @throws ServiceException
2178    */
2179   public static void grant(AccessControlService.BlockingInterface protocol,
2180       String userShortName, String namespace,
2181       Permission.Action... actions) throws ServiceException {
2182     List<AccessControlProtos.Permission.Action> permActions =
2183         Lists.newArrayListWithCapacity(actions.length);
2184     for (Permission.Action a : actions) {
2185       permActions.add(ProtobufUtil.toPermissionAction(a));
2186     }
2187     AccessControlProtos.GrantRequest request = RequestConverter.
2188       buildGrantRequest(userShortName, namespace, permActions.toArray(
2189         new AccessControlProtos.Permission.Action[actions.length]));
2190     protocol.grant(null, request);
2191   }
2192 
2193   /**
2194    * A utility used to revoke a user's global permissions.
2195    * <p>
2196    * It's also called by the shell, in case you want to find references.
2197    *
2198    * @param protocol the AccessControlService protocol proxy
2199    * @param userShortName the short name of the user to revoke permissions
2200    * @param actions the permissions to be revoked
2201    * @throws ServiceException
2202    */
2203   public static void revoke(AccessControlService.BlockingInterface protocol,
2204       String userShortName, Permission.Action... actions) throws ServiceException {
2205     List<AccessControlProtos.Permission.Action> permActions =
2206         Lists.newArrayListWithCapacity(actions.length);
2207     for (Permission.Action a : actions) {
2208       permActions.add(ProtobufUtil.toPermissionAction(a));
2209     }
2210     AccessControlProtos.RevokeRequest request = RequestConverter.
2211       buildRevokeRequest(userShortName, permActions.toArray(
2212         new AccessControlProtos.Permission.Action[actions.length]));
2213     protocol.revoke(null, request);
2214   }
2215 
2216   /**
2217    * A utility used to revoke a user's table permissions. The permissions will
2218    * be for a table/column family/qualifier.
2219    * <p>
2220    * It's also called by the shell, in case you want to find references.
2221    *
2222    * @param protocol the AccessControlService protocol proxy
2223    * @param userShortName the short name of the user to revoke permissions
2224    * @param tableName optional table name
2225    * @param f optional column family
2226    * @param q optional qualifier
2227    * @param actions the permissions to be revoked
2228    * @throws ServiceException
2229    */
2230   public static void revoke(AccessControlService.BlockingInterface protocol,
2231       String userShortName, TableName tableName, byte[] f, byte[] q,
2232       Permission.Action... actions) throws ServiceException {
2233     List<AccessControlProtos.Permission.Action> permActions =
2234         Lists.newArrayListWithCapacity(actions.length);
2235     for (Permission.Action a : actions) {
2236       permActions.add(ProtobufUtil.toPermissionAction(a));
2237     }
2238     AccessControlProtos.RevokeRequest request = RequestConverter.
2239       buildRevokeRequest(userShortName, tableName, f, q, permActions.toArray(
2240         new AccessControlProtos.Permission.Action[actions.length]));
2241     protocol.revoke(null, request);
2242   }
2243 
2244   /**
2245    * A utility used to revoke a user's namespace permissions.
2246    * <p>
2247    * It's also called by the shell, in case you want to find references.
2248    *
2249    * @param protocol the AccessControlService protocol proxy
2250    * @param userShortName the short name of the user to revoke permissions
2251    * @param namespace optional table name
2252    * @param actions the permissions to be revoked
2253    * @throws ServiceException
2254    */
2255   public static void revoke(AccessControlService.BlockingInterface protocol,
2256       String userShortName, String namespace,
2257       Permission.Action... actions) throws ServiceException {
2258     List<AccessControlProtos.Permission.Action> permActions =
2259         Lists.newArrayListWithCapacity(actions.length);
2260     for (Permission.Action a : actions) {
2261       permActions.add(ProtobufUtil.toPermissionAction(a));
2262     }
2263     AccessControlProtos.RevokeRequest request = RequestConverter.
2264       buildRevokeRequest(userShortName, namespace, permActions.toArray(
2265         new AccessControlProtos.Permission.Action[actions.length]));
2266     protocol.revoke(null, request);
2267   }
2268 
2269   /**
2270    * A utility used to get user's global permissions.
2271    * <p>
2272    * It's also called by the shell, in case you want to find references.
2273    *
2274    * @param protocol the AccessControlService protocol proxy
2275    * @throws ServiceException
2276    */
2277   public static List<UserPermission> getUserPermissions(
2278       AccessControlService.BlockingInterface protocol) throws ServiceException {
2279     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2280       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2281     builder.setType(AccessControlProtos.Permission.Type.Global);
2282     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2283     AccessControlProtos.GetUserPermissionsResponse response =
2284       protocol.getUserPermissions(null, request);
2285     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2286     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2287       perms.add(ProtobufUtil.toUserPermission(perm));
2288     }
2289     return perms;
2290   }
2291 
2292   /**
2293    * A utility used to get user table permissions.
2294    * <p>
2295    * It's also called by the shell, in case you want to find references.
2296    *
2297    * @param protocol the AccessControlService protocol proxy
2298    * @param t optional table name
2299    * @throws ServiceException
2300    */
2301   public static List<UserPermission> getUserPermissions(
2302       AccessControlService.BlockingInterface protocol,
2303       TableName t) throws ServiceException {
2304     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2305       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2306     if (t != null) {
2307       builder.setTableName(ProtobufUtil.toProtoTableName(t));
2308     }
2309     builder.setType(AccessControlProtos.Permission.Type.Table);
2310     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2311     AccessControlProtos.GetUserPermissionsResponse response =
2312       protocol.getUserPermissions(null, request);
2313     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2314     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2315       perms.add(ProtobufUtil.toUserPermission(perm));
2316     }
2317     return perms;
2318   }
2319 
2320   /**
2321    * A utility used to get permissions for selected namespace.
2322    * <p>
2323    * It's also called by the shell, in case you want to find references.
2324    *
2325    * @param protocol the AccessControlService protocol proxy
2326    * @param namespace name of the namespace
2327    * @throws ServiceException
2328    */
2329   public static List<UserPermission> getUserPermissions(
2330       AccessControlService.BlockingInterface protocol,
2331       byte[] namespace) throws ServiceException {
2332     AccessControlProtos.GetUserPermissionsRequest.Builder builder =
2333       AccessControlProtos.GetUserPermissionsRequest.newBuilder();
2334     if (namespace != null) {
2335       builder.setNamespaceName(ByteStringer.wrap(namespace));
2336     }
2337     builder.setType(AccessControlProtos.Permission.Type.Namespace);
2338     AccessControlProtos.GetUserPermissionsRequest request = builder.build();
2339     AccessControlProtos.GetUserPermissionsResponse response =
2340       protocol.getUserPermissions(null, request);
2341     List<UserPermission> perms = new ArrayList<UserPermission>(response.getUserPermissionCount());
2342     for (AccessControlProtos.UserPermission perm: response.getUserPermissionList()) {
2343       perms.add(ProtobufUtil.toUserPermission(perm));
2344     }
2345     return perms;
2346   }
2347 
2348   /**
2349    * Convert a protobuf UserTablePermissions to a
2350    * ListMultimap<String, TablePermission> where key is username.
2351    *
2352    * @param proto the protobuf UserPermission
2353    * @return the converted UserPermission
2354    */
2355   public static ListMultimap<String, TablePermission> toUserTablePermissions(
2356       AccessControlProtos.UsersAndPermissions proto) {
2357     ListMultimap<String, TablePermission> perms = ArrayListMultimap.create();
2358     AccessControlProtos.UsersAndPermissions.UserPermissions userPerm;
2359 
2360     for (int i = 0; i < proto.getUserPermissionsCount(); i++) {
2361       userPerm = proto.getUserPermissions(i);
2362       for (int j = 0; j < userPerm.getPermissionsCount(); j++) {
2363         TablePermission tablePerm = toTablePermission(userPerm.getPermissions(j));
2364         perms.put(userPerm.getUser().toStringUtf8(), tablePerm);
2365       }
2366     }
2367 
2368     return perms;
2369   }
2370 
2371   /**
2372    * Converts a Token instance (with embedded identifier) to the protobuf representation.
2373    *
2374    * @param token the Token instance to copy
2375    * @return the protobuf Token message
2376    */
2377   public static AuthenticationProtos.Token toToken(Token<AuthenticationTokenIdentifier> token) {
2378     AuthenticationProtos.Token.Builder builder = AuthenticationProtos.Token.newBuilder();
2379     builder.setIdentifier(ByteStringer.wrap(token.getIdentifier()));
2380     builder.setPassword(ByteStringer.wrap(token.getPassword()));
2381     if (token.getService() != null) {
2382       builder.setService(ByteString.copyFromUtf8(token.getService().toString()));
2383     }
2384     return builder.build();
2385   }
2386 
2387   /**
2388    * Converts a protobuf Token message back into a Token instance.
2389    *
2390    * @param proto the protobuf Token message
2391    * @return the Token instance
2392    */
2393   public static Token<AuthenticationTokenIdentifier> toToken(AuthenticationProtos.Token proto) {
2394     return new Token<AuthenticationTokenIdentifier>(
2395         proto.hasIdentifier() ? proto.getIdentifier().toByteArray() : null,
2396         proto.hasPassword() ? proto.getPassword().toByteArray() : null,
2397         AuthenticationTokenIdentifier.AUTH_TOKEN_TYPE,
2398         proto.hasService() ? new Text(proto.getService().toStringUtf8()) : null);
2399   }
2400 
2401   /**
2402    * Find the HRegion encoded name based on a region specifier
2403    *
2404    * @param regionSpecifier the region specifier
2405    * @return the corresponding region's encoded name
2406    * @throws DoNotRetryIOException if the specifier type is unsupported
2407    */
2408   public static String getRegionEncodedName(
2409       final RegionSpecifier regionSpecifier) throws DoNotRetryIOException {
2410     byte[] value = regionSpecifier.getValue().toByteArray();
2411     RegionSpecifierType type = regionSpecifier.getType();
2412     switch (type) {
2413       case REGION_NAME:
2414         return HRegionInfo.encodeRegionName(value);
2415       case ENCODED_REGION_NAME:
2416         return Bytes.toString(value);
2417       default:
2418         throw new DoNotRetryIOException(
2419           "Unsupported region specifier type: " + type);
2420     }
2421   }
2422 
2423   public static ScanMetrics toScanMetrics(final byte[] bytes) {
2424     Parser<MapReduceProtos.ScanMetrics> parser = MapReduceProtos.ScanMetrics.PARSER;
2425     MapReduceProtos.ScanMetrics pScanMetrics = null;
2426     try {
2427       pScanMetrics = parser.parseFrom(bytes);
2428     } catch (InvalidProtocolBufferException e) {
2429       //Ignored there are just no key values to add.
2430     }
2431     ScanMetrics scanMetrics = new ScanMetrics();
2432     if (pScanMetrics != null) {
2433       for (HBaseProtos.NameInt64Pair pair : pScanMetrics.getMetricsList()) {
2434         if (pair.hasName() && pair.hasValue()) {
2435           scanMetrics.setCounter(pair.getName(), pair.getValue());
2436         }
2437       }
2438     }
2439     return scanMetrics;
2440   }
2441 
2442   public static MapReduceProtos.ScanMetrics toScanMetrics(ScanMetrics scanMetrics) {
2443     MapReduceProtos.ScanMetrics.Builder builder = MapReduceProtos.ScanMetrics.newBuilder();
2444     Map<String, Long> metrics = scanMetrics.getMetricsMap();
2445     for (Entry<String, Long> e : metrics.entrySet()) {
2446       HBaseProtos.NameInt64Pair nameInt64Pair =
2447           HBaseProtos.NameInt64Pair.newBuilder()
2448               .setName(e.getKey())
2449               .setValue(e.getValue())
2450               .build();
2451       builder.addMetrics(nameInt64Pair);
2452     }
2453     return builder.build();
2454   }
2455 
2456   /**
2457    * Unwraps an exception from a protobuf service into the underlying (expected) IOException.
2458    * This method will <strong>always</strong> throw an exception.
2459    * @param se the {@code ServiceException} instance to convert into an {@code IOException}
2460    */
2461   public static void toIOException(ServiceException se) throws IOException {
2462     if (se == null) {
2463       throw new NullPointerException("Null service exception passed!");
2464     }
2465 
2466     Throwable cause = se.getCause();
2467     if (cause != null && cause instanceof IOException) {
2468       throw (IOException)cause;
2469     }
2470     throw new IOException(se);
2471   }
2472 
2473   public static CellProtos.Cell toCell(final Cell kv) {
2474     // Doing this is going to kill us if we do it for all data passed.
2475     // St.Ack 20121205
2476     CellProtos.Cell.Builder kvbuilder = CellProtos.Cell.newBuilder();
2477     kvbuilder.setRow(ByteStringer.wrap(kv.getRowArray(), kv.getRowOffset(),
2478         kv.getRowLength()));
2479     kvbuilder.setFamily(ByteStringer.wrap(kv.getFamilyArray(),
2480         kv.getFamilyOffset(), kv.getFamilyLength()));
2481     kvbuilder.setQualifier(ByteStringer.wrap(kv.getQualifierArray(),
2482         kv.getQualifierOffset(), kv.getQualifierLength()));
2483     kvbuilder.setCellType(CellProtos.CellType.valueOf(kv.getTypeByte()));
2484     kvbuilder.setTimestamp(kv.getTimestamp());
2485     kvbuilder.setValue(ByteStringer.wrap(kv.getValueArray(), kv.getValueOffset(),
2486         kv.getValueLength()));
2487     return kvbuilder.build();
2488   }
2489 
2490   public static Cell toCell(final CellProtos.Cell cell) {
2491     // Doing this is going to kill us if we do it for all data passed.
2492     // St.Ack 20121205
2493     return CellUtil.createCell(cell.getRow().toByteArray(),
2494       cell.getFamily().toByteArray(),
2495       cell.getQualifier().toByteArray(),
2496       cell.getTimestamp(),
2497       (byte)cell.getCellType().getNumber(),
2498       cell.getValue().toByteArray());
2499   }
2500 
2501   public static HBaseProtos.NamespaceDescriptor toProtoNamespaceDescriptor(NamespaceDescriptor ns) {
2502     HBaseProtos.NamespaceDescriptor.Builder b =
2503         HBaseProtos.NamespaceDescriptor.newBuilder()
2504             .setName(ByteString.copyFromUtf8(ns.getName()));
2505     for(Map.Entry<String, String> entry: ns.getConfiguration().entrySet()) {
2506       b.addConfiguration(HBaseProtos.NameStringPair.newBuilder()
2507           .setName(entry.getKey())
2508           .setValue(entry.getValue()));
2509     }
2510     return b.build();
2511   }
2512 
2513   public static NamespaceDescriptor toNamespaceDescriptor(
2514       HBaseProtos.NamespaceDescriptor desc) throws IOException {
2515     NamespaceDescriptor.Builder b =
2516       NamespaceDescriptor.create(desc.getName().toStringUtf8());
2517     for(HBaseProtos.NameStringPair prop : desc.getConfigurationList()) {
2518       b.addConfiguration(prop.getName(), prop.getValue());
2519     }
2520     return b.build();
2521   }
2522 
2523   /**
2524    * Get an instance of the argument type declared in a class's signature. The
2525    * argument type is assumed to be a PB Message subclass, and the instance is
2526    * created using parseFrom method on the passed ByteString.
2527    * @param runtimeClass the runtime type of the class
2528    * @param position the position of the argument in the class declaration
2529    * @param b the ByteString which should be parsed to get the instance created
2530    * @return the instance
2531    * @throws IOException
2532    */
2533   @SuppressWarnings("unchecked")
2534   public static <T extends Message>
2535   T getParsedGenericInstance(Class<?> runtimeClass, int position, ByteString b)
2536       throws IOException {
2537     Type type = runtimeClass.getGenericSuperclass();
2538     Type argType = ((ParameterizedType)type).getActualTypeArguments()[position];
2539     Class<T> classType = (Class<T>)argType;
2540     T inst;
2541     try {
2542       Method m = classType.getMethod("parseFrom", ByteString.class);
2543       inst = (T)m.invoke(null, b);
2544       return inst;
2545     } catch (SecurityException e) {
2546       throw new IOException(e);
2547     } catch (NoSuchMethodException e) {
2548       throw new IOException(e);
2549     } catch (IllegalArgumentException e) {
2550       throw new IOException(e);
2551     } catch (InvocationTargetException e) {
2552       throw new IOException(e);
2553     } catch (IllegalAccessException e) {
2554       throw new IOException(e);
2555     }
2556   }
2557 
2558   @SuppressWarnings("deprecation")
2559   public static CompactionDescriptor toCompactionDescriptor(HRegionInfo info, byte[] family,
2560       List<Path> inputPaths, List<Path> outputPaths, Path storeDir) {
2561     // compaction descriptor contains relative paths.
2562     // input / output paths are relative to the store dir
2563     // store dir is relative to region dir
2564     CompactionDescriptor.Builder builder = CompactionDescriptor.newBuilder()
2565         .setTableName(ByteStringer.wrap(info.getTableName()))
2566         .setEncodedRegionName(ByteStringer.wrap(info.getEncodedNameAsBytes()))
2567         .setFamilyName(ByteStringer.wrap(family))
2568         .setStoreHomeDir(storeDir.getName()); //make relative
2569     for (Path inputPath : inputPaths) {
2570       builder.addCompactionInput(inputPath.getName()); //relative path
2571     }
2572     for (Path outputPath : outputPaths) {
2573       builder.addCompactionOutput(outputPath.getName());
2574     }
2575     builder.setRegionName(ByteStringer.wrap(info.getRegionName()));
2576     return builder.build();
2577   }
2578 
2579   public static FlushDescriptor toFlushDescriptor(FlushAction action, HRegionInfo hri,
2580       long flushSeqId, Map<byte[], List<Path>> committedFiles) {
2581     FlushDescriptor.Builder desc = FlushDescriptor.newBuilder()
2582         .setAction(action)
2583         .setEncodedRegionName(ByteStringer.wrap(hri.getEncodedNameAsBytes()))
2584         .setFlushSequenceNumber(flushSeqId)
2585         .setTableName(ByteStringer.wrap(hri.getTable().getName()));
2586 
2587     for (Map.Entry<byte[], List<Path>> entry : committedFiles.entrySet()) {
2588       WALProtos.FlushDescriptor.StoreFlushDescriptor.Builder builder =
2589           WALProtos.FlushDescriptor.StoreFlushDescriptor.newBuilder()
2590           .setFamilyName(ByteStringer.wrap(entry.getKey()))
2591           .setStoreHomeDir(Bytes.toString(entry.getKey())); //relative to region
2592       if (entry.getValue() != null) {
2593         for (Path path : entry.getValue()) {
2594           builder.addFlushOutput(path.getName());
2595         }
2596       }
2597       desc.addStoreFlushes(builder);
2598     }
2599     return desc.build();
2600   }
2601 
2602   public static RegionEventDescriptor toRegionEventDescriptor(
2603       EventType eventType, HRegionInfo hri, long seqId, ServerName server,
2604       Map<byte[], List<Path>> storeFiles) {
2605     RegionEventDescriptor.Builder desc = RegionEventDescriptor.newBuilder()
2606         .setEventType(eventType)
2607         .setTableName(ByteStringer.wrap(hri.getTable().getName()))
2608         .setEncodedRegionName(ByteStringer.wrap(hri.getEncodedNameAsBytes()))
2609         .setLogSequenceNumber(seqId)
2610         .setServer(toServerName(server));
2611 
2612     for (Map.Entry<byte[], List<Path>> entry : storeFiles.entrySet()) {
2613       StoreDescriptor.Builder builder = StoreDescriptor.newBuilder()
2614           .setFamilyName(ByteStringer.wrap(entry.getKey()))
2615           .setStoreHomeDir(Bytes.toString(entry.getKey()));
2616       for (Path path : entry.getValue()) {
2617         builder.addStoreFile(path.getName());
2618       }
2619 
2620       desc.addStores(builder);
2621     }
2622     return desc.build();
2623   }
2624 
2625   /**
2626    * Return short version of Message toString'd, shorter than TextFormat#shortDebugString.
2627    * Tries to NOT print out data both because it can be big but also so we do not have data in our
2628    * logs. Use judiciously.
2629    * @param m
2630    * @return toString of passed <code>m</code>
2631    */
2632   public static String getShortTextFormat(Message m) {
2633     if (m == null) return "null";
2634     if (m instanceof ScanRequest) {
2635       // This should be small and safe to output.  No data.
2636       return TextFormat.shortDebugString(m);
2637     } else if (m instanceof RegionServerReportRequest) {
2638       // Print a short message only, just the servername and the requests, not the full load.
2639       RegionServerReportRequest r = (RegionServerReportRequest)m;
2640       return "server " + TextFormat.shortDebugString(r.getServer()) +
2641         " load { numberOfRequests: " + r.getLoad().getNumberOfRequests() + " }";
2642     } else if (m instanceof RegionServerStartupRequest) {
2643       // Should be small enough.
2644       return TextFormat.shortDebugString(m);
2645     } else if (m instanceof MutationProto) {
2646       return toShortString((MutationProto)m);
2647     } else if (m instanceof GetRequest) {
2648       GetRequest r = (GetRequest) m;
2649       return "region= " + getStringForByteString(r.getRegion().getValue()) +
2650           ", row=" + getStringForByteString(r.getGet().getRow());
2651     } else if (m instanceof ClientProtos.MultiRequest) {
2652       ClientProtos.MultiRequest r = (ClientProtos.MultiRequest) m;
2653       // Get first set of Actions.
2654       ClientProtos.RegionAction actions = r.getRegionActionList().get(0);
2655       String row = actions.getActionCount() <= 0? "":
2656         getStringForByteString(actions.getAction(0).hasGet()?
2657           actions.getAction(0).getGet().getRow():
2658           actions.getAction(0).getMutation().getRow());
2659       return "region= " + getStringForByteString(actions.getRegion().getValue()) +
2660           ", for " + r.getRegionActionCount() +
2661           " actions and 1st row key=" + row;
2662     } else if (m instanceof ClientProtos.MutateRequest) {
2663       ClientProtos.MutateRequest r = (ClientProtos.MutateRequest) m;
2664       return "region= " + getStringForByteString(r.getRegion().getValue()) +
2665           ", row=" + getStringForByteString(r.getMutation().getRow());
2666     }
2667     return "TODO: " + m.getClass().toString();
2668   }
2669 
2670   private static String getStringForByteString(ByteString bs) {
2671     return Bytes.toStringBinary(bs.toByteArray());
2672   }
2673 
2674   /**
2675    * Print out some subset of a MutationProto rather than all of it and its data
2676    * @param proto Protobuf to print out
2677    * @return Short String of mutation proto
2678    */
2679   static String toShortString(final MutationProto proto) {
2680     return "row=" + Bytes.toString(proto.getRow().toByteArray()) +
2681         ", type=" + proto.getMutateType().toString();
2682   }
2683 
2684   public static TableName toTableName(HBaseProtos.TableName tableNamePB) {
2685     return TableName.valueOf(tableNamePB.getNamespace().asReadOnlyByteBuffer(),
2686         tableNamePB.getQualifier().asReadOnlyByteBuffer());
2687   }
2688 
2689   public static HBaseProtos.TableName toProtoTableName(TableName tableName) {
2690     return HBaseProtos.TableName.newBuilder()
2691         .setNamespace(ByteStringer.wrap(tableName.getNamespace()))
2692         .setQualifier(ByteStringer.wrap(tableName.getQualifier())).build();
2693   }
2694 
2695   public static TableName[] getTableNameArray(List<HBaseProtos.TableName> tableNamesList) {
2696     if (tableNamesList == null) {
2697       return new TableName[0];
2698     }
2699     TableName[] tableNames = new TableName[tableNamesList.size()];
2700     for (int i = 0; i < tableNamesList.size(); i++) {
2701       tableNames[i] = toTableName(tableNamesList.get(i));
2702     }
2703     return tableNames;
2704   }
2705 
2706   /**
2707    * Convert a protocol buffer CellVisibility to a client CellVisibility
2708    *
2709    * @param proto
2710    * @return the converted client CellVisibility
2711    */
2712   public static CellVisibility toCellVisibility(ClientProtos.CellVisibility proto) {
2713     if (proto == null) return null;
2714     return new CellVisibility(proto.getExpression());
2715   }
2716 
2717   /**
2718    * Convert a protocol buffer CellVisibility bytes to a client CellVisibility
2719    *
2720    * @param protoBytes
2721    * @return the converted client CellVisibility
2722    * @throws DeserializationException
2723    */
2724   public static CellVisibility toCellVisibility(byte[] protoBytes) throws DeserializationException {
2725     if (protoBytes == null) return null;
2726     ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder();
2727     ClientProtos.CellVisibility proto = null;
2728     try {
2729       proto = builder.mergeFrom(protoBytes).build();
2730     } catch (InvalidProtocolBufferException e) {
2731       throw new DeserializationException(e);
2732     }
2733     return toCellVisibility(proto);
2734   }
2735 
2736   /**
2737    * Create a protocol buffer CellVisibility based on a client CellVisibility.
2738    *
2739    * @param cellVisibility
2740    * @return a protocol buffer CellVisibility
2741    */
2742   public static ClientProtos.CellVisibility toCellVisibility(CellVisibility cellVisibility) {
2743     ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder();
2744     builder.setExpression(cellVisibility.getExpression());
2745     return builder.build();
2746   }
2747 
2748   /**
2749    * Convert a protocol buffer Authorizations to a client Authorizations
2750    *
2751    * @param proto
2752    * @return the converted client Authorizations
2753    */
2754   public static Authorizations toAuthorizations(ClientProtos.Authorizations proto) {
2755     if (proto == null) return null;
2756     return new Authorizations(proto.getLabelList());
2757   }
2758 
2759   /**
2760    * Convert a protocol buffer Authorizations bytes to a client Authorizations
2761    *
2762    * @param protoBytes
2763    * @return the converted client Authorizations
2764    * @throws DeserializationException
2765    */
2766   public static Authorizations toAuthorizations(byte[] protoBytes) throws DeserializationException {
2767     if (protoBytes == null) return null;
2768     ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder();
2769     ClientProtos.Authorizations proto = null;
2770     try {
2771       proto = builder.mergeFrom(protoBytes).build();
2772     } catch (InvalidProtocolBufferException e) {
2773       throw new DeserializationException(e);
2774     }
2775     return toAuthorizations(proto);
2776   }
2777 
2778   /**
2779    * Create a protocol buffer Authorizations based on a client Authorizations.
2780    *
2781    * @param authorizations
2782    * @return a protocol buffer Authorizations
2783    */
2784   public static ClientProtos.Authorizations toAuthorizations(Authorizations authorizations) {
2785     ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder();
2786     for (String label : authorizations.getLabels()) {
2787       builder.addLabel(label);
2788     }
2789     return builder.build();
2790   }
2791 
2792   public static AccessControlProtos.UsersAndPermissions toUsersAndPermissions(String user,
2793       Permission perms) {
2794     return AccessControlProtos.UsersAndPermissions.newBuilder()
2795       .addUserPermissions(AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder()
2796         .setUser(ByteString.copyFromUtf8(user))
2797         .addPermissions(toPermission(perms))
2798         .build())
2799       .build();
2800   }
2801 
2802   public static AccessControlProtos.UsersAndPermissions toUsersAndPermissions(
2803       ListMultimap<String, Permission> perms) {
2804     AccessControlProtos.UsersAndPermissions.Builder builder =
2805         AccessControlProtos.UsersAndPermissions.newBuilder();
2806     for (Map.Entry<String, Collection<Permission>> entry : perms.asMap().entrySet()) {
2807       AccessControlProtos.UsersAndPermissions.UserPermissions.Builder userPermBuilder =
2808         AccessControlProtos.UsersAndPermissions.UserPermissions.newBuilder();
2809       userPermBuilder.setUser(ByteString.copyFromUtf8(entry.getKey()));
2810       for (Permission perm: entry.getValue()) {
2811         userPermBuilder.addPermissions(toPermission(perm));
2812       }
2813       builder.addUserPermissions(userPermBuilder.build());
2814     }
2815     return builder.build();
2816   }
2817 
2818   public static ListMultimap<String, Permission> toUsersAndPermissions(
2819       AccessControlProtos.UsersAndPermissions proto) {
2820     ListMultimap<String, Permission> result = ArrayListMultimap.create();
2821     for (AccessControlProtos.UsersAndPermissions.UserPermissions userPerms:
2822         proto.getUserPermissionsList()) {
2823       String user = userPerms.getUser().toStringUtf8();
2824       for (AccessControlProtos.Permission perm: userPerms.getPermissionsList()) {
2825         result.put(user, toPermission(perm));
2826       }
2827     }
2828     return result;
2829   }
2830 
2831   /**
2832    * Convert a protocol buffer TimeUnit to a client TimeUnit
2833    *
2834    * @param proto
2835    * @return the converted client TimeUnit
2836    */
2837   public static TimeUnit toTimeUnit(final HBaseProtos.TimeUnit proto) {
2838     switch (proto) {
2839       case NANOSECONDS:  return TimeUnit.NANOSECONDS;
2840       case MICROSECONDS: return TimeUnit.MICROSECONDS;
2841       case MILLISECONDS: return TimeUnit.MILLISECONDS;
2842       case SECONDS:      return TimeUnit.SECONDS;
2843       case MINUTES:      return TimeUnit.MINUTES;
2844       case HOURS:        return TimeUnit.HOURS;
2845       case DAYS:         return TimeUnit.DAYS;
2846     }
2847     throw new RuntimeException("Invalid TimeUnit " + proto);
2848   }
2849 
2850   /**
2851    * Convert a client TimeUnit to a protocol buffer TimeUnit
2852    *
2853    * @param timeUnit
2854    * @return the converted protocol buffer TimeUnit
2855    */
2856   public static HBaseProtos.TimeUnit toProtoTimeUnit(final TimeUnit timeUnit) {
2857     switch (timeUnit) {
2858       case NANOSECONDS:  return HBaseProtos.TimeUnit.NANOSECONDS;
2859       case MICROSECONDS: return HBaseProtos.TimeUnit.MICROSECONDS;
2860       case MILLISECONDS: return HBaseProtos.TimeUnit.MILLISECONDS;
2861       case SECONDS:      return HBaseProtos.TimeUnit.SECONDS;
2862       case MINUTES:      return HBaseProtos.TimeUnit.MINUTES;
2863       case HOURS:        return HBaseProtos.TimeUnit.HOURS;
2864       case DAYS:         return HBaseProtos.TimeUnit.DAYS;
2865     }
2866     throw new RuntimeException("Invalid TimeUnit " + timeUnit);
2867   }
2868 
2869   /**
2870    * Convert a protocol buffer ThrottleType to a client ThrottleType
2871    *
2872    * @param proto
2873    * @return the converted client ThrottleType
2874    */
2875   public static ThrottleType toThrottleType(final QuotaProtos.ThrottleType proto) {
2876     switch (proto) {
2877       case REQUEST_NUMBER: return ThrottleType.REQUEST_NUMBER;
2878       case REQUEST_SIZE:   return ThrottleType.REQUEST_SIZE;
2879     }
2880     throw new RuntimeException("Invalid ThrottleType " + proto);
2881   }
2882 
2883   /**
2884    * Convert a client ThrottleType to a protocol buffer ThrottleType
2885    *
2886    * @param type
2887    * @return the converted protocol buffer ThrottleType
2888    */
2889   public static QuotaProtos.ThrottleType toProtoThrottleType(final ThrottleType type) {
2890     switch (type) {
2891       case REQUEST_NUMBER: return QuotaProtos.ThrottleType.REQUEST_NUMBER;
2892       case REQUEST_SIZE:   return QuotaProtos.ThrottleType.REQUEST_SIZE;
2893     }
2894     throw new RuntimeException("Invalid ThrottleType " + type);
2895   }
2896 
2897   /**
2898    * Convert a protocol buffer QuotaScope to a client QuotaScope
2899    *
2900    * @param proto
2901    * @return the converted client QuotaScope
2902    */
2903   public static QuotaScope toQuotaScope(final QuotaProtos.QuotaScope proto) {
2904     switch (proto) {
2905       case CLUSTER: return QuotaScope.CLUSTER;
2906       case MACHINE: return QuotaScope.MACHINE;
2907     }
2908     throw new RuntimeException("Invalid QuotaScope " + proto);
2909   }
2910 
2911   /**
2912    * Convert a client QuotaScope to a protocol buffer QuotaScope
2913    *
2914    * @param scope
2915    * @return the converted protocol buffer QuotaScope
2916    */
2917   public static QuotaProtos.QuotaScope toProtoQuotaScope(final QuotaScope scope) {
2918     switch (scope) {
2919       case CLUSTER: return QuotaProtos.QuotaScope.CLUSTER;
2920       case MACHINE: return QuotaProtos.QuotaScope.MACHINE;
2921     }
2922     throw new RuntimeException("Invalid QuotaScope " + scope);
2923   }
2924 
2925   /**
2926    * Convert a protocol buffer QuotaType to a client QuotaType
2927    *
2928    * @param proto
2929    * @return the converted client QuotaType
2930    */
2931   public static QuotaType toQuotaScope(final QuotaProtos.QuotaType proto) {
2932     switch (proto) {
2933       case THROTTLE: return QuotaType.THROTTLE;
2934     }
2935     throw new RuntimeException("Invalid QuotaType " + proto);
2936   }
2937 
2938   /**
2939    * Convert a client QuotaType to a protocol buffer QuotaType
2940    *
2941    * @param type
2942    * @return the converted protocol buffer QuotaType
2943    */
2944   public static QuotaProtos.QuotaType toProtoQuotaScope(final QuotaType type) {
2945     switch (type) {
2946       case THROTTLE: return QuotaProtos.QuotaType.THROTTLE;
2947     }
2948     throw new RuntimeException("Invalid QuotaType " + type);
2949   }
2950 
2951   /**
2952    * Build a protocol buffer TimedQuota
2953    *
2954    * @param limit the allowed number of request/data per timeUnit
2955    * @param timeUnit the limit time unit
2956    * @param scope the quota scope
2957    * @return the protocol buffer TimedQuota
2958    */
2959   public static QuotaProtos.TimedQuota toTimedQuota(final long limit, final TimeUnit timeUnit,
2960       final QuotaScope scope) {
2961     return QuotaProtos.TimedQuota.newBuilder()
2962             .setSoftLimit(limit)
2963             .setTimeUnit(toProtoTimeUnit(timeUnit))
2964             .setScope(toProtoQuotaScope(scope))
2965             .build();
2966   }
2967 
2968   /**
2969    * Generates a marker for the WAL so that we propagate the notion of a bulk region load
2970    * throughout the WAL.
2971    *
2972    * @param tableName         The tableName into which the bulk load is being imported into.
2973    * @param encodedRegionName Encoded region name of the region which is being bulk loaded.
2974    * @param storeFiles        A set of store files of a column family are bulk loaded.
2975    * @param bulkloadSeqId     sequence ID (by a force flush) used to create bulk load hfile
2976    *                          name
2977    * @return The WAL log marker for bulk loads.
2978    */
2979   public static WALProtos.BulkLoadDescriptor toBulkLoadDescriptor(TableName tableName,
2980       ByteString encodedRegionName, Map<byte[], List<Path>> storeFiles, long bulkloadSeqId) {
2981     BulkLoadDescriptor.Builder desc = BulkLoadDescriptor.newBuilder()
2982         .setTableName(ProtobufUtil.toProtoTableName(tableName))
2983         .setEncodedRegionName(encodedRegionName).setBulkloadSeqNum(bulkloadSeqId);
2984 
2985     for (Map.Entry<byte[], List<Path>> entry : storeFiles.entrySet()) {
2986       WALProtos.StoreDescriptor.Builder builder = StoreDescriptor.newBuilder()
2987           .setFamilyName(ByteStringer.wrap(entry.getKey()))
2988           .setStoreHomeDir(Bytes.toString(entry.getKey())); // relative to region
2989       for (Path path : entry.getValue()) {
2990         builder.addStoreFile(path.getName());
2991       }
2992       desc.addStores(builder);
2993     }
2994 
2995     return desc.build();
2996   }
2997 }