001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.shaded.protobuf; 019 020import static org.apache.hadoop.hbase.protobuf.ProtobufMagic.PB_MAGIC; 021 022import java.io.ByteArrayOutputStream; 023import java.io.EOFException; 024import java.io.IOException; 025import java.io.InputStream; 026import java.lang.reflect.Constructor; 027import java.lang.reflect.InvocationTargetException; 028import java.lang.reflect.Method; 029import java.nio.ByteBuffer; 030import java.security.AccessController; 031import java.security.PrivilegedAction; 032import java.util.ArrayList; 033import java.util.Collection; 034import java.util.Collections; 035import java.util.HashMap; 036import java.util.List; 037import java.util.Locale; 038import java.util.Map; 039import java.util.Map.Entry; 040import java.util.NavigableSet; 041import java.util.Objects; 042import java.util.Optional; 043import java.util.Set; 044import java.util.concurrent.Callable; 045import java.util.concurrent.TimeUnit; 046import java.util.function.Function; 047import java.util.regex.Pattern; 048import java.util.stream.Collectors; 049import org.apache.hadoop.conf.Configuration; 050import org.apache.hadoop.fs.Path; 051import org.apache.hadoop.hbase.ByteBufferExtendedCell; 052import org.apache.hadoop.hbase.CacheEvictionStats; 053import org.apache.hadoop.hbase.CacheEvictionStatsBuilder; 054import org.apache.hadoop.hbase.Cell; 055import org.apache.hadoop.hbase.CellBuilderType; 056import org.apache.hadoop.hbase.CellScanner; 057import org.apache.hadoop.hbase.CellUtil; 058import org.apache.hadoop.hbase.CompareOperator; 059import org.apache.hadoop.hbase.DoNotRetryIOException; 060import org.apache.hadoop.hbase.ExtendedCell; 061import org.apache.hadoop.hbase.ExtendedCellBuilder; 062import org.apache.hadoop.hbase.ExtendedCellBuilderFactory; 063import org.apache.hadoop.hbase.HBaseConfiguration; 064import org.apache.hadoop.hbase.HBaseIOException; 065import org.apache.hadoop.hbase.HConstants; 066import org.apache.hadoop.hbase.HRegionLocation; 067import org.apache.hadoop.hbase.KeyValue; 068import org.apache.hadoop.hbase.NamespaceDescriptor; 069import org.apache.hadoop.hbase.ServerName; 070import org.apache.hadoop.hbase.ServerTask; 071import org.apache.hadoop.hbase.ServerTaskBuilder; 072import org.apache.hadoop.hbase.TableName; 073import org.apache.hadoop.hbase.client.Append; 074import org.apache.hadoop.hbase.client.BalanceRequest; 075import org.apache.hadoop.hbase.client.BalanceResponse; 076import org.apache.hadoop.hbase.client.BalancerDecision; 077import org.apache.hadoop.hbase.client.BalancerRejection; 078import org.apache.hadoop.hbase.client.CheckAndMutate; 079import org.apache.hadoop.hbase.client.ClientInternalHelper; 080import org.apache.hadoop.hbase.client.ClientUtil; 081import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 082import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 083import org.apache.hadoop.hbase.client.CompactionState; 084import org.apache.hadoop.hbase.client.Consistency; 085import org.apache.hadoop.hbase.client.Cursor; 086import org.apache.hadoop.hbase.client.Delete; 087import org.apache.hadoop.hbase.client.Durability; 088import org.apache.hadoop.hbase.client.Get; 089import org.apache.hadoop.hbase.client.Increment; 090import org.apache.hadoop.hbase.client.LogEntry; 091import org.apache.hadoop.hbase.client.Mutation; 092import org.apache.hadoop.hbase.client.OnlineLogRecord; 093import org.apache.hadoop.hbase.client.Put; 094import org.apache.hadoop.hbase.client.QueryMetrics; 095import org.apache.hadoop.hbase.client.RegionInfoBuilder; 096import org.apache.hadoop.hbase.client.RegionLoadStats; 097import org.apache.hadoop.hbase.client.RegionReplicaUtil; 098import org.apache.hadoop.hbase.client.RegionStatesCount; 099import org.apache.hadoop.hbase.client.Result; 100import org.apache.hadoop.hbase.client.RowMutations; 101import org.apache.hadoop.hbase.client.Scan; 102import org.apache.hadoop.hbase.client.SlowLogParams; 103import org.apache.hadoop.hbase.client.SnapshotDescription; 104import org.apache.hadoop.hbase.client.SnapshotType; 105import org.apache.hadoop.hbase.client.TableDescriptor; 106import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 107import org.apache.hadoop.hbase.client.metrics.ScanMetrics; 108import org.apache.hadoop.hbase.client.security.SecurityCapability; 109import org.apache.hadoop.hbase.exceptions.DeserializationException; 110import org.apache.hadoop.hbase.filter.BinaryComparator; 111import org.apache.hadoop.hbase.filter.ByteArrayComparable; 112import org.apache.hadoop.hbase.filter.Filter; 113import org.apache.hadoop.hbase.io.TimeRange; 114import org.apache.hadoop.hbase.master.RegionState; 115import org.apache.hadoop.hbase.net.Address; 116import org.apache.hadoop.hbase.protobuf.ProtobufMagic; 117import org.apache.hadoop.hbase.protobuf.ProtobufMessageConverter; 118import org.apache.hadoop.hbase.quotas.QuotaScope; 119import org.apache.hadoop.hbase.quotas.QuotaType; 120import org.apache.hadoop.hbase.quotas.SpaceViolationPolicy; 121import org.apache.hadoop.hbase.quotas.ThrottleType; 122import org.apache.hadoop.hbase.replication.ReplicationLoadSink; 123import org.apache.hadoop.hbase.replication.ReplicationLoadSource; 124import org.apache.hadoop.hbase.rsgroup.RSGroupInfo; 125import org.apache.hadoop.hbase.security.visibility.Authorizations; 126import org.apache.hadoop.hbase.security.visibility.CellVisibility; 127import org.apache.hadoop.hbase.util.Addressing; 128import org.apache.hadoop.hbase.util.Bytes; 129import org.apache.hadoop.hbase.util.DynamicClassLoader; 130import org.apache.hadoop.hbase.util.ExceptionUtil; 131import org.apache.hadoop.hbase.util.Methods; 132import org.apache.hadoop.hbase.util.ReflectedFunctionCache; 133import org.apache.hadoop.hbase.util.VersionInfo; 134import org.apache.hadoop.ipc.RemoteException; 135import org.apache.yetus.audience.InterfaceAudience; 136import org.slf4j.Logger; 137import org.slf4j.LoggerFactory; 138 139import org.apache.hbase.thirdparty.com.google.common.io.ByteStreams; 140import org.apache.hbase.thirdparty.com.google.gson.JsonArray; 141import org.apache.hbase.thirdparty.com.google.gson.JsonElement; 142import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 143import org.apache.hbase.thirdparty.com.google.protobuf.CodedInputStream; 144import org.apache.hbase.thirdparty.com.google.protobuf.InvalidProtocolBufferException; 145import org.apache.hbase.thirdparty.com.google.protobuf.Message; 146import org.apache.hbase.thirdparty.com.google.protobuf.Parser; 147import org.apache.hbase.thirdparty.com.google.protobuf.RpcChannel; 148import org.apache.hbase.thirdparty.com.google.protobuf.RpcController; 149import org.apache.hbase.thirdparty.com.google.protobuf.Service; 150import org.apache.hbase.thirdparty.com.google.protobuf.ServiceException; 151import org.apache.hbase.thirdparty.com.google.protobuf.TextFormat; 152import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations; 153import org.apache.hbase.thirdparty.org.apache.commons.collections4.CollectionUtils; 154 155import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos; 156import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.AdminService; 157import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ClearSlowLogResponses; 158import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.CloseRegionRequest; 159import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetCachedFilesListRequest; 160import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetCachedFilesListResponse; 161import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionRequest; 162import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetOnlineRegionResponse; 163import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoRequest; 164import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetRegionInfoResponse; 165import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoRequest; 166import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetServerInfoResponse; 167import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetStoreFileRequest; 168import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.GetStoreFileResponse; 169import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.OpenRegionRequest; 170import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ServerInfo; 171import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.WarmupRegionRequest; 172import org.apache.hadoop.hbase.shaded.protobuf.generated.CellProtos; 173import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; 174import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.Column; 175import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.CoprocessorServiceRequest; 176import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.GetRequest; 177import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MultiRequest; 178import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutateRequest; 179import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto; 180import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.ColumnValue; 181import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.ColumnValue.QualifierValue; 182import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.DeleteType; 183import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.MutationProto.MutationType; 184import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.RegionAction; 185import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos.ScanRequest; 186import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos; 187import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionLoad; 188import org.apache.hadoop.hbase.shaded.protobuf.generated.ComparatorProtos; 189import org.apache.hadoop.hbase.shaded.protobuf.generated.FilterProtos; 190import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 191import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.BytesBytesPair; 192import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema; 193import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameBytesPair; 194import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.NameStringPair; 195import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ProcedureDescription; 196import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionExceptionMessage; 197import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionInfo; 198import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier; 199import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.RegionSpecifier.RegionSpecifierType; 200import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.TableSchema; 201import org.apache.hadoop.hbase.shaded.protobuf.generated.HFileProtos; 202import org.apache.hadoop.hbase.shaded.protobuf.generated.LockServiceProtos; 203import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos; 204import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; 205import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest; 206import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetCompletedSnapshotsResponse; 207import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsResponse; 208import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse; 209import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByNamespaceResponse; 210import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListTableDescriptorsByStateResponse; 211import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MajorCompactionTimestampResponse; 212import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos; 213import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos; 214import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupAdminProtos; 215import org.apache.hadoop.hbase.shaded.protobuf.generated.RSGroupProtos; 216import org.apache.hadoop.hbase.shaded.protobuf.generated.RecentLogs; 217import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest; 218import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest; 219import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos; 220import org.apache.hadoop.hbase.shaded.protobuf.generated.TooSlowLog; 221import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos; 222import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.BulkLoadDescriptor; 223import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.CompactionDescriptor; 224import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FlushDescriptor; 225import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FlushDescriptor.FlushAction; 226import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.RegionEventDescriptor; 227import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.RegionEventDescriptor.EventType; 228import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.StoreDescriptor; 229import org.apache.hadoop.hbase.shaded.protobuf.generated.ZooKeeperProtos; 230 231/** 232 * Protobufs utility. Be aware that a class named org.apache.hadoop.hbase.protobuf.ProtobufUtil 233 * (i.e. no 'shaded' in the package name) carries a COPY of a subset of this class for non-shaded 234 * users; e.g. Coprocessor Endpoints. If you make change in here, be sure to make change in the 235 * companion class too (not the end of the world, especially if you are adding new functionality but 236 * something to be aware of. 237 */ 238@InterfaceAudience.Private // TODO: some clients (Hive, etc) use this class 239public final class ProtobufUtil { 240 241 private static final Logger LOG = LoggerFactory.getLogger(ProtobufUtil.class.getName()); 242 243 private ProtobufUtil() { 244 } 245 246 /** 247 * Many results are simple: no cell, exists true or false. To save on object creations, we reuse 248 * them across calls. 249 */ 250 private final static ExtendedCell[] EMPTY_CELL_ARRAY = new ExtendedCell[0]; 251 private final static Result EMPTY_RESULT = Result.create(EMPTY_CELL_ARRAY); 252 final static Result EMPTY_RESULT_EXISTS_TRUE = Result.create(null, true); 253 final static Result EMPTY_RESULT_EXISTS_FALSE = Result.create(null, false); 254 private final static Result EMPTY_RESULT_STALE = Result.create(EMPTY_CELL_ARRAY, null, true); 255 private final static Result EMPTY_RESULT_EXISTS_TRUE_STALE = 256 Result.create((Cell[]) null, true, true); 257 private final static Result EMPTY_RESULT_EXISTS_FALSE_STALE = 258 Result.create((Cell[]) null, false, true); 259 260 private final static ClientProtos.Result EMPTY_RESULT_PB; 261 private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE; 262 private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE; 263 private final static ClientProtos.Result EMPTY_RESULT_PB_STALE; 264 private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_TRUE_STALE; 265 private final static ClientProtos.Result EMPTY_RESULT_PB_EXISTS_FALSE_STALE; 266 267 static { 268 ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder(); 269 270 builder.setExists(true); 271 builder.setAssociatedCellCount(0); 272 EMPTY_RESULT_PB_EXISTS_TRUE = builder.build(); 273 274 builder.setStale(true); 275 EMPTY_RESULT_PB_EXISTS_TRUE_STALE = builder.build(); 276 builder.clear(); 277 278 builder.setExists(false); 279 builder.setAssociatedCellCount(0); 280 EMPTY_RESULT_PB_EXISTS_FALSE = builder.build(); 281 builder.setStale(true); 282 EMPTY_RESULT_PB_EXISTS_FALSE_STALE = builder.build(); 283 284 builder.clear(); 285 builder.setAssociatedCellCount(0); 286 EMPTY_RESULT_PB = builder.build(); 287 builder.setStale(true); 288 EMPTY_RESULT_PB_STALE = builder.build(); 289 } 290 291 private static volatile boolean classLoaderLoaded = false; 292 293 /** 294 * Dynamic class loader to load filter/comparators 295 */ 296 private final static class ClassLoaderHolder { 297 private final static ClassLoader CLASS_LOADER; 298 299 static { 300 ClassLoader parent = ProtobufUtil.class.getClassLoader(); 301 Configuration conf = HBaseConfiguration.create(); 302 CLASS_LOADER = AccessController 303 .doPrivileged((PrivilegedAction<ClassLoader>) () -> new DynamicClassLoader(conf, parent)); 304 classLoaderLoaded = true; 305 } 306 } 307 308 public static boolean isClassLoaderLoaded() { 309 return classLoaderLoaded; 310 } 311 312 private static final String PARSE_FROM = "parseFrom"; 313 314 // We don't bother using the dynamic CLASS_LOADER above, because currently we can't support 315 // optimizing dynamically loaded classes. We can do it once we build for java9+, see the todo 316 // in ReflectedFunctionCache 317 private static final ReflectedFunctionCache<byte[], Filter> FILTERS = 318 new ReflectedFunctionCache<>(Filter.class, byte[].class, PARSE_FROM); 319 private static final ReflectedFunctionCache<byte[], ByteArrayComparable> COMPARATORS = 320 new ReflectedFunctionCache<>(ByteArrayComparable.class, byte[].class, PARSE_FROM); 321 322 private static volatile boolean ALLOW_FAST_REFLECTION_FALLTHROUGH = true; 323 324 // Visible for tests 325 public static void setAllowFastReflectionFallthrough(boolean val) { 326 ALLOW_FAST_REFLECTION_FALLTHROUGH = val; 327 } 328 329 /** 330 * Prepend the passed bytes with four bytes of magic, {@link ProtobufMagic#PB_MAGIC}, to flag what 331 * follows as a protobuf in hbase. Prepend these bytes to all content written to znodes, etc. 332 * @param bytes Bytes to decorate 333 * @return The passed <code>bytes</code> with magic prepended (Creates a new byte array that is 334 * <code>bytes.length</code> plus {@link ProtobufMagic#PB_MAGIC}.length. 335 */ 336 public static byte[] prependPBMagic(final byte[] bytes) { 337 return Bytes.add(PB_MAGIC, bytes); 338 } 339 340 /** Returns True if passed <code>bytes</code> has {@link ProtobufMagic#PB_MAGIC} for a prefix. */ 341 public static boolean isPBMagicPrefix(final byte[] bytes) { 342 return ProtobufMagic.isPBMagicPrefix(bytes); 343 } 344 345 /** Returns True if passed <code>bytes</code> has {@link ProtobufMagic#PB_MAGIC} for a prefix. */ 346 public static boolean isPBMagicPrefix(final byte[] bytes, int offset, int len) { 347 return ProtobufMagic.isPBMagicPrefix(bytes, offset, len); 348 } 349 350 /** 351 * Expect the {@link ProtobufMagic#PB_MAGIC} or throw an exception. 352 * @param bytes bytes to check 353 * @throws DeserializationException if we are missing the pb magic prefix 354 */ 355 public static void expectPBMagicPrefix(final byte[] bytes) throws DeserializationException { 356 if (!isPBMagicPrefix(bytes)) { 357 String bytesPrefix = bytes == null ? "null" : Bytes.toStringBinary(bytes, 0, PB_MAGIC.length); 358 throw new DeserializationException( 359 "Missing pb magic " + Bytes.toString(PB_MAGIC) + " prefix" + ", bytes: " + bytesPrefix); 360 } 361 } 362 363 /** Returns Length of {@link ProtobufMagic#lengthOfPBMagic()} */ 364 public static int lengthOfPBMagic() { 365 return ProtobufMagic.lengthOfPBMagic(); 366 } 367 368 public static ComparatorProtos.ByteArrayComparable toByteArrayComparable(final byte[] value) { 369 ComparatorProtos.ByteArrayComparable.Builder builder = 370 ComparatorProtos.ByteArrayComparable.newBuilder(); 371 if (value != null) builder.setValue(UnsafeByteOperations.unsafeWrap(value)); 372 return builder.build(); 373 } 374 375 /** 376 * Return the IOException thrown by the remote server wrapped in ServiceException as cause. 377 * @param se ServiceException that wraps IO exception thrown by the server 378 * @return Exception wrapped in ServiceException or a new IOException that wraps the unexpected 379 * ServiceException. 380 */ 381 public static IOException getRemoteException(ServiceException se) { 382 return makeIOExceptionOfException(se); 383 } 384 385 /** 386 * Like {@link #getRemoteException(ServiceException)} but more generic, able to handle more than 387 * just {@link ServiceException}. Prefer this method to 388 * {@link #getRemoteException(ServiceException)} because trying to contain direct protobuf 389 * references. 390 */ 391 public static IOException handleRemoteException(Throwable e) { 392 return makeIOExceptionOfException(e); 393 } 394 395 private static IOException makeIOExceptionOfException(Throwable e) { 396 Throwable t = e; 397 if (e instanceof ServiceException) { 398 t = e.getCause(); 399 } 400 if (ExceptionUtil.isInterrupt(t)) { 401 return ExceptionUtil.asInterrupt(t); 402 } 403 if (t instanceof RemoteException) { 404 t = ((RemoteException) t).unwrapRemoteException(); 405 } 406 return t instanceof IOException ? (IOException) t : new HBaseIOException(t); 407 } 408 409 /** 410 * Convert a ServerName to a protocol buffer ServerName 411 * @param serverName the ServerName to convert 412 * @return the converted protocol buffer ServerName 413 * @see #toServerName(org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ServerName) 414 */ 415 public static HBaseProtos.ServerName toServerName(final ServerName serverName) { 416 if (serverName == null) { 417 return null; 418 } 419 HBaseProtos.ServerName.Builder builder = HBaseProtos.ServerName.newBuilder(); 420 builder.setHostName(serverName.getHostname()); 421 if (serverName.getPort() >= 0) { 422 builder.setPort(serverName.getPort()); 423 } 424 if (serverName.getStartcode() >= 0) { 425 builder.setStartCode(serverName.getStartcode()); 426 } 427 return builder.build(); 428 } 429 430 /** 431 * Convert a protocol buffer ServerName to a ServerName 432 * @param proto the protocol buffer ServerName to convert 433 * @return the converted ServerName 434 */ 435 public static ServerName toServerName(final HBaseProtos.ServerName proto) { 436 if (proto == null) return null; 437 String hostName = proto.getHostName(); 438 long startCode = -1; 439 int port = -1; 440 if (proto.hasPort()) { 441 port = proto.getPort(); 442 } 443 if (proto.hasStartCode()) { 444 startCode = proto.getStartCode(); 445 } 446 return ServerName.valueOf(hostName, port, startCode); 447 } 448 449 /** 450 * Get a ServerName from the passed in data bytes. 451 * @param data Data with a serialize server name in it; can handle the old style servername where 452 * servername was host and port. Works too with data that begins w/ the pb 'PBUF' 453 * magic and that is then followed by a protobuf that has a serialized 454 * {@link ServerName} in it. 455 * @return Returns null if <code>data</code> is null else converts passed data to a ServerName 456 * instance. 457 */ 458 public static ServerName toServerName(final byte[] data) throws DeserializationException { 459 if (data == null || data.length <= 0) { 460 return null; 461 } 462 if (ProtobufMagic.isPBMagicPrefix(data)) { 463 int prefixLen = ProtobufMagic.lengthOfPBMagic(); 464 try { 465 ZooKeeperProtos.Master rss = 466 ZooKeeperProtos.Master.parser().parseFrom(data, prefixLen, data.length - prefixLen); 467 HBaseProtos.ServerName sn = rss.getMaster(); 468 return ServerName.valueOf(sn.getHostName(), sn.getPort(), sn.getStartCode()); 469 } catch (/* InvalidProtocolBufferException */IOException e) { 470 // A failed parse of the znode is pretty catastrophic. Rather than loop 471 // retrying hoping the bad bytes will changes, and rather than change 472 // the signature on this method to add an IOE which will send ripples all 473 // over the code base, throw a RuntimeException. This should "never" happen. 474 // Fail fast if it does. 475 throw new DeserializationException(e); 476 } 477 } 478 // The str returned could be old style -- pre hbase-1502 -- which was 479 // hostname and port seperated by a colon rather than hostname, port and 480 // startcode delimited by a ','. 481 String str = Bytes.toString(data); 482 int index = str.indexOf(ServerName.SERVERNAME_SEPARATOR); 483 if (index != -1) { 484 // Presume its ServerName serialized with versioned bytes. 485 return ServerName.parseVersionedServerName(data); 486 } 487 // Presume it a hostname:port format. 488 String hostname = Addressing.parseHostname(str); 489 int port = Addressing.parsePort(str); 490 return ServerName.valueOf(hostname, port, -1L); 491 } 492 493 /** 494 * Convert a list of protocol buffer ServerName to a list of ServerName 495 * @param proto protocol buffer ServerNameList 496 * @return a list of ServerName 497 */ 498 public static List<ServerName> toServerNameList(List<HBaseProtos.ServerName> proto) { 499 return proto.stream().map(ProtobufUtil::toServerName).collect(Collectors.toList()); 500 } 501 502 /** 503 * Get a list of NamespaceDescriptor from ListNamespaceDescriptorsResponse protobuf 504 * @param proto the ListNamespaceDescriptorsResponse 505 * @return a list of NamespaceDescriptor 506 */ 507 public static List<NamespaceDescriptor> 508 toNamespaceDescriptorList(ListNamespaceDescriptorsResponse proto) { 509 return proto.getNamespaceDescriptorList().stream().map(ProtobufUtil::toNamespaceDescriptor) 510 .collect(Collectors.toList()); 511 } 512 513 /** 514 * Get a list of TableDescriptor from GetTableDescriptorsResponse protobuf 515 * @param proto the GetTableDescriptorsResponse 516 * @return a list of TableDescriptor 517 */ 518 public static List<TableDescriptor> toTableDescriptorList(GetTableDescriptorsResponse proto) { 519 if (proto == null) { 520 return new ArrayList<>(); 521 } 522 return proto.getTableSchemaList().stream().map(ProtobufUtil::toTableDescriptor) 523 .collect(Collectors.toList()); 524 } 525 526 /** 527 * Get a list of TableDescriptor from ListTableDescriptorsByNamespaceResponse protobuf 528 * @param proto the ListTableDescriptorsByNamespaceResponse 529 * @return a list of TableDescriptor 530 */ 531 public static List<TableDescriptor> 532 toTableDescriptorList(ListTableDescriptorsByNamespaceResponse proto) { 533 if (proto == null) return new ArrayList<>(); 534 return proto.getTableSchemaList().stream().map(ProtobufUtil::toTableDescriptor) 535 .collect(Collectors.toList()); 536 } 537 538 /** 539 * Get a list of TableDescriptor from ListTableDescriptorsByNamespaceResponse protobuf 540 * @param proto the ListTableDescriptorsByNamespaceResponse 541 * @return a list of TableDescriptor 542 */ 543 public static List<TableDescriptor> 544 toTableDescriptorList(ListTableDescriptorsByStateResponse proto) { 545 if (proto == null) return new ArrayList<>(); 546 return proto.getTableSchemaList().stream().map(ProtobufUtil::toTableDescriptor) 547 .collect(Collectors.toList()); 548 } 549 550 /** 551 * get the split keys in form "byte [][]" from a CreateTableRequest proto 552 * @param proto the CreateTableRequest 553 * @return the split keys 554 */ 555 public static byte[][] getSplitKeysArray(final CreateTableRequest proto) { 556 byte[][] splitKeys = new byte[proto.getSplitKeysCount()][]; 557 for (int i = 0; i < proto.getSplitKeysCount(); ++i) { 558 splitKeys[i] = proto.getSplitKeys(i).toByteArray(); 559 } 560 return splitKeys; 561 } 562 563 /** 564 * Convert a protobuf Durability into a client Durability 565 */ 566 public static Durability toDurability(final ClientProtos.MutationProto.Durability proto) { 567 switch (proto) { 568 case USE_DEFAULT: 569 return Durability.USE_DEFAULT; 570 case SKIP_WAL: 571 return Durability.SKIP_WAL; 572 case ASYNC_WAL: 573 return Durability.ASYNC_WAL; 574 case SYNC_WAL: 575 return Durability.SYNC_WAL; 576 case FSYNC_WAL: 577 return Durability.FSYNC_WAL; 578 default: 579 return Durability.USE_DEFAULT; 580 } 581 } 582 583 /** 584 * Convert a client Durability into a protbuf Durability 585 */ 586 public static ClientProtos.MutationProto.Durability toDurability(final Durability d) { 587 switch (d) { 588 case USE_DEFAULT: 589 return ClientProtos.MutationProto.Durability.USE_DEFAULT; 590 case SKIP_WAL: 591 return ClientProtos.MutationProto.Durability.SKIP_WAL; 592 case ASYNC_WAL: 593 return ClientProtos.MutationProto.Durability.ASYNC_WAL; 594 case SYNC_WAL: 595 return ClientProtos.MutationProto.Durability.SYNC_WAL; 596 case FSYNC_WAL: 597 return ClientProtos.MutationProto.Durability.FSYNC_WAL; 598 default: 599 return ClientProtos.MutationProto.Durability.USE_DEFAULT; 600 } 601 } 602 603 /** 604 * Convert a protocol buffer Get to a client Get 605 * @param proto the protocol buffer Get to convert 606 * @return the converted client Get 607 */ 608 public static Get toGet(final ClientProtos.Get proto) throws IOException { 609 if (proto == null) return null; 610 byte[] row = proto.getRow().toByteArray(); 611 Get get = new Get(row); 612 if (proto.hasCacheBlocks()) { 613 get.setCacheBlocks(proto.getCacheBlocks()); 614 } 615 if (proto.hasMaxVersions()) { 616 get.readVersions(proto.getMaxVersions()); 617 } 618 if (proto.hasStoreLimit()) { 619 get.setMaxResultsPerColumnFamily(proto.getStoreLimit()); 620 } 621 if (proto.hasStoreOffset()) { 622 get.setRowOffsetPerColumnFamily(proto.getStoreOffset()); 623 } 624 if (proto.getCfTimeRangeCount() > 0) { 625 for (HBaseProtos.ColumnFamilyTimeRange cftr : proto.getCfTimeRangeList()) { 626 TimeRange timeRange = toTimeRange(cftr.getTimeRange()); 627 get.setColumnFamilyTimeRange(cftr.getColumnFamily().toByteArray(), timeRange.getMin(), 628 timeRange.getMax()); 629 } 630 } 631 if (proto.hasTimeRange()) { 632 TimeRange timeRange = toTimeRange(proto.getTimeRange()); 633 get.setTimeRange(timeRange.getMin(), timeRange.getMax()); 634 } 635 if (proto.hasFilter()) { 636 FilterProtos.Filter filter = proto.getFilter(); 637 get.setFilter(ProtobufUtil.toFilter(filter)); 638 } 639 for (NameBytesPair attribute : proto.getAttributeList()) { 640 get.setAttribute(attribute.getName(), attribute.getValue().toByteArray()); 641 } 642 if (proto.getColumnCount() > 0) { 643 for (Column column : proto.getColumnList()) { 644 byte[] family = column.getFamily().toByteArray(); 645 if (column.getQualifierCount() > 0) { 646 for (ByteString qualifier : column.getQualifierList()) { 647 get.addColumn(family, qualifier.toByteArray()); 648 } 649 } else { 650 get.addFamily(family); 651 } 652 } 653 } 654 if (proto.hasExistenceOnly() && proto.getExistenceOnly()) { 655 get.setCheckExistenceOnly(true); 656 } 657 if (proto.hasConsistency()) { 658 get.setConsistency(toConsistency(proto.getConsistency())); 659 } 660 if (proto.hasLoadColumnFamiliesOnDemand()) { 661 get.setLoadColumnFamiliesOnDemand(proto.getLoadColumnFamiliesOnDemand()); 662 } 663 get.setQueryMetricsEnabled(proto.getQueryMetricsEnabled()); 664 return get; 665 } 666 667 public static Consistency toConsistency(ClientProtos.Consistency consistency) { 668 switch (consistency) { 669 case STRONG: 670 return Consistency.STRONG; 671 case TIMELINE: 672 return Consistency.TIMELINE; 673 default: 674 return Consistency.STRONG; 675 } 676 } 677 678 public static ClientProtos.Consistency toConsistency(Consistency consistency) { 679 switch (consistency) { 680 case STRONG: 681 return ClientProtos.Consistency.STRONG; 682 case TIMELINE: 683 return ClientProtos.Consistency.TIMELINE; 684 default: 685 return ClientProtos.Consistency.STRONG; 686 } 687 } 688 689 /** 690 * Convert a protocol buffer Mutate to a Put. 691 * @param proto The protocol buffer MutationProto to convert 692 * @return A client Put. 693 */ 694 public static Put toPut(final MutationProto proto) throws IOException { 695 return toPut(proto, null); 696 } 697 698 /** 699 * Convert a protocol buffer Mutate to a Put. 700 * @param proto The protocol buffer MutationProto to convert 701 * @param cellScanner If non-null, the Cell data that goes with this proto. 702 * @return A client Put. 703 */ 704 public static Put toPut(final MutationProto proto, final CellScanner cellScanner) 705 throws IOException { 706 // TODO: Server-side at least why do we convert back to the Client types? Why not just pb it? 707 MutationType type = proto.getMutateType(); 708 assert type == MutationType.PUT : type.name(); 709 long timestamp = proto.hasTimestamp() ? proto.getTimestamp() : HConstants.LATEST_TIMESTAMP; 710 Put put = proto.hasRow() ? new Put(proto.getRow().toByteArray(), timestamp) : 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( 716 "Cell count of " + cellCount + " but no cellScanner: " + 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 (put == null) { 725 put = new Put(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp); 726 } 727 put.add(cell); 728 } 729 } else { 730 if (put == null) { 731 throw new IllegalArgumentException("row cannot be null"); 732 } 733 // The proto has the metadata and the data itself 734 ExtendedCellBuilder cellBuilder = 735 ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY); 736 for (ColumnValue column : proto.getColumnValueList()) { 737 byte[] family = column.getFamily().toByteArray(); 738 for (QualifierValue qv : column.getQualifierValueList()) { 739 if (!qv.hasValue()) { 740 throw new DoNotRetryIOException("Missing required field: qualifier value"); 741 } 742 long ts = timestamp; 743 if (qv.hasTimestamp()) { 744 ts = qv.getTimestamp(); 745 } 746 byte[] allTagsBytes; 747 if (qv.hasTags()) { 748 allTagsBytes = qv.getTags().toByteArray(); 749 if (qv.hasDeleteType()) { 750 put.add(cellBuilder.clear().setRow(proto.getRow().toByteArray()).setFamily(family) 751 .setQualifier(qv.hasQualifier() ? qv.getQualifier().toByteArray() : null) 752 .setTimestamp(ts).setType(fromDeleteType(qv.getDeleteType()).getCode()) 753 .setTags(allTagsBytes).build()); 754 } else { 755 put.add(cellBuilder.clear().setRow(put.getRow()).setFamily(family) 756 .setQualifier(qv.hasQualifier() ? qv.getQualifier().toByteArray() : null) 757 .setTimestamp(ts).setType(Cell.Type.Put) 758 .setValue(qv.hasValue() ? qv.getValue().toByteArray() : null).setTags(allTagsBytes) 759 .build()); 760 } 761 } else { 762 if (qv.hasDeleteType()) { 763 put.add(cellBuilder.clear().setRow(put.getRow()).setFamily(family) 764 .setQualifier(qv.hasQualifier() ? qv.getQualifier().toByteArray() : null) 765 .setTimestamp(ts).setType(fromDeleteType(qv.getDeleteType()).getCode()).build()); 766 } else { 767 put.add(cellBuilder.clear().setRow(put.getRow()).setFamily(family) 768 .setQualifier(qv.hasQualifier() ? qv.getQualifier().toByteArray() : null) 769 .setTimestamp(ts).setType(Cell.Type.Put) 770 .setValue(qv.hasValue() ? qv.getValue().toByteArray() : null).build()); 771 } 772 } 773 } 774 } 775 } 776 put.setDurability(toDurability(proto.getDurability())); 777 for (NameBytesPair attribute : proto.getAttributeList()) { 778 put.setAttribute(attribute.getName(), attribute.getValue().toByteArray()); 779 } 780 return put; 781 } 782 783 /** 784 * Convert a protocol buffer Mutate to a Delete 785 * @param proto the protocol buffer Mutate to convert 786 * @return the converted client Delete 787 */ 788 public static Delete toDelete(final MutationProto proto) throws IOException { 789 return toDelete(proto, null); 790 } 791 792 /** 793 * Convert a protocol buffer Mutate to a Delete 794 * @param proto the protocol buffer Mutate to convert 795 * @param cellScanner if non-null, the data that goes with this delete. 796 * @return the converted client Delete 797 */ 798 public static Delete toDelete(final MutationProto proto, final CellScanner cellScanner) 799 throws IOException { 800 MutationType type = proto.getMutateType(); 801 assert type == MutationType.DELETE : type.name(); 802 long timestamp = proto.hasTimestamp() ? proto.getTimestamp() : HConstants.LATEST_TIMESTAMP; 803 Delete delete = proto.hasRow() ? new Delete(proto.getRow().toByteArray(), timestamp) : null; 804 int cellCount = proto.hasAssociatedCellCount() ? proto.getAssociatedCellCount() : 0; 805 if (cellCount > 0) { 806 // The proto has metadata only and the data is separate to be found in the cellScanner. 807 if (cellScanner == null) { 808 // TextFormat should be fine for a Delete since it carries no data, just coordinates. 809 throw new DoNotRetryIOException("Cell count of " + cellCount + " but no cellScanner: " 810 + TextFormat.shortDebugString(proto)); 811 } 812 for (int i = 0; i < cellCount; i++) { 813 if (!cellScanner.advance()) { 814 // TextFormat should be fine for a Delete since it carries no data, just coordinates. 815 throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i 816 + " no cell returned: " + TextFormat.shortDebugString(proto)); 817 } 818 Cell cell = cellScanner.current(); 819 if (delete == null) { 820 delete = 821 new Delete(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength(), timestamp); 822 } 823 delete.add(cell); 824 } 825 } else { 826 if (delete == null) { 827 throw new IllegalArgumentException("row cannot be null"); 828 } 829 for (ColumnValue column : proto.getColumnValueList()) { 830 byte[] family = column.getFamily().toByteArray(); 831 for (QualifierValue qv : column.getQualifierValueList()) { 832 DeleteType deleteType = qv.getDeleteType(); 833 byte[] qualifier = null; 834 if (qv.hasQualifier()) { 835 qualifier = qv.getQualifier().toByteArray(); 836 } 837 long ts = cellTimestampOrLatest(qv); 838 if (deleteType == DeleteType.DELETE_ONE_VERSION) { 839 delete.addColumn(family, qualifier, ts); 840 } else if (deleteType == DeleteType.DELETE_MULTIPLE_VERSIONS) { 841 delete.addColumns(family, qualifier, ts); 842 } else if (deleteType == DeleteType.DELETE_FAMILY_VERSION) { 843 delete.addFamilyVersion(family, ts); 844 } else { 845 delete.addFamily(family, ts); 846 } 847 } 848 } 849 } 850 delete.setDurability(toDurability(proto.getDurability())); 851 for (NameBytesPair attribute : proto.getAttributeList()) { 852 delete.setAttribute(attribute.getName(), attribute.getValue().toByteArray()); 853 } 854 return delete; 855 } 856 857 @FunctionalInterface 858 private interface ConsumerWithException<T, U> { 859 void accept(T t, U u) throws IOException; 860 } 861 862 private static <T extends Mutation> T toDelta(Function<Bytes, T> supplier, 863 ConsumerWithException<T, Cell> consumer, final MutationProto proto, 864 final CellScanner cellScanner) throws IOException { 865 byte[] row = proto.hasRow() ? proto.getRow().toByteArray() : null; 866 T mutation = row == null ? null : supplier.apply(new Bytes(row)); 867 int cellCount = proto.hasAssociatedCellCount() ? proto.getAssociatedCellCount() : 0; 868 if (cellCount > 0) { 869 // The proto has metadata only and the data is separate to be found in the cellScanner. 870 if (cellScanner == null) { 871 throw new DoNotRetryIOException( 872 "Cell count of " + cellCount + " but no cellScanner: " + toShortString(proto)); 873 } 874 for (int i = 0; i < cellCount; i++) { 875 if (!cellScanner.advance()) { 876 throw new DoNotRetryIOException("Cell count of " + cellCount + " but at index " + i 877 + " no cell returned: " + toShortString(proto)); 878 } 879 Cell cell = cellScanner.current(); 880 if (mutation == null) { 881 mutation = 882 supplier.apply(new Bytes(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength())); 883 } 884 consumer.accept(mutation, cell); 885 } 886 } else { 887 if (mutation == null) { 888 throw new IllegalArgumentException("row cannot be null"); 889 } 890 for (ColumnValue column : proto.getColumnValueList()) { 891 byte[] family = column.getFamily().toByteArray(); 892 for (QualifierValue qv : column.getQualifierValueList()) { 893 byte[] qualifier = qv.getQualifier().toByteArray(); 894 if (!qv.hasValue()) { 895 throw new DoNotRetryIOException("Missing required field: qualifier value"); 896 } 897 byte[] value = qv.getValue().toByteArray(); 898 byte[] tags = null; 899 if (qv.hasTags()) { 900 tags = qv.getTags().toByteArray(); 901 } 902 consumer.accept(mutation, 903 ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY) 904 .setRow(mutation.getRow()).setFamily(family).setQualifier(qualifier) 905 .setTimestamp(cellTimestampOrLatest(qv)).setType(KeyValue.Type.Put.getCode()) 906 .setValue(value).setTags(tags).build()); 907 } 908 } 909 } 910 mutation.setDurability(toDurability(proto.getDurability())); 911 for (NameBytesPair attribute : proto.getAttributeList()) { 912 mutation.setAttribute(attribute.getName(), attribute.getValue().toByteArray()); 913 } 914 return mutation; 915 } 916 917 private static long cellTimestampOrLatest(QualifierValue cell) { 918 if (cell.hasTimestamp()) { 919 return cell.getTimestamp(); 920 } else { 921 return HConstants.LATEST_TIMESTAMP; 922 } 923 } 924 925 /** 926 * Convert a protocol buffer Mutate to an Append 927 * @param proto the protocol buffer Mutate to convert 928 * @return the converted client Append 929 */ 930 public static Append toAppend(final MutationProto proto, final CellScanner cellScanner) 931 throws IOException { 932 MutationType type = proto.getMutateType(); 933 assert type == MutationType.APPEND : type.name(); 934 Append append = toDelta((Bytes row) -> new Append(row.get(), row.getOffset(), row.getLength()), 935 Append::add, proto, cellScanner); 936 if (proto.hasTimeRange()) { 937 TimeRange timeRange = toTimeRange(proto.getTimeRange()); 938 append.setTimeRange(timeRange.getMin(), timeRange.getMax()); 939 } 940 return append; 941 } 942 943 /** 944 * Convert a protocol buffer Mutate to an Increment 945 * @param proto the protocol buffer Mutate to convert 946 * @return the converted client Increment 947 */ 948 public static Increment toIncrement(final MutationProto proto, final CellScanner cellScanner) 949 throws IOException { 950 MutationType type = proto.getMutateType(); 951 assert type == MutationType.INCREMENT : type.name(); 952 Increment increment = 953 toDelta((Bytes row) -> new Increment(row.get(), row.getOffset(), row.getLength()), 954 Increment::add, proto, cellScanner); 955 if (proto.hasTimeRange()) { 956 TimeRange timeRange = toTimeRange(proto.getTimeRange()); 957 increment.setTimeRange(timeRange.getMin(), timeRange.getMax()); 958 } 959 return increment; 960 } 961 962 /** 963 * Convert a MutateRequest to Mutation 964 * @param proto the protocol buffer Mutate to convert 965 * @return the converted Mutation 966 */ 967 public static Mutation toMutation(final MutationProto proto) throws IOException { 968 MutationType type = proto.getMutateType(); 969 if (type == MutationType.INCREMENT) { 970 return toIncrement(proto, null); 971 } 972 if (type == MutationType.APPEND) { 973 return toAppend(proto, null); 974 } 975 if (type == MutationType.DELETE) { 976 return toDelete(proto, null); 977 } 978 if (type == MutationType.PUT) { 979 return toPut(proto, null); 980 } 981 throw new IOException("Unknown mutation type " + type); 982 } 983 984 public static ClientProtos.Scan.ReadType toReadType(Scan.ReadType readType) { 985 switch (readType) { 986 case DEFAULT: 987 return ClientProtos.Scan.ReadType.DEFAULT; 988 case STREAM: 989 return ClientProtos.Scan.ReadType.STREAM; 990 case PREAD: 991 return ClientProtos.Scan.ReadType.PREAD; 992 default: 993 throw new IllegalArgumentException("Unknown ReadType: " + readType); 994 } 995 } 996 997 public static Scan.ReadType toReadType(ClientProtos.Scan.ReadType readType) { 998 switch (readType) { 999 case DEFAULT: 1000 return Scan.ReadType.DEFAULT; 1001 case STREAM: 1002 return Scan.ReadType.STREAM; 1003 case PREAD: 1004 return Scan.ReadType.PREAD; 1005 default: 1006 throw new IllegalArgumentException("Unknown ReadType: " + readType); 1007 } 1008 } 1009 1010 /** 1011 * Convert a client Scan to a protocol buffer Scan 1012 * @param scan the client Scan to convert 1013 * @return the converted protocol buffer Scan 1014 */ 1015 public static ClientProtos.Scan toScan(final Scan scan) throws IOException { 1016 ClientProtos.Scan.Builder scanBuilder = ClientProtos.Scan.newBuilder(); 1017 scanBuilder.setCacheBlocks(scan.getCacheBlocks()); 1018 if (scan.getBatch() > 0) { 1019 scanBuilder.setBatchSize(scan.getBatch()); 1020 } 1021 if (scan.getMaxResultSize() > 0) { 1022 scanBuilder.setMaxResultSize(scan.getMaxResultSize()); 1023 } 1024 if (scan.getAllowPartialResults()) { 1025 scanBuilder.setAllowPartialResults(scan.getAllowPartialResults()); 1026 } 1027 Boolean loadColumnFamiliesOnDemand = scan.getLoadColumnFamiliesOnDemandValue(); 1028 if (loadColumnFamiliesOnDemand != null) { 1029 scanBuilder.setLoadColumnFamiliesOnDemand(loadColumnFamiliesOnDemand); 1030 } 1031 scanBuilder.setMaxVersions(scan.getMaxVersions()); 1032 scan.getColumnFamilyTimeRange().forEach((cf, timeRange) -> { 1033 scanBuilder.addCfTimeRange(HBaseProtos.ColumnFamilyTimeRange.newBuilder() 1034 .setColumnFamily(UnsafeByteOperations.unsafeWrap(cf)).setTimeRange(toTimeRange(timeRange)) 1035 .build()); 1036 }); 1037 scanBuilder.setTimeRange(ProtobufUtil.toTimeRange(scan.getTimeRange())); 1038 Map<String, byte[]> attributes = scan.getAttributesMap(); 1039 if (!attributes.isEmpty()) { 1040 NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder(); 1041 for (Map.Entry<String, byte[]> attribute : attributes.entrySet()) { 1042 attributeBuilder.setName(attribute.getKey()); 1043 attributeBuilder.setValue(UnsafeByteOperations.unsafeWrap(attribute.getValue())); 1044 scanBuilder.addAttribute(attributeBuilder.build()); 1045 } 1046 } 1047 byte[] startRow = scan.getStartRow(); 1048 if (startRow != null && startRow.length > 0) { 1049 scanBuilder.setStartRow(UnsafeByteOperations.unsafeWrap(startRow)); 1050 } 1051 byte[] stopRow = scan.getStopRow(); 1052 if (stopRow != null && stopRow.length > 0) { 1053 scanBuilder.setStopRow(UnsafeByteOperations.unsafeWrap(stopRow)); 1054 } 1055 if (scan.hasFilter()) { 1056 scanBuilder.setFilter(ProtobufUtil.toFilter(scan.getFilter())); 1057 } 1058 if (scan.hasFamilies()) { 1059 Column.Builder columnBuilder = Column.newBuilder(); 1060 for (Map.Entry<byte[], NavigableSet<byte[]>> family : scan.getFamilyMap().entrySet()) { 1061 columnBuilder.setFamily(UnsafeByteOperations.unsafeWrap(family.getKey())); 1062 NavigableSet<byte[]> qualifiers = family.getValue(); 1063 columnBuilder.clearQualifier(); 1064 if (qualifiers != null && qualifiers.size() > 0) { 1065 for (byte[] qualifier : qualifiers) { 1066 columnBuilder.addQualifier(UnsafeByteOperations.unsafeWrap(qualifier)); 1067 } 1068 } 1069 scanBuilder.addColumn(columnBuilder.build()); 1070 } 1071 } 1072 if (scan.getMaxResultsPerColumnFamily() >= 0) { 1073 scanBuilder.setStoreLimit(scan.getMaxResultsPerColumnFamily()); 1074 } 1075 if (scan.getRowOffsetPerColumnFamily() > 0) { 1076 scanBuilder.setStoreOffset(scan.getRowOffsetPerColumnFamily()); 1077 } 1078 if (scan.isReversed()) { 1079 scanBuilder.setReversed(scan.isReversed()); 1080 } 1081 if (scan.getConsistency() == Consistency.TIMELINE) { 1082 scanBuilder.setConsistency(toConsistency(scan.getConsistency())); 1083 } 1084 if (scan.getCaching() > 0) { 1085 scanBuilder.setCaching(scan.getCaching()); 1086 } 1087 long mvccReadPoint = ClientInternalHelper.getMvccReadPoint(scan); 1088 if (mvccReadPoint > 0) { 1089 scanBuilder.setMvccReadPoint(mvccReadPoint); 1090 } 1091 if (!scan.includeStartRow()) { 1092 scanBuilder.setIncludeStartRow(false); 1093 } 1094 scanBuilder.setIncludeStopRow(scan.includeStopRow()); 1095 if (scan.getReadType() != Scan.ReadType.DEFAULT) { 1096 scanBuilder.setReadType(toReadType(scan.getReadType())); 1097 } 1098 if (scan.isNeedCursorResult()) { 1099 scanBuilder.setNeedCursorResult(true); 1100 } 1101 scanBuilder.setQueryMetricsEnabled(scan.isQueryMetricsEnabled()); 1102 return scanBuilder.build(); 1103 } 1104 1105 /** 1106 * Convert a protocol buffer Scan to a client Scan 1107 * @param proto the protocol buffer Scan to convert 1108 * @return the converted client Scan 1109 */ 1110 public static Scan toScan(final ClientProtos.Scan proto) throws IOException { 1111 byte[] startRow = HConstants.EMPTY_START_ROW; 1112 byte[] stopRow = HConstants.EMPTY_END_ROW; 1113 boolean includeStartRow = true; 1114 boolean includeStopRow = false; 1115 if (proto.hasStartRow()) { 1116 startRow = proto.getStartRow().toByteArray(); 1117 } 1118 if (proto.hasStopRow()) { 1119 stopRow = proto.getStopRow().toByteArray(); 1120 } 1121 if (proto.hasIncludeStartRow()) { 1122 includeStartRow = proto.getIncludeStartRow(); 1123 } 1124 if (proto.hasIncludeStopRow()) { 1125 includeStopRow = proto.getIncludeStopRow(); 1126 } else { 1127 // old client without this flag, we should consider start=end as a get. 1128 if (ClientUtil.areScanStartRowAndStopRowEqual(startRow, stopRow)) { 1129 includeStopRow = true; 1130 } 1131 } 1132 Scan scan = 1133 new Scan().withStartRow(startRow, includeStartRow).withStopRow(stopRow, includeStopRow); 1134 if (proto.hasCacheBlocks()) { 1135 scan.setCacheBlocks(proto.getCacheBlocks()); 1136 } 1137 if (proto.hasMaxVersions()) { 1138 scan.readVersions(proto.getMaxVersions()); 1139 } 1140 if (proto.hasStoreLimit()) { 1141 scan.setMaxResultsPerColumnFamily(proto.getStoreLimit()); 1142 } 1143 if (proto.hasStoreOffset()) { 1144 scan.setRowOffsetPerColumnFamily(proto.getStoreOffset()); 1145 } 1146 if (proto.hasLoadColumnFamiliesOnDemand()) { 1147 scan.setLoadColumnFamiliesOnDemand(proto.getLoadColumnFamiliesOnDemand()); 1148 } 1149 if (proto.getCfTimeRangeCount() > 0) { 1150 for (HBaseProtos.ColumnFamilyTimeRange cftr : proto.getCfTimeRangeList()) { 1151 TimeRange timeRange = toTimeRange(cftr.getTimeRange()); 1152 scan.setColumnFamilyTimeRange(cftr.getColumnFamily().toByteArray(), timeRange.getMin(), 1153 timeRange.getMax()); 1154 } 1155 } 1156 if (proto.hasTimeRange()) { 1157 TimeRange timeRange = toTimeRange(proto.getTimeRange()); 1158 scan.setTimeRange(timeRange.getMin(), timeRange.getMax()); 1159 } 1160 if (proto.hasFilter()) { 1161 FilterProtos.Filter filter = proto.getFilter(); 1162 scan.setFilter(ProtobufUtil.toFilter(filter)); 1163 } 1164 if (proto.hasBatchSize()) { 1165 scan.setBatch(proto.getBatchSize()); 1166 } 1167 if (proto.hasMaxResultSize()) { 1168 scan.setMaxResultSize(proto.getMaxResultSize()); 1169 } 1170 if (proto.hasAllowPartialResults()) { 1171 scan.setAllowPartialResults(proto.getAllowPartialResults()); 1172 } 1173 for (NameBytesPair attribute : proto.getAttributeList()) { 1174 scan.setAttribute(attribute.getName(), attribute.getValue().toByteArray()); 1175 } 1176 if (proto.getColumnCount() > 0) { 1177 for (Column column : proto.getColumnList()) { 1178 byte[] family = column.getFamily().toByteArray(); 1179 if (column.getQualifierCount() > 0) { 1180 for (ByteString qualifier : column.getQualifierList()) { 1181 scan.addColumn(family, qualifier.toByteArray()); 1182 } 1183 } else { 1184 scan.addFamily(family); 1185 } 1186 } 1187 } 1188 if (proto.hasReversed()) { 1189 scan.setReversed(proto.getReversed()); 1190 } 1191 if (proto.hasConsistency()) { 1192 scan.setConsistency(toConsistency(proto.getConsistency())); 1193 } 1194 if (proto.hasCaching()) { 1195 scan.setCaching(proto.getCaching()); 1196 } 1197 if (proto.hasMvccReadPoint()) { 1198 ClientInternalHelper.setMvccReadPoint(scan, proto.getMvccReadPoint()); 1199 } 1200 if (proto.hasReadType()) { 1201 scan.setReadType(toReadType(proto.getReadType())); 1202 } 1203 if (proto.getNeedCursorResult()) { 1204 scan.setNeedCursorResult(true); 1205 } 1206 scan.setQueryMetricsEnabled(proto.getQueryMetricsEnabled()); 1207 return scan; 1208 } 1209 1210 public static ClientProtos.Cursor toCursor(Cursor cursor) { 1211 ClientProtos.Cursor.Builder builder = ClientProtos.Cursor.newBuilder(); 1212 ClientProtos.Cursor.newBuilder().setRow(ByteString.copyFrom(cursor.getRow())); 1213 return builder.build(); 1214 } 1215 1216 public static ClientProtos.Cursor toCursor(Cell cell) { 1217 return ClientProtos.Cursor.newBuilder() 1218 .setRow(ByteString.copyFrom(cell.getRowArray(), cell.getRowOffset(), cell.getRowLength())) 1219 .build(); 1220 } 1221 1222 public static Cursor toCursor(ClientProtos.Cursor cursor) { 1223 return ClientUtil.createCursor(cursor.getRow().toByteArray()); 1224 } 1225 1226 /** 1227 * Create a protocol buffer Get based on a client Get. 1228 * @param get the client Get 1229 * @return a protocol buffer Get 1230 */ 1231 public static ClientProtos.Get toGet(final Get get) throws IOException { 1232 ClientProtos.Get.Builder builder = ClientProtos.Get.newBuilder(); 1233 builder.setRow(UnsafeByteOperations.unsafeWrap(get.getRow())); 1234 builder.setCacheBlocks(get.getCacheBlocks()); 1235 builder.setMaxVersions(get.getMaxVersions()); 1236 if (get.getFilter() != null) { 1237 builder.setFilter(ProtobufUtil.toFilter(get.getFilter())); 1238 } 1239 get.getColumnFamilyTimeRange().forEach((cf, timeRange) -> { 1240 builder.addCfTimeRange(HBaseProtos.ColumnFamilyTimeRange.newBuilder() 1241 .setColumnFamily(UnsafeByteOperations.unsafeWrap(cf)).setTimeRange(toTimeRange(timeRange)) 1242 .build()); 1243 }); 1244 builder.setTimeRange(ProtobufUtil.toTimeRange(get.getTimeRange())); 1245 Map<String, byte[]> attributes = get.getAttributesMap(); 1246 if (!attributes.isEmpty()) { 1247 NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder(); 1248 for (Map.Entry<String, byte[]> attribute : attributes.entrySet()) { 1249 attributeBuilder.setName(attribute.getKey()); 1250 attributeBuilder.setValue(UnsafeByteOperations.unsafeWrap(attribute.getValue())); 1251 builder.addAttribute(attributeBuilder.build()); 1252 } 1253 } 1254 if (get.hasFamilies()) { 1255 Column.Builder columnBuilder = Column.newBuilder(); 1256 Map<byte[], NavigableSet<byte[]>> families = get.getFamilyMap(); 1257 for (Map.Entry<byte[], NavigableSet<byte[]>> family : families.entrySet()) { 1258 NavigableSet<byte[]> qualifiers = family.getValue(); 1259 columnBuilder.setFamily(UnsafeByteOperations.unsafeWrap(family.getKey())); 1260 columnBuilder.clearQualifier(); 1261 if (qualifiers != null && qualifiers.size() > 0) { 1262 for (byte[] qualifier : qualifiers) { 1263 columnBuilder.addQualifier(UnsafeByteOperations.unsafeWrap(qualifier)); 1264 } 1265 } 1266 builder.addColumn(columnBuilder.build()); 1267 } 1268 } 1269 if (get.getMaxResultsPerColumnFamily() >= 0) { 1270 builder.setStoreLimit(get.getMaxResultsPerColumnFamily()); 1271 } 1272 if (get.getRowOffsetPerColumnFamily() > 0) { 1273 builder.setStoreOffset(get.getRowOffsetPerColumnFamily()); 1274 } 1275 if (get.isCheckExistenceOnly()) { 1276 builder.setExistenceOnly(true); 1277 } 1278 if (get.getConsistency() != null && get.getConsistency() != Consistency.STRONG) { 1279 builder.setConsistency(toConsistency(get.getConsistency())); 1280 } 1281 1282 Boolean loadColumnFamiliesOnDemand = get.getLoadColumnFamiliesOnDemandValue(); 1283 if (loadColumnFamiliesOnDemand != null) { 1284 builder.setLoadColumnFamiliesOnDemand(loadColumnFamiliesOnDemand); 1285 } 1286 builder.setQueryMetricsEnabled(get.isQueryMetricsEnabled()); 1287 return builder.build(); 1288 } 1289 1290 public static MutationProto toMutation(final MutationType type, final Mutation mutation) 1291 throws IOException { 1292 return toMutation(type, mutation, HConstants.NO_NONCE); 1293 } 1294 1295 /** 1296 * Create a protocol buffer Mutate based on a client Mutation 1297 * @return a protobuf'd Mutation 1298 */ 1299 public static MutationProto toMutation(final MutationType type, final Mutation mutation, 1300 final long nonce) throws IOException { 1301 return toMutation(type, mutation, MutationProto.newBuilder(), nonce); 1302 } 1303 1304 public static MutationProto toMutation(final MutationType type, final Mutation mutation, 1305 MutationProto.Builder builder) throws IOException { 1306 return toMutation(type, mutation, builder, HConstants.NO_NONCE); 1307 } 1308 1309 public static MutationProto toMutation(final MutationType type, final Mutation mutation, 1310 MutationProto.Builder builder, long nonce) throws IOException { 1311 builder = getMutationBuilderAndSetCommonFields(type, mutation, builder); 1312 if (nonce != HConstants.NO_NONCE) { 1313 builder.setNonce(nonce); 1314 } 1315 if (type == MutationType.INCREMENT) { 1316 builder.setTimeRange(ProtobufUtil.toTimeRange(((Increment) mutation).getTimeRange())); 1317 } 1318 if (type == MutationType.APPEND) { 1319 builder.setTimeRange(ProtobufUtil.toTimeRange(((Append) mutation).getTimeRange())); 1320 } 1321 ColumnValue.Builder columnBuilder = ColumnValue.newBuilder(); 1322 QualifierValue.Builder valueBuilder = QualifierValue.newBuilder(); 1323 for (Map.Entry<byte[], List<ExtendedCell>> family : ClientInternalHelper 1324 .getExtendedFamilyCellMap(mutation).entrySet()) { 1325 columnBuilder.clear(); 1326 columnBuilder.setFamily(UnsafeByteOperations.unsafeWrap(family.getKey())); 1327 for (ExtendedCell cell : family.getValue()) { 1328 valueBuilder.clear(); 1329 valueBuilder.setQualifier(UnsafeByteOperations.unsafeWrap(cell.getQualifierArray(), 1330 cell.getQualifierOffset(), cell.getQualifierLength())); 1331 valueBuilder.setValue(UnsafeByteOperations.unsafeWrap(cell.getValueArray(), 1332 cell.getValueOffset(), cell.getValueLength())); 1333 valueBuilder.setTimestamp(cell.getTimestamp()); 1334 if (type == MutationType.DELETE || (type == MutationType.PUT && CellUtil.isDelete(cell))) { 1335 KeyValue.Type keyValueType = KeyValue.Type.codeToType(cell.getTypeByte()); 1336 valueBuilder.setDeleteType(toDeleteType(keyValueType)); 1337 } 1338 columnBuilder.addQualifierValue(valueBuilder.build()); 1339 } 1340 builder.addColumnValue(columnBuilder.build()); 1341 } 1342 return builder.build(); 1343 } 1344 1345 /** 1346 * Create a protocol buffer MutationProto based on a client Mutation. Does NOT include data. 1347 * Understanding is that the Cell will be transported other than via protobuf. 1348 * @return a protobuf'd Mutation 1349 */ 1350 public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation, 1351 final MutationProto.Builder builder) throws IOException { 1352 return toMutationNoData(type, mutation, builder, HConstants.NO_NONCE); 1353 } 1354 1355 /** 1356 * Create a protocol buffer MutationProto based on a client Mutation. Does NOT include data. 1357 * Understanding is that the Cell will be transported other than via protobuf. 1358 * @return a protobuf'd Mutation 1359 */ 1360 public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation) 1361 throws IOException { 1362 MutationProto.Builder builder = MutationProto.newBuilder(); 1363 return toMutationNoData(type, mutation, builder); 1364 } 1365 1366 public static MutationProto toMutationNoData(final MutationType type, final Mutation mutation, 1367 final MutationProto.Builder builder, long nonce) throws IOException { 1368 getMutationBuilderAndSetCommonFields(type, mutation, builder); 1369 builder.setAssociatedCellCount(mutation.size()); 1370 if (mutation instanceof Increment) { 1371 builder.setTimeRange(ProtobufUtil.toTimeRange(((Increment) mutation).getTimeRange())); 1372 } 1373 if (mutation instanceof Append) { 1374 builder.setTimeRange(ProtobufUtil.toTimeRange(((Append) mutation).getTimeRange())); 1375 } 1376 if (nonce != HConstants.NO_NONCE) { 1377 builder.setNonce(nonce); 1378 } 1379 return builder.build(); 1380 } 1381 1382 /** 1383 * Code shared by {@link #toMutation(MutationType, Mutation)} and 1384 * {@link #toMutationNoData(MutationType, Mutation)} 1385 * @return A partly-filled out protobuf'd Mutation. 1386 */ 1387 private static MutationProto.Builder getMutationBuilderAndSetCommonFields(final MutationType type, 1388 final Mutation mutation, MutationProto.Builder builder) { 1389 builder.setRow(UnsafeByteOperations.unsafeWrap(mutation.getRow())); 1390 builder.setMutateType(type); 1391 builder.setDurability(toDurability(mutation.getDurability())); 1392 builder.setTimestamp(mutation.getTimestamp()); 1393 Map<String, byte[]> attributes = mutation.getAttributesMap(); 1394 if (!attributes.isEmpty()) { 1395 NameBytesPair.Builder attributeBuilder = NameBytesPair.newBuilder(); 1396 for (Map.Entry<String, byte[]> attribute : attributes.entrySet()) { 1397 attributeBuilder.setName(attribute.getKey()); 1398 attributeBuilder.setValue(UnsafeByteOperations.unsafeWrap(attribute.getValue())); 1399 builder.addAttribute(attributeBuilder.build()); 1400 } 1401 } 1402 return builder; 1403 } 1404 1405 /** 1406 * Convert a client Result to a protocol buffer Result 1407 * @param result the client Result to convert 1408 * @return the converted protocol buffer Result 1409 */ 1410 public static ClientProtos.Result toResult(final Result result) { 1411 return toResult(result, false); 1412 } 1413 1414 /** 1415 * Convert a client Result to a protocol buffer Result 1416 * @param result the client Result to convert 1417 * @param encodeTags whether to includeTags in converted protobuf result or not When @encodeTags 1418 * is set to true, it will return all the tags in the response. These tags may 1419 * contain some sensitive data like acl permissions, etc. Only the tools like 1420 * Export, Import which needs to take backup needs to set it to true so that 1421 * cell tags are persisted in backup. Refer to HBASE-25246 for more context. 1422 * @return the converted protocol buffer Result 1423 */ 1424 public static ClientProtos.Result toResult(final Result result, boolean encodeTags) { 1425 if (result.getExists() != null) { 1426 return toResult(result.getExists(), result.isStale()); 1427 } 1428 1429 ExtendedCell[] cells = ClientInternalHelper.getExtendedRawCells(result); 1430 if (cells == null || cells.length == 0) { 1431 return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB; 1432 } 1433 1434 ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder(); 1435 for (ExtendedCell c : cells) { 1436 builder.addCell(toCell(c, encodeTags)); 1437 } 1438 1439 builder.setStale(result.isStale()); 1440 builder.setPartial(result.mayHaveMoreCellsInRow()); 1441 1442 if (result.getMetrics() != null) { 1443 builder.setMetrics(toQueryMetrics(result.getMetrics())); 1444 } 1445 1446 return builder.build(); 1447 } 1448 1449 /** 1450 * Convert a client Result to a protocol buffer Result 1451 * @param existence the client existence to send 1452 * @return the converted protocol buffer Result 1453 */ 1454 public static ClientProtos.Result toResult(final boolean existence, boolean stale) { 1455 if (stale) { 1456 return existence ? EMPTY_RESULT_PB_EXISTS_TRUE_STALE : EMPTY_RESULT_PB_EXISTS_FALSE_STALE; 1457 } else { 1458 return existence ? EMPTY_RESULT_PB_EXISTS_TRUE : EMPTY_RESULT_PB_EXISTS_FALSE; 1459 } 1460 } 1461 1462 /** 1463 * Convert a client Result to a protocol buffer Result. The pb Result does not include the Cell 1464 * data. That is for transport otherwise. 1465 * @param result the client Result to convert 1466 * @return the converted protocol buffer Result 1467 */ 1468 public static ClientProtos.Result toResultNoData(final Result result) { 1469 if (result.getExists() != null) return toResult(result.getExists(), result.isStale()); 1470 int size = result.size(); 1471 if (size == 0) return result.isStale() ? EMPTY_RESULT_PB_STALE : EMPTY_RESULT_PB; 1472 ClientProtos.Result.Builder builder = ClientProtos.Result.newBuilder(); 1473 builder.setAssociatedCellCount(size); 1474 builder.setStale(result.isStale()); 1475 if (result.getMetrics() != null) { 1476 builder.setMetrics(toQueryMetrics(result.getMetrics())); 1477 } 1478 return builder.build(); 1479 } 1480 1481 /** 1482 * Convert a protocol buffer Result to a client Result 1483 * @param proto the protocol buffer Result to convert 1484 * @return the converted client Result 1485 */ 1486 public static Result toResult(final ClientProtos.Result proto) { 1487 return toResult(proto, false); 1488 } 1489 1490 /** 1491 * Convert a protocol buffer Result to a client Result 1492 * @param proto the protocol buffer Result to convert 1493 * @param decodeTags whether to decode tags into converted client Result When @decodeTags is set 1494 * to true, it will decode all the tags from the response. These tags may 1495 * contain some sensitive data like acl permissions, etc. Only the tools like 1496 * Export, Import which needs to take backup needs to set it to true so that 1497 * cell tags are persisted in backup. Refer to HBASE-25246 for more context. 1498 * @return the converted client Result 1499 */ 1500 public static Result toResult(final ClientProtos.Result proto, boolean decodeTags) { 1501 if (proto.hasExists()) { 1502 if (proto.getStale()) { 1503 return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE : EMPTY_RESULT_EXISTS_FALSE_STALE; 1504 } 1505 return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE; 1506 } 1507 1508 List<CellProtos.Cell> values = proto.getCellList(); 1509 if (values.isEmpty()) { 1510 return proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT; 1511 } 1512 1513 List<Cell> cells = new ArrayList<>(values.size()); 1514 ExtendedCellBuilder builder = ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY); 1515 for (CellProtos.Cell c : values) { 1516 cells.add(toCell(builder, c, decodeTags)); 1517 } 1518 Result r = Result.create(cells, null, proto.getStale(), proto.getPartial()); 1519 if (proto.hasMetrics()) { 1520 r.setMetrics(toQueryMetrics(proto.getMetrics())); 1521 } 1522 return r; 1523 } 1524 1525 /** 1526 * Convert a protocol buffer Result to a client Result 1527 * @param proto the protocol buffer Result to convert 1528 * @param scanner Optional cell scanner. 1529 * @return the converted client Result 1530 */ 1531 public static Result toResult(final ClientProtos.Result proto, final CellScanner scanner) 1532 throws IOException { 1533 List<CellProtos.Cell> values = proto.getCellList(); 1534 1535 if (proto.hasExists()) { 1536 if ( 1537 (values != null && !values.isEmpty()) 1538 || (proto.hasAssociatedCellCount() && proto.getAssociatedCellCount() > 0) 1539 ) { 1540 throw new IllegalArgumentException("bad proto: exists with cells is no allowed " + proto); 1541 } 1542 if (proto.getStale()) { 1543 return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE_STALE : EMPTY_RESULT_EXISTS_FALSE_STALE; 1544 } 1545 return proto.getExists() ? EMPTY_RESULT_EXISTS_TRUE : EMPTY_RESULT_EXISTS_FALSE; 1546 } 1547 1548 // TODO: Unit test that has some Cells in scanner and some in the proto. 1549 List<Cell> cells = null; 1550 if (proto.hasAssociatedCellCount()) { 1551 int count = proto.getAssociatedCellCount(); 1552 cells = new ArrayList<>(count + values.size()); 1553 for (int i = 0; i < count; i++) { 1554 if (!scanner.advance()) throw new IOException("Failed get " + i + " of " + count); 1555 cells.add(scanner.current()); 1556 } 1557 } 1558 1559 if (!values.isEmpty()) { 1560 if (cells == null) cells = new ArrayList<>(values.size()); 1561 ExtendedCellBuilder builder = ExtendedCellBuilderFactory.create(CellBuilderType.SHALLOW_COPY); 1562 for (CellProtos.Cell c : values) { 1563 cells.add(toCell(builder, c, false)); 1564 } 1565 } 1566 1567 Result r = (cells == null || cells.isEmpty()) 1568 ? (proto.getStale() ? EMPTY_RESULT_STALE : EMPTY_RESULT) 1569 : Result.create(cells, null, proto.getStale()); 1570 1571 if (proto.hasMetrics()) { 1572 r.setMetrics(toQueryMetrics(proto.getMetrics())); 1573 } 1574 1575 return r; 1576 } 1577 1578 /** 1579 * Convert a ByteArrayComparable to a protocol buffer Comparator 1580 * @param comparator the ByteArrayComparable to convert 1581 * @return the converted protocol buffer Comparator 1582 */ 1583 public static ComparatorProtos.Comparator toComparator(ByteArrayComparable comparator) { 1584 ComparatorProtos.Comparator.Builder builder = ComparatorProtos.Comparator.newBuilder(); 1585 builder.setName(comparator.getClass().getName()); 1586 builder.setSerializedComparator(UnsafeByteOperations.unsafeWrap(comparator.toByteArray())); 1587 return builder.build(); 1588 } 1589 1590 /** 1591 * Convert a protocol buffer Comparator to a ByteArrayComparable 1592 * @param proto the protocol buffer Comparator to convert 1593 * @return the converted ByteArrayComparable 1594 */ 1595 @SuppressWarnings("unchecked") 1596 public static ByteArrayComparable toComparator(ComparatorProtos.Comparator proto) 1597 throws IOException { 1598 String type = proto.getName(); 1599 byte[] value = proto.getSerializedComparator().toByteArray(); 1600 1601 try { 1602 ByteArrayComparable result = COMPARATORS.getAndCallByName(type, value); 1603 if (result != null) { 1604 return result; 1605 } 1606 1607 if (!ALLOW_FAST_REFLECTION_FALLTHROUGH) { 1608 throw new IllegalStateException("Failed to deserialize comparator " + type 1609 + " because fast reflection returned null and fallthrough is disabled"); 1610 } 1611 1612 Class<?> c = Class.forName(type, true, ClassLoaderHolder.CLASS_LOADER); 1613 Method parseFrom = c.getMethod(PARSE_FROM, byte[].class); 1614 if (parseFrom == null) { 1615 throw new IOException("Unable to locate function: " + PARSE_FROM + " in type: " + type); 1616 } 1617 return (ByteArrayComparable) parseFrom.invoke(null, value); 1618 } catch (Exception e) { 1619 throw new IOException(e); 1620 } 1621 } 1622 1623 /** 1624 * Convert a protocol buffer Filter to a client Filter 1625 * @param proto the protocol buffer Filter to convert 1626 * @return the converted Filter 1627 */ 1628 @SuppressWarnings("unchecked") 1629 public static Filter toFilter(FilterProtos.Filter proto) throws IOException { 1630 String type = proto.getName(); 1631 final byte[] value = proto.getSerializedFilter().toByteArray(); 1632 1633 try { 1634 Filter result = FILTERS.getAndCallByName(type, value); 1635 if (result != null) { 1636 return result; 1637 } 1638 1639 if (!ALLOW_FAST_REFLECTION_FALLTHROUGH) { 1640 throw new IllegalStateException("Failed to deserialize comparator " + type 1641 + " because fast reflection returned null and fallthrough is disabled"); 1642 } 1643 1644 Class<?> c = Class.forName(type, true, ClassLoaderHolder.CLASS_LOADER); 1645 Method parseFrom = c.getMethod(PARSE_FROM, byte[].class); 1646 if (parseFrom == null) { 1647 throw new IOException("Unable to locate function: " + PARSE_FROM + " in type: " + type); 1648 } 1649 return (Filter) parseFrom.invoke(c, value); 1650 } catch (Exception e) { 1651 // Either we couldn't instantiate the method object, or "parseFrom" failed. 1652 // In either case, let's not retry. 1653 throw new DoNotRetryIOException(e); 1654 } 1655 } 1656 1657 /** 1658 * Convert a client Filter to a protocol buffer Filter 1659 * @param filter the Filter to convert 1660 * @return the converted protocol buffer Filter 1661 */ 1662 public static FilterProtos.Filter toFilter(Filter filter) throws IOException { 1663 FilterProtos.Filter.Builder builder = FilterProtos.Filter.newBuilder(); 1664 builder.setName(filter.getClass().getName()); 1665 builder.setSerializedFilter(UnsafeByteOperations.unsafeWrap(filter.toByteArray())); 1666 return builder.build(); 1667 } 1668 1669 /** 1670 * Convert a delete KeyValue type to protocol buffer DeleteType. 1671 * @return protocol buffer DeleteType 1672 */ 1673 public static DeleteType toDeleteType(KeyValue.Type type) throws IOException { 1674 switch (type) { 1675 case Delete: 1676 return DeleteType.DELETE_ONE_VERSION; 1677 case DeleteColumn: 1678 return DeleteType.DELETE_MULTIPLE_VERSIONS; 1679 case DeleteFamily: 1680 return DeleteType.DELETE_FAMILY; 1681 case DeleteFamilyVersion: 1682 return DeleteType.DELETE_FAMILY_VERSION; 1683 default: 1684 throw new IOException("Unknown delete type: " + type); 1685 } 1686 } 1687 1688 /** 1689 * Convert a protocol buffer DeleteType to delete KeyValue type. 1690 * @param type The DeleteType 1691 * @return The type. 1692 */ 1693 public static KeyValue.Type fromDeleteType(DeleteType type) throws IOException { 1694 switch (type) { 1695 case DELETE_ONE_VERSION: 1696 return KeyValue.Type.Delete; 1697 case DELETE_MULTIPLE_VERSIONS: 1698 return KeyValue.Type.DeleteColumn; 1699 case DELETE_FAMILY: 1700 return KeyValue.Type.DeleteFamily; 1701 case DELETE_FAMILY_VERSION: 1702 return KeyValue.Type.DeleteFamilyVersion; 1703 default: 1704 throw new IOException("Unknown delete type: " + type); 1705 } 1706 } 1707 1708 /** 1709 * Convert a stringified protocol buffer exception Parameter to a Java Exception 1710 * @param parameter the protocol buffer Parameter to convert 1711 * @return the converted Exception 1712 * @throws IOException if failed to deserialize the parameter 1713 */ 1714 @SuppressWarnings("unchecked") 1715 public static Throwable toException(final NameBytesPair parameter) throws IOException { 1716 if (parameter == null || !parameter.hasValue()) return null; 1717 String desc = parameter.getValue().toStringUtf8(); 1718 String type = parameter.getName(); 1719 try { 1720 Class<? extends Throwable> c = 1721 (Class<? extends Throwable>) Class.forName(type, true, ClassLoaderHolder.CLASS_LOADER); 1722 Constructor<? extends Throwable> cn = null; 1723 try { 1724 cn = c.getDeclaredConstructor(String.class); 1725 return cn.newInstance(desc); 1726 } catch (NoSuchMethodException e) { 1727 // Could be a raw RemoteException. See HBASE-8987. 1728 cn = c.getDeclaredConstructor(String.class, String.class); 1729 return cn.newInstance(type, desc); 1730 } 1731 } catch (Exception e) { 1732 throw new IOException(e); 1733 } 1734 } 1735 1736 // Start helpers for Client 1737 1738 @SuppressWarnings("unchecked") 1739 public static <T extends Service> T newServiceStub(Class<T> service, RpcChannel channel) 1740 throws Exception { 1741 return (T) Methods.call(service, null, "newStub", new Class[] { RpcChannel.class }, 1742 new Object[] { channel }); 1743 } 1744 1745 // End helpers for Client 1746 // Start helpers for Admin 1747 1748 /** 1749 * A helper to retrieve region info given a region name or an encoded region name using admin 1750 * protocol. 1751 * @return the retrieved region info 1752 */ 1753 public static org.apache.hadoop.hbase.client.RegionInfo getRegionInfo( 1754 final RpcController controller, final AdminService.BlockingInterface admin, 1755 final byte[] regionName) throws IOException { 1756 try { 1757 GetRegionInfoResponse response = 1758 admin.getRegionInfo(controller, getGetRegionInfoRequest(regionName)); 1759 return toRegionInfo(response.getRegionInfo()); 1760 } catch (ServiceException se) { 1761 throw getRemoteException(se); 1762 } 1763 } 1764 1765 /** Returns A GetRegionInfoRequest for the passed in regionName. */ 1766 public static GetRegionInfoRequest getGetRegionInfoRequest(final byte[] regionName) 1767 throws IOException { 1768 return org.apache.hadoop.hbase.client.RegionInfo.isEncodedRegionName(regionName) 1769 ? GetRegionInfoRequest.newBuilder() 1770 .setRegion(RequestConverter.buildRegionSpecifier(RegionSpecifierType.ENCODED_REGION_NAME, 1771 regionName)) 1772 .build() 1773 : RequestConverter.buildGetRegionInfoRequest(regionName); 1774 } 1775 1776 /** 1777 * A helper to close a region given a region name using admin protocol. 1778 */ 1779 public static void closeRegion(final RpcController controller, 1780 final AdminService.BlockingInterface admin, final ServerName server, final byte[] regionName) 1781 throws IOException { 1782 CloseRegionRequest closeRegionRequest = 1783 ProtobufUtil.buildCloseRegionRequest(server, regionName); 1784 try { 1785 admin.closeRegion(controller, closeRegionRequest); 1786 } catch (ServiceException se) { 1787 throw getRemoteException(se); 1788 } 1789 } 1790 1791 /** 1792 * A helper to warmup a region given a region name using admin protocol 1793 */ 1794 public static void warmupRegion(final RpcController controller, 1795 final AdminService.BlockingInterface admin, 1796 final org.apache.hadoop.hbase.client.RegionInfo regionInfo) throws IOException { 1797 1798 try { 1799 WarmupRegionRequest warmupRegionRequest = 1800 RequestConverter.buildWarmupRegionRequest(regionInfo); 1801 1802 admin.warmupRegion(controller, warmupRegionRequest); 1803 } catch (ServiceException e) { 1804 throw getRemoteException(e); 1805 } 1806 } 1807 1808 /** 1809 * A helper to open a region using admin protocol. 1810 */ 1811 public static void openRegion(final RpcController controller, 1812 final AdminService.BlockingInterface admin, ServerName server, 1813 final org.apache.hadoop.hbase.client.RegionInfo region) throws IOException { 1814 OpenRegionRequest request = RequestConverter.buildOpenRegionRequest(server, region, null); 1815 try { 1816 admin.openRegion(controller, request); 1817 } catch (ServiceException se) { 1818 throw ProtobufUtil.getRemoteException(se); 1819 } 1820 } 1821 1822 /** 1823 * A helper to get the all the online regions on a region server using admin protocol. 1824 * @return a list of online region info 1825 */ 1826 public static List<org.apache.hadoop.hbase.client.RegionInfo> 1827 getOnlineRegions(final AdminService.BlockingInterface admin) throws IOException { 1828 return getOnlineRegions(null, admin); 1829 } 1830 1831 /** 1832 * A helper to get the all the online regions on a region server using admin protocol. 1833 * @return a list of online region info 1834 */ 1835 public static List<org.apache.hadoop.hbase.client.RegionInfo> getOnlineRegions( 1836 final RpcController controller, final AdminService.BlockingInterface admin) throws IOException { 1837 GetOnlineRegionRequest request = RequestConverter.buildGetOnlineRegionRequest(); 1838 GetOnlineRegionResponse response = null; 1839 try { 1840 response = admin.getOnlineRegion(controller, request); 1841 } catch (ServiceException se) { 1842 throw getRemoteException(se); 1843 } 1844 return getRegionInfos(response); 1845 } 1846 1847 /** 1848 * Get the list of cached files 1849 */ 1850 public static List<String> getCachedFilesList(final RpcController controller, 1851 final AdminService.BlockingInterface admin) throws IOException { 1852 GetCachedFilesListRequest request = GetCachedFilesListRequest.newBuilder().build(); 1853 GetCachedFilesListResponse response = null; 1854 try { 1855 response = admin.getCachedFilesList(controller, request); 1856 } catch (ServiceException se) { 1857 throw getRemoteException(se); 1858 } 1859 return new ArrayList<>(response.getCachedFilesList()); 1860 } 1861 1862 /** 1863 * Get the list of region info from a GetOnlineRegionResponse 1864 * @param proto the GetOnlineRegionResponse 1865 * @return the list of region info or empty if <code>proto</code> is null 1866 */ 1867 public static List<org.apache.hadoop.hbase.client.RegionInfo> 1868 getRegionInfos(final GetOnlineRegionResponse proto) { 1869 if (proto == null) return Collections.EMPTY_LIST; 1870 List<org.apache.hadoop.hbase.client.RegionInfo> regionInfos = 1871 new ArrayList<>(proto.getRegionInfoList().size()); 1872 for (RegionInfo regionInfo : proto.getRegionInfoList()) { 1873 regionInfos.add(toRegionInfo(regionInfo)); 1874 } 1875 return regionInfos; 1876 } 1877 1878 /** 1879 * A helper to get the info of a region server using admin protocol. 1880 * @return the server name 1881 */ 1882 public static ServerInfo getServerInfo(final RpcController controller, 1883 final AdminService.BlockingInterface admin) throws IOException { 1884 GetServerInfoRequest request = RequestConverter.buildGetServerInfoRequest(); 1885 try { 1886 GetServerInfoResponse response = admin.getServerInfo(controller, request); 1887 return response.getServerInfo(); 1888 } catch (ServiceException se) { 1889 throw getRemoteException(se); 1890 } 1891 } 1892 1893 /** 1894 * A helper to get the list of files of a column family on a given region using admin protocol. 1895 * @return the list of store files 1896 */ 1897 public static List<String> getStoreFiles(final AdminService.BlockingInterface admin, 1898 final byte[] regionName, final byte[] family) throws IOException { 1899 return getStoreFiles(null, admin, regionName, family); 1900 } 1901 1902 /** 1903 * A helper to get the list of files of a column family on a given region using admin protocol. 1904 * @return the list of store files 1905 */ 1906 public static List<String> getStoreFiles(final RpcController controller, 1907 final AdminService.BlockingInterface admin, final byte[] regionName, final byte[] family) 1908 throws IOException { 1909 GetStoreFileRequest request = ProtobufUtil.buildGetStoreFileRequest(regionName, family); 1910 try { 1911 GetStoreFileResponse response = admin.getStoreFile(controller, request); 1912 return response.getStoreFileList(); 1913 } catch (ServiceException se) { 1914 throw ProtobufUtil.getRemoteException(se); 1915 } 1916 } 1917 1918 // End helpers for Admin 1919 1920 /* 1921 * Get the total (read + write) requests from a RegionLoad pb 1922 * @param rl - RegionLoad pb 1923 * @return total (read + write) requests 1924 */ 1925 public static long getTotalRequestsCount(RegionLoad rl) { 1926 if (rl == null) { 1927 return 0; 1928 } 1929 1930 return rl.getReadRequestsCount() + rl.getWriteRequestsCount(); 1931 } 1932 1933 public static byte[] toDelimitedByteArray(final Message m) throws IOException { 1934 // Allocate arbitrary big size so we avoid resizing. 1935 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096); 1936 baos.write(PB_MAGIC); 1937 m.writeDelimitedTo(baos); 1938 return baos.toByteArray(); 1939 } 1940 1941 /** 1942 * Find the HRegion encoded name based on a region specifier 1943 * @param regionSpecifier the region specifier 1944 * @return the corresponding region's encoded name 1945 * @throws DoNotRetryIOException if the specifier type is unsupported 1946 */ 1947 public static String getRegionEncodedName(final RegionSpecifier regionSpecifier) 1948 throws DoNotRetryIOException { 1949 ByteString value = regionSpecifier.getValue(); 1950 RegionSpecifierType type = regionSpecifier.getType(); 1951 switch (type) { 1952 case REGION_NAME: 1953 return org.apache.hadoop.hbase.client.RegionInfo.encodeRegionName(value.toByteArray()); 1954 case ENCODED_REGION_NAME: 1955 return value.toStringUtf8(); 1956 default: 1957 throw new DoNotRetryIOException("Unsupported region specifier type: " + type); 1958 } 1959 } 1960 1961 public static ScanMetrics toScanMetrics(final byte[] bytes) { 1962 MapReduceProtos.ScanMetrics pScanMetrics = null; 1963 try { 1964 pScanMetrics = MapReduceProtos.ScanMetrics.parseFrom(bytes); 1965 } catch (InvalidProtocolBufferException e) { 1966 // Ignored there are just no key values to add. 1967 } 1968 ScanMetrics scanMetrics = new ScanMetrics(); 1969 if (pScanMetrics != null) { 1970 for (HBaseProtos.NameInt64Pair pair : pScanMetrics.getMetricsList()) { 1971 if (pair.hasName() && pair.hasValue()) { 1972 scanMetrics.setCounter(pair.getName(), pair.getValue()); 1973 } 1974 } 1975 } 1976 return scanMetrics; 1977 } 1978 1979 public static MapReduceProtos.ScanMetrics toScanMetrics(ScanMetrics scanMetrics, boolean reset) { 1980 MapReduceProtos.ScanMetrics.Builder builder = MapReduceProtos.ScanMetrics.newBuilder(); 1981 Map<String, Long> metrics = scanMetrics.getMetricsMap(reset); 1982 for (Entry<String, Long> e : metrics.entrySet()) { 1983 HBaseProtos.NameInt64Pair nameInt64Pair = 1984 HBaseProtos.NameInt64Pair.newBuilder().setName(e.getKey()).setValue(e.getValue()).build(); 1985 builder.addMetrics(nameInt64Pair); 1986 } 1987 return builder.build(); 1988 } 1989 1990 /** 1991 * Unwraps an exception from a protobuf service into the underlying (expected) IOException. This 1992 * method will <strong>always</strong> throw an exception. 1993 * @param se the {@code ServiceException} instance to convert into an {@code IOException} 1994 * @throws NullPointerException if {@code se} is {@code null} 1995 */ 1996 public static void toIOException(ServiceException se) throws IOException { 1997 Objects.requireNonNull(se, "Service exception cannot be null"); 1998 1999 Throwable cause = se.getCause(); 2000 if (cause != null && cause instanceof IOException) { 2001 throw (IOException) cause; 2002 } 2003 throw new IOException(se); 2004 } 2005 2006 public static CellProtos.Cell toCell(final ExtendedCell kv, boolean encodeTags) { 2007 // Doing this is going to kill us if we do it for all data passed. 2008 // St.Ack 20121205 2009 CellProtos.Cell.Builder kvbuilder = CellProtos.Cell.newBuilder(); 2010 if (kv instanceof ByteBufferExtendedCell) { 2011 kvbuilder.setRow(wrap(((ByteBufferExtendedCell) kv).getRowByteBuffer(), 2012 ((ByteBufferExtendedCell) kv).getRowPosition(), kv.getRowLength())); 2013 kvbuilder.setFamily(wrap(((ByteBufferExtendedCell) kv).getFamilyByteBuffer(), 2014 ((ByteBufferExtendedCell) kv).getFamilyPosition(), kv.getFamilyLength())); 2015 kvbuilder.setQualifier(wrap(((ByteBufferExtendedCell) kv).getQualifierByteBuffer(), 2016 ((ByteBufferExtendedCell) kv).getQualifierPosition(), kv.getQualifierLength())); 2017 kvbuilder.setCellType(CellProtos.CellType.forNumber(kv.getTypeByte())); 2018 kvbuilder.setTimestamp(kv.getTimestamp()); 2019 kvbuilder.setValue(wrap(((ByteBufferExtendedCell) kv).getValueByteBuffer(), 2020 ((ByteBufferExtendedCell) kv).getValuePosition(), kv.getValueLength())); 2021 if (encodeTags) { 2022 kvbuilder.setTags(wrap(((ByteBufferExtendedCell) kv).getTagsByteBuffer(), 2023 ((ByteBufferExtendedCell) kv).getTagsPosition(), kv.getTagsLength())); 2024 } 2025 } else { 2026 kvbuilder.setRow( 2027 UnsafeByteOperations.unsafeWrap(kv.getRowArray(), kv.getRowOffset(), kv.getRowLength())); 2028 kvbuilder.setFamily(UnsafeByteOperations.unsafeWrap(kv.getFamilyArray(), kv.getFamilyOffset(), 2029 kv.getFamilyLength())); 2030 kvbuilder.setQualifier(UnsafeByteOperations.unsafeWrap(kv.getQualifierArray(), 2031 kv.getQualifierOffset(), kv.getQualifierLength())); 2032 kvbuilder.setCellType(CellProtos.CellType.forNumber(kv.getTypeByte())); 2033 kvbuilder.setTimestamp(kv.getTimestamp()); 2034 kvbuilder.setValue(UnsafeByteOperations.unsafeWrap(kv.getValueArray(), kv.getValueOffset(), 2035 kv.getValueLength())); 2036 if (encodeTags) { 2037 kvbuilder.setTags(UnsafeByteOperations.unsafeWrap(kv.getTagsArray(), kv.getTagsOffset(), 2038 kv.getTagsLength())); 2039 } 2040 } 2041 return kvbuilder.build(); 2042 } 2043 2044 private static ByteString wrap(ByteBuffer b, int offset, int length) { 2045 ByteBuffer dup = b.duplicate(); 2046 dup.position(offset); 2047 dup.limit(offset + length); 2048 return UnsafeByteOperations.unsafeWrap(dup); 2049 } 2050 2051 public static ExtendedCell toCell(ExtendedCellBuilder cellBuilder, final CellProtos.Cell cell, 2052 boolean decodeTags) { 2053 ExtendedCellBuilder builder = cellBuilder.clear().setRow(cell.getRow().toByteArray()) 2054 .setFamily(cell.getFamily().toByteArray()).setQualifier(cell.getQualifier().toByteArray()) 2055 .setTimestamp(cell.getTimestamp()).setType((byte) cell.getCellType().getNumber()) 2056 .setValue(cell.getValue().toByteArray()); 2057 if (decodeTags && cell.hasTags()) { 2058 builder.setTags(cell.getTags().toByteArray()); 2059 } 2060 return builder.build(); 2061 } 2062 2063 public static HBaseProtos.NamespaceDescriptor toProtoNamespaceDescriptor(NamespaceDescriptor ns) { 2064 HBaseProtos.NamespaceDescriptor.Builder b = 2065 HBaseProtos.NamespaceDescriptor.newBuilder().setName(ByteString.copyFromUtf8(ns.getName())); 2066 for (Map.Entry<String, String> entry : ns.getConfiguration().entrySet()) { 2067 b.addConfiguration( 2068 HBaseProtos.NameStringPair.newBuilder().setName(entry.getKey()).setValue(entry.getValue())); 2069 } 2070 return b.build(); 2071 } 2072 2073 public static NamespaceDescriptor toNamespaceDescriptor(HBaseProtos.NamespaceDescriptor desc) { 2074 NamespaceDescriptor.Builder b = NamespaceDescriptor.create(desc.getName().toStringUtf8()); 2075 for (HBaseProtos.NameStringPair prop : desc.getConfigurationList()) { 2076 b.addConfiguration(prop.getName(), prop.getValue()); 2077 } 2078 return b.build(); 2079 } 2080 2081 public static CompactionDescriptor toCompactionDescriptor( 2082 org.apache.hadoop.hbase.client.RegionInfo info, byte[] family, List<Path> inputPaths, 2083 List<Path> outputPaths, Path storeDir) { 2084 return toCompactionDescriptor(info, null, family, inputPaths, outputPaths, storeDir); 2085 } 2086 2087 public static CompactionDescriptor toCompactionDescriptor( 2088 org.apache.hadoop.hbase.client.RegionInfo info, byte[] regionName, byte[] family, 2089 List<Path> inputPaths, List<Path> outputPaths, Path storeDir) { 2090 // compaction descriptor contains relative paths. 2091 // input / output paths are relative to the store dir 2092 // store dir is relative to region dir 2093 CompactionDescriptor.Builder builder = CompactionDescriptor.newBuilder() 2094 .setTableName(UnsafeByteOperations.unsafeWrap(info.getTable().toBytes())) 2095 .setEncodedRegionName(UnsafeByteOperations 2096 .unsafeWrap(regionName == null ? info.getEncodedNameAsBytes() : regionName)) 2097 .setFamilyName(UnsafeByteOperations.unsafeWrap(family)).setStoreHomeDir(storeDir.getName()); // make 2098 // relative 2099 for (Path inputPath : inputPaths) { 2100 builder.addCompactionInput(inputPath.getName()); // relative path 2101 } 2102 for (Path outputPath : outputPaths) { 2103 builder.addCompactionOutput(outputPath.getName()); 2104 } 2105 builder.setRegionName(UnsafeByteOperations.unsafeWrap(info.getRegionName())); 2106 return builder.build(); 2107 } 2108 2109 public static FlushDescriptor toFlushDescriptor(FlushAction action, 2110 org.apache.hadoop.hbase.client.RegionInfo hri, long flushSeqId, 2111 Map<byte[], List<Path>> committedFiles) { 2112 FlushDescriptor.Builder desc = FlushDescriptor.newBuilder().setAction(action) 2113 .setEncodedRegionName(UnsafeByteOperations.unsafeWrap(hri.getEncodedNameAsBytes())) 2114 .setRegionName(UnsafeByteOperations.unsafeWrap(hri.getRegionName())) 2115 .setFlushSequenceNumber(flushSeqId) 2116 .setTableName(UnsafeByteOperations.unsafeWrap(hri.getTable().getName())); 2117 2118 for (Map.Entry<byte[], List<Path>> entry : committedFiles.entrySet()) { 2119 WALProtos.FlushDescriptor.StoreFlushDescriptor.Builder builder = 2120 WALProtos.FlushDescriptor.StoreFlushDescriptor.newBuilder() 2121 .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey())) 2122 .setStoreHomeDir(Bytes.toString(entry.getKey())); // relative to region 2123 if (entry.getValue() != null) { 2124 for (Path path : entry.getValue()) { 2125 builder.addFlushOutput(path.getName()); 2126 } 2127 } 2128 desc.addStoreFlushes(builder); 2129 } 2130 return desc.build(); 2131 } 2132 2133 public static RegionEventDescriptor toRegionEventDescriptor(EventType eventType, 2134 org.apache.hadoop.hbase.client.RegionInfo hri, long seqId, ServerName server, 2135 Map<byte[], List<Path>> storeFiles) { 2136 final byte[] tableNameAsBytes = hri.getTable().getName(); 2137 final byte[] encodedNameAsBytes = hri.getEncodedNameAsBytes(); 2138 final byte[] regionNameAsBytes = hri.getRegionName(); 2139 return toRegionEventDescriptor(eventType, tableNameAsBytes, encodedNameAsBytes, 2140 regionNameAsBytes, seqId, 2141 2142 server, storeFiles); 2143 } 2144 2145 public static RegionEventDescriptor toRegionEventDescriptor(EventType eventType, 2146 byte[] tableNameAsBytes, byte[] encodedNameAsBytes, byte[] regionNameAsBytes, long seqId, 2147 2148 ServerName server, Map<byte[], List<Path>> storeFiles) { 2149 RegionEventDescriptor.Builder desc = RegionEventDescriptor.newBuilder().setEventType(eventType) 2150 .setTableName(UnsafeByteOperations.unsafeWrap(tableNameAsBytes)) 2151 .setEncodedRegionName(UnsafeByteOperations.unsafeWrap(encodedNameAsBytes)) 2152 .setRegionName(UnsafeByteOperations.unsafeWrap(regionNameAsBytes)).setLogSequenceNumber(seqId) 2153 .setServer(toServerName(server)); 2154 2155 for (Entry<byte[], List<Path>> entry : storeFiles.entrySet()) { 2156 StoreDescriptor.Builder builder = 2157 StoreDescriptor.newBuilder().setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey())) 2158 .setStoreHomeDir(Bytes.toString(entry.getKey())); 2159 for (Path path : entry.getValue()) { 2160 builder.addStoreFile(path.getName()); 2161 } 2162 2163 desc.addStores(builder); 2164 } 2165 return desc.build(); 2166 } 2167 2168 /** 2169 * Return short version of Message toString'd, shorter than TextFormat#shortDebugString. Tries to 2170 * NOT print out data both because it can be big but also so we do not have data in our logs. Use 2171 * judiciously. 2172 * @return toString of passed <code>m</code> 2173 */ 2174 public static String getShortTextFormat(Message m) { 2175 if (m == null) { 2176 return "null"; 2177 } 2178 if (m instanceof ScanRequest) { 2179 // This should be small and safe to output. No data. 2180 return TextFormat.shortDebugString(m); 2181 } else if (m instanceof RegionServerReportRequest) { 2182 // Print a short message only, just the servername and the requests, not the full load. 2183 RegionServerReportRequest r = (RegionServerReportRequest) m; 2184 return "server " + TextFormat.shortDebugString(r.getServer()) + " load { numberOfRequests: " 2185 + r.getLoad().getNumberOfRequests() + " }"; 2186 } else if (m instanceof RegionServerStartupRequest) { 2187 // Should be small enough. 2188 return TextFormat.shortDebugString(m); 2189 } else if (m instanceof MutationProto) { 2190 return toShortString((MutationProto) m); 2191 } else if (m instanceof GetRequest) { 2192 GetRequest r = (GetRequest) m; 2193 return "region= " + getStringForByteString(r.getRegion().getValue()) + ", row=" 2194 + getStringForByteString(r.getGet().getRow()); 2195 } else if (m instanceof ClientProtos.MultiRequest) { 2196 ClientProtos.MultiRequest r = (ClientProtos.MultiRequest) m; 2197 2198 // Get the number of Actions 2199 int actionsCount = 2200 r.getRegionActionList().stream().mapToInt(ClientProtos.RegionAction::getActionCount).sum(); 2201 2202 // Get first set of Actions. 2203 ClientProtos.RegionAction actions = r.getRegionActionList().get(0); 2204 String row = actions.getActionCount() <= 0 2205 ? "" 2206 : getStringForByteString(actions.getAction(0).hasGet() 2207 ? actions.getAction(0).getGet().getRow() 2208 : actions.getAction(0).getMutation().getRow()); 2209 return "region= " + getStringForByteString(actions.getRegion().getValue()) + ", for " 2210 + actionsCount + " action(s) and 1st row key=" + row; 2211 } else if (m instanceof ClientProtos.MutateRequest) { 2212 ClientProtos.MutateRequest r = (ClientProtos.MutateRequest) m; 2213 return "region= " + getStringForByteString(r.getRegion().getValue()) + ", row=" 2214 + getStringForByteString(r.getMutation().getRow()); 2215 } else if (m instanceof ClientProtos.CoprocessorServiceRequest) { 2216 ClientProtos.CoprocessorServiceRequest r = (ClientProtos.CoprocessorServiceRequest) m; 2217 return "coprocessorService= " + r.getCall().getServiceName() + ":" 2218 + r.getCall().getMethodName(); 2219 } else if (m instanceof MasterProtos.MoveRegionRequest) { 2220 return TextFormat.shortDebugString(m); 2221 } 2222 return "TODO: " + m.getClass().toString(); 2223 } 2224 2225 private static String getStringForByteString(ByteString bs) { 2226 return Bytes.toStringBinary(bs.toByteArray()); 2227 } 2228 2229 /** 2230 * Return SlowLogParams to maintain recent online slowlog responses 2231 * @param message Message object {@link Message} 2232 * @return SlowLogParams with regionName(for filter queries) and params 2233 */ 2234 public static SlowLogParams getSlowLogParams(Message message, boolean slowLogScanPayloadEnabled) { 2235 if (message == null) { 2236 return null; 2237 } 2238 if (message instanceof ScanRequest) { 2239 ScanRequest scanRequest = (ScanRequest) message; 2240 String regionName = getStringForByteString(scanRequest.getRegion().getValue()); 2241 String params = TextFormat.shortDebugString(message); 2242 if (slowLogScanPayloadEnabled) { 2243 return new SlowLogParams(regionName, params, scanRequest.getScan()); 2244 } else { 2245 return new SlowLogParams(regionName, params); 2246 } 2247 } else if (message instanceof MutationProto) { 2248 MutationProto mutationProto = (MutationProto) message; 2249 String params = "type= " + mutationProto.getMutateType().toString() + ", row= " 2250 + getStringForByteString(mutationProto.getRow()); 2251 return new SlowLogParams(params); 2252 } else if (message instanceof GetRequest) { 2253 GetRequest getRequest = (GetRequest) message; 2254 String regionName = getStringForByteString(getRequest.getRegion().getValue()); 2255 String params = 2256 "region= " + regionName + ", row= " + getStringForByteString(getRequest.getGet().getRow()); 2257 return new SlowLogParams(regionName, params); 2258 } else if (message instanceof MultiRequest) { 2259 MultiRequest multiRequest = (MultiRequest) message; 2260 int actionsCount = multiRequest.getRegionActionList().stream() 2261 .mapToInt(ClientProtos.RegionAction::getActionCount).sum(); 2262 RegionAction actions = multiRequest.getRegionActionList().get(0); 2263 String regionName = getStringForByteString(actions.getRegion().getValue()); 2264 String params = "region= " + regionName + ", for " + actionsCount + " action(s)"; 2265 return new SlowLogParams(regionName, params); 2266 } else if (message instanceof MutateRequest) { 2267 MutateRequest mutateRequest = (MutateRequest) message; 2268 String regionName = getStringForByteString(mutateRequest.getRegion().getValue()); 2269 String params = "region= " + regionName + ", row= " 2270 + getStringForByteString(mutateRequest.getMutation().getRow()); 2271 return new SlowLogParams(regionName, params); 2272 } else if (message instanceof CoprocessorServiceRequest) { 2273 CoprocessorServiceRequest coprocessorServiceRequest = (CoprocessorServiceRequest) message; 2274 String params = "coprocessorService= " + coprocessorServiceRequest.getCall().getServiceName() 2275 + ":" + coprocessorServiceRequest.getCall().getMethodName(); 2276 return new SlowLogParams(params); 2277 } 2278 String params = message.getClass().toString(); 2279 return new SlowLogParams(params); 2280 } 2281 2282 /** 2283 * Convert a list of NameBytesPair to a more readable CSV 2284 */ 2285 public static String convertAttributesToCsv(List<NameBytesPair> attributes) { 2286 if (attributes.isEmpty()) { 2287 return HConstants.EMPTY_STRING; 2288 } 2289 return deserializeAttributes(convertNameBytesPairsToMap(attributes)).entrySet().stream() 2290 .map(entry -> entry.getKey() + " = " + entry.getValue()).collect(Collectors.joining(", ")); 2291 } 2292 2293 /** 2294 * Convert a map of byte array attributes to a more readable map of binary string representations 2295 */ 2296 public static Map<String, String> deserializeAttributes(Map<String, byte[]> attributes) { 2297 return attributes.entrySet().stream().collect( 2298 Collectors.toMap(Map.Entry::getKey, entry -> Bytes.toStringBinary(entry.getValue()))); 2299 } 2300 2301 /** 2302 * Print out some subset of a MutationProto rather than all of it and its data 2303 * @param proto Protobuf to print out 2304 * @return Short String of mutation proto 2305 */ 2306 static String toShortString(final MutationProto proto) { 2307 return "row=" + Bytes.toString(proto.getRow().toByteArray()) + ", type=" 2308 + proto.getMutateType().toString(); 2309 } 2310 2311 public static TableName toTableName(HBaseProtos.TableName tableNamePB) { 2312 return TableName.valueOf(tableNamePB.getNamespace().asReadOnlyByteBuffer(), 2313 tableNamePB.getQualifier().asReadOnlyByteBuffer()); 2314 } 2315 2316 public static HBaseProtos.TableName toProtoTableName(TableName tableName) { 2317 return HBaseProtos.TableName.newBuilder() 2318 .setNamespace(UnsafeByteOperations.unsafeWrap(tableName.getNamespace())) 2319 .setQualifier(UnsafeByteOperations.unsafeWrap(tableName.getQualifier())).build(); 2320 } 2321 2322 public static List<HBaseProtos.TableName> toProtoTableNameList(List<TableName> tableNameList) { 2323 if (tableNameList == null) { 2324 return new ArrayList<>(); 2325 } 2326 return tableNameList.stream().map(ProtobufUtil::toProtoTableName).collect(Collectors.toList()); 2327 } 2328 2329 public static List<TableName> toTableNameList(List<HBaseProtos.TableName> tableNamesList) { 2330 if (tableNamesList == null) { 2331 return new ArrayList<>(); 2332 } 2333 return tableNamesList.stream().map(ProtobufUtil::toTableName).collect(Collectors.toList()); 2334 } 2335 2336 public static TableName[] getTableNameArray(List<HBaseProtos.TableName> tableNamesList) { 2337 if (tableNamesList == null) { 2338 return new TableName[0]; 2339 } 2340 TableName[] tableNames = new TableName[tableNamesList.size()]; 2341 for (int i = 0; i < tableNamesList.size(); i++) { 2342 tableNames[i] = toTableName(tableNamesList.get(i)); 2343 } 2344 return tableNames; 2345 } 2346 2347 /** 2348 * Convert a protocol buffer CellVisibility to a client CellVisibility 2349 * @return the converted client CellVisibility 2350 */ 2351 public static CellVisibility toCellVisibility(ClientProtos.CellVisibility proto) { 2352 if (proto == null) return null; 2353 return new CellVisibility(proto.getExpression()); 2354 } 2355 2356 /** 2357 * Convert a protocol buffer CellVisibility bytes to a client CellVisibility 2358 * @return the converted client CellVisibility 2359 */ 2360 public static CellVisibility toCellVisibility(byte[] protoBytes) throws DeserializationException { 2361 if (protoBytes == null) return null; 2362 ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder(); 2363 ClientProtos.CellVisibility proto = null; 2364 try { 2365 ProtobufUtil.mergeFrom(builder, protoBytes); 2366 proto = builder.build(); 2367 } catch (IOException e) { 2368 throw new DeserializationException(e); 2369 } 2370 return toCellVisibility(proto); 2371 } 2372 2373 /** 2374 * Create a protocol buffer CellVisibility based on a client CellVisibility. 2375 * @return a protocol buffer CellVisibility 2376 */ 2377 public static ClientProtos.CellVisibility toCellVisibility(CellVisibility cellVisibility) { 2378 ClientProtos.CellVisibility.Builder builder = ClientProtos.CellVisibility.newBuilder(); 2379 builder.setExpression(cellVisibility.getExpression()); 2380 return builder.build(); 2381 } 2382 2383 /** 2384 * Convert a protocol buffer Authorizations to a client Authorizations 2385 * @return the converted client Authorizations 2386 */ 2387 public static Authorizations toAuthorizations(ClientProtos.Authorizations proto) { 2388 if (proto == null) return null; 2389 return new Authorizations(proto.getLabelList()); 2390 } 2391 2392 /** 2393 * Convert a protocol buffer Authorizations bytes to a client Authorizations 2394 * @return the converted client Authorizations 2395 */ 2396 public static Authorizations toAuthorizations(byte[] protoBytes) throws DeserializationException { 2397 if (protoBytes == null) return null; 2398 ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder(); 2399 ClientProtos.Authorizations proto = null; 2400 try { 2401 ProtobufUtil.mergeFrom(builder, protoBytes); 2402 proto = builder.build(); 2403 } catch (IOException e) { 2404 throw new DeserializationException(e); 2405 } 2406 return toAuthorizations(proto); 2407 } 2408 2409 /** 2410 * Create a protocol buffer Authorizations based on a client Authorizations. 2411 * @return a protocol buffer Authorizations 2412 */ 2413 public static ClientProtos.Authorizations toAuthorizations(Authorizations authorizations) { 2414 ClientProtos.Authorizations.Builder builder = ClientProtos.Authorizations.newBuilder(); 2415 for (String label : authorizations.getLabels()) { 2416 builder.addLabel(label); 2417 } 2418 return builder.build(); 2419 } 2420 2421 /** 2422 * Convert a protocol buffer TimeUnit to a client TimeUnit 2423 * @return the converted client TimeUnit 2424 */ 2425 public static TimeUnit toTimeUnit(final HBaseProtos.TimeUnit proto) { 2426 switch (proto) { 2427 case NANOSECONDS: 2428 return TimeUnit.NANOSECONDS; 2429 case MICROSECONDS: 2430 return TimeUnit.MICROSECONDS; 2431 case MILLISECONDS: 2432 return TimeUnit.MILLISECONDS; 2433 case SECONDS: 2434 return TimeUnit.SECONDS; 2435 case MINUTES: 2436 return TimeUnit.MINUTES; 2437 case HOURS: 2438 return TimeUnit.HOURS; 2439 case DAYS: 2440 return TimeUnit.DAYS; 2441 } 2442 throw new RuntimeException("Invalid TimeUnit " + proto); 2443 } 2444 2445 /** 2446 * Convert a client TimeUnit to a protocol buffer TimeUnit 2447 * @return the converted protocol buffer TimeUnit 2448 */ 2449 public static HBaseProtos.TimeUnit toProtoTimeUnit(final TimeUnit timeUnit) { 2450 switch (timeUnit) { 2451 case NANOSECONDS: 2452 return HBaseProtos.TimeUnit.NANOSECONDS; 2453 case MICROSECONDS: 2454 return HBaseProtos.TimeUnit.MICROSECONDS; 2455 case MILLISECONDS: 2456 return HBaseProtos.TimeUnit.MILLISECONDS; 2457 case SECONDS: 2458 return HBaseProtos.TimeUnit.SECONDS; 2459 case MINUTES: 2460 return HBaseProtos.TimeUnit.MINUTES; 2461 case HOURS: 2462 return HBaseProtos.TimeUnit.HOURS; 2463 case DAYS: 2464 return HBaseProtos.TimeUnit.DAYS; 2465 } 2466 throw new RuntimeException("Invalid TimeUnit " + timeUnit); 2467 } 2468 2469 /** 2470 * Convert a protocol buffer ThrottleType to a client ThrottleType 2471 * @return the converted client ThrottleType 2472 */ 2473 public static ThrottleType toThrottleType(final QuotaProtos.ThrottleType proto) { 2474 switch (proto) { 2475 case REQUEST_NUMBER: 2476 return ThrottleType.REQUEST_NUMBER; 2477 case REQUEST_SIZE: 2478 return ThrottleType.REQUEST_SIZE; 2479 case REQUEST_CAPACITY_UNIT: 2480 return ThrottleType.REQUEST_CAPACITY_UNIT; 2481 case WRITE_NUMBER: 2482 return ThrottleType.WRITE_NUMBER; 2483 case WRITE_SIZE: 2484 return ThrottleType.WRITE_SIZE; 2485 case READ_NUMBER: 2486 return ThrottleType.READ_NUMBER; 2487 case READ_SIZE: 2488 return ThrottleType.READ_SIZE; 2489 case READ_CAPACITY_UNIT: 2490 return ThrottleType.READ_CAPACITY_UNIT; 2491 case WRITE_CAPACITY_UNIT: 2492 return ThrottleType.WRITE_CAPACITY_UNIT; 2493 case ATOMIC_READ_SIZE: 2494 return ThrottleType.ATOMIC_READ_SIZE; 2495 case ATOMIC_REQUEST_NUMBER: 2496 return ThrottleType.ATOMIC_REQUEST_NUMBER; 2497 case ATOMIC_WRITE_SIZE: 2498 return ThrottleType.ATOMIC_WRITE_SIZE; 2499 case REQUEST_HANDLER_USAGE_MS: 2500 return ThrottleType.REQUEST_HANDLER_USAGE_MS; 2501 default: 2502 throw new RuntimeException("Invalid ThrottleType " + proto); 2503 } 2504 } 2505 2506 /** 2507 * Convert a client ThrottleType to a protocol buffer ThrottleType 2508 * @return the converted protocol buffer ThrottleType 2509 */ 2510 public static QuotaProtos.ThrottleType toProtoThrottleType(final ThrottleType type) { 2511 switch (type) { 2512 case REQUEST_NUMBER: 2513 return QuotaProtos.ThrottleType.REQUEST_NUMBER; 2514 case REQUEST_SIZE: 2515 return QuotaProtos.ThrottleType.REQUEST_SIZE; 2516 case WRITE_NUMBER: 2517 return QuotaProtos.ThrottleType.WRITE_NUMBER; 2518 case WRITE_SIZE: 2519 return QuotaProtos.ThrottleType.WRITE_SIZE; 2520 case READ_NUMBER: 2521 return QuotaProtos.ThrottleType.READ_NUMBER; 2522 case READ_SIZE: 2523 return QuotaProtos.ThrottleType.READ_SIZE; 2524 case REQUEST_CAPACITY_UNIT: 2525 return QuotaProtos.ThrottleType.REQUEST_CAPACITY_UNIT; 2526 case READ_CAPACITY_UNIT: 2527 return QuotaProtos.ThrottleType.READ_CAPACITY_UNIT; 2528 case WRITE_CAPACITY_UNIT: 2529 return QuotaProtos.ThrottleType.WRITE_CAPACITY_UNIT; 2530 case ATOMIC_READ_SIZE: 2531 return QuotaProtos.ThrottleType.ATOMIC_READ_SIZE; 2532 case ATOMIC_REQUEST_NUMBER: 2533 return QuotaProtos.ThrottleType.ATOMIC_REQUEST_NUMBER; 2534 case ATOMIC_WRITE_SIZE: 2535 return QuotaProtos.ThrottleType.ATOMIC_WRITE_SIZE; 2536 case REQUEST_HANDLER_USAGE_MS: 2537 return QuotaProtos.ThrottleType.REQUEST_HANDLER_USAGE_MS; 2538 default: 2539 throw new RuntimeException("Invalid ThrottleType " + type); 2540 } 2541 } 2542 2543 /** 2544 * Convert a protocol buffer QuotaScope to a client QuotaScope 2545 * @return the converted client QuotaScope 2546 */ 2547 public static QuotaScope toQuotaScope(final QuotaProtos.QuotaScope proto) { 2548 switch (proto) { 2549 case CLUSTER: 2550 return QuotaScope.CLUSTER; 2551 case MACHINE: 2552 return QuotaScope.MACHINE; 2553 } 2554 throw new RuntimeException("Invalid QuotaScope " + proto); 2555 } 2556 2557 /** 2558 * Convert a client QuotaScope to a protocol buffer QuotaScope 2559 * @return the converted protocol buffer QuotaScope 2560 */ 2561 public static QuotaProtos.QuotaScope toProtoQuotaScope(final QuotaScope scope) { 2562 switch (scope) { 2563 case CLUSTER: 2564 return QuotaProtos.QuotaScope.CLUSTER; 2565 case MACHINE: 2566 return QuotaProtos.QuotaScope.MACHINE; 2567 } 2568 throw new RuntimeException("Invalid QuotaScope " + scope); 2569 } 2570 2571 /** 2572 * Convert a protocol buffer QuotaType to a client QuotaType 2573 * @return the converted client QuotaType 2574 */ 2575 public static QuotaType toQuotaScope(final QuotaProtos.QuotaType proto) { 2576 switch (proto) { 2577 case THROTTLE: 2578 return QuotaType.THROTTLE; 2579 case SPACE: 2580 return QuotaType.SPACE; 2581 } 2582 throw new RuntimeException("Invalid QuotaType " + proto); 2583 } 2584 2585 /** 2586 * Convert a client QuotaType to a protocol buffer QuotaType 2587 * @return the converted protocol buffer QuotaType 2588 */ 2589 public static QuotaProtos.QuotaType toProtoQuotaScope(final QuotaType type) { 2590 switch (type) { 2591 case THROTTLE: 2592 return QuotaProtos.QuotaType.THROTTLE; 2593 case SPACE: 2594 return QuotaProtos.QuotaType.SPACE; 2595 default: 2596 throw new RuntimeException("Invalid QuotaType " + type); 2597 } 2598 } 2599 2600 /** 2601 * Converts a protocol buffer SpaceViolationPolicy to a client SpaceViolationPolicy. 2602 * @param proto The protocol buffer space violation policy. 2603 * @return The corresponding client SpaceViolationPolicy. 2604 */ 2605 public static SpaceViolationPolicy 2606 toViolationPolicy(final QuotaProtos.SpaceViolationPolicy proto) { 2607 switch (proto) { 2608 case DISABLE: 2609 return SpaceViolationPolicy.DISABLE; 2610 case NO_WRITES_COMPACTIONS: 2611 return SpaceViolationPolicy.NO_WRITES_COMPACTIONS; 2612 case NO_WRITES: 2613 return SpaceViolationPolicy.NO_WRITES; 2614 case NO_INSERTS: 2615 return SpaceViolationPolicy.NO_INSERTS; 2616 } 2617 throw new RuntimeException("Invalid SpaceViolationPolicy " + proto); 2618 } 2619 2620 /** 2621 * Converts a client SpaceViolationPolicy to a protocol buffer SpaceViolationPolicy. 2622 * @param policy The client SpaceViolationPolicy object. 2623 * @return The corresponding protocol buffer SpaceViolationPolicy. 2624 */ 2625 public static QuotaProtos.SpaceViolationPolicy 2626 toProtoViolationPolicy(final SpaceViolationPolicy policy) { 2627 switch (policy) { 2628 case DISABLE: 2629 return QuotaProtos.SpaceViolationPolicy.DISABLE; 2630 case NO_WRITES_COMPACTIONS: 2631 return QuotaProtos.SpaceViolationPolicy.NO_WRITES_COMPACTIONS; 2632 case NO_WRITES: 2633 return QuotaProtos.SpaceViolationPolicy.NO_WRITES; 2634 case NO_INSERTS: 2635 return QuotaProtos.SpaceViolationPolicy.NO_INSERTS; 2636 } 2637 throw new RuntimeException("Invalid SpaceViolationPolicy " + policy); 2638 } 2639 2640 /** 2641 * Build a protocol buffer TimedQuota 2642 * @param limit the allowed number of request/data per timeUnit 2643 * @param timeUnit the limit time unit 2644 * @param scope the quota scope 2645 * @return the protocol buffer TimedQuota 2646 */ 2647 public static QuotaProtos.TimedQuota toTimedQuota(final long limit, final TimeUnit timeUnit, 2648 final QuotaScope scope) { 2649 return QuotaProtos.TimedQuota.newBuilder().setSoftLimit(limit) 2650 .setTimeUnit(toProtoTimeUnit(timeUnit)).setScope(toProtoQuotaScope(scope)).build(); 2651 } 2652 2653 /** 2654 * Builds a protocol buffer SpaceQuota. 2655 * @param limit The maximum space usage for the quota in bytes. 2656 * @param violationPolicy The policy to apply when the quota is violated. 2657 * @return The protocol buffer SpaceQuota. 2658 */ 2659 public static QuotaProtos.SpaceQuota toProtoSpaceQuota(final long limit, 2660 final SpaceViolationPolicy violationPolicy) { 2661 return QuotaProtos.SpaceQuota.newBuilder().setSoftLimit(limit) 2662 .setViolationPolicy(toProtoViolationPolicy(violationPolicy)).build(); 2663 } 2664 2665 /** 2666 * Generates a marker for the WAL so that we propagate the notion of a bulk region load throughout 2667 * the WAL. 2668 * @param tableName The tableName into which the bulk load is being imported into. 2669 * @param encodedRegionName Encoded region name of the region which is being bulk loaded. 2670 * @param storeFiles A set of store files of a column family are bulk loaded. 2671 * @param storeFilesSize Map of store files and their lengths 2672 * @param bulkloadSeqId sequence ID (by a force flush) used to create bulk load hfile name 2673 * @return The WAL log marker for bulk loads. 2674 */ 2675 public static WALProtos.BulkLoadDescriptor toBulkLoadDescriptor(TableName tableName, 2676 ByteString encodedRegionName, Map<byte[], List<Path>> storeFiles, 2677 Map<String, Long> storeFilesSize, long bulkloadSeqId) { 2678 return toBulkLoadDescriptor(tableName, encodedRegionName, storeFiles, storeFilesSize, 2679 bulkloadSeqId, null, true); 2680 } 2681 2682 public static WALProtos.BulkLoadDescriptor toBulkLoadDescriptor(TableName tableName, 2683 ByteString encodedRegionName, Map<byte[], List<Path>> storeFiles, 2684 Map<String, Long> storeFilesSize, long bulkloadSeqId, List<String> clusterIds, 2685 boolean replicate) { 2686 BulkLoadDescriptor.Builder desc = 2687 BulkLoadDescriptor.newBuilder().setTableName(ProtobufUtil.toProtoTableName(tableName)) 2688 .setEncodedRegionName(encodedRegionName).setBulkloadSeqNum(bulkloadSeqId) 2689 .setReplicate(replicate); 2690 if (clusterIds != null) { 2691 desc.addAllClusterIds(clusterIds); 2692 } 2693 2694 for (Map.Entry<byte[], List<Path>> entry : storeFiles.entrySet()) { 2695 WALProtos.StoreDescriptor.Builder builder = 2696 StoreDescriptor.newBuilder().setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey())) 2697 .setStoreHomeDir(Bytes.toString(entry.getKey())); // relative to region 2698 for (Path path : entry.getValue()) { 2699 String name = path.getName(); 2700 builder.addStoreFile(name); 2701 Long size = storeFilesSize.get(name) == null ? (Long) 0L : storeFilesSize.get(name); 2702 builder.setStoreFileSizeBytes(size); 2703 } 2704 desc.addStores(builder); 2705 } 2706 2707 return desc.build(); 2708 } 2709 2710 /** 2711 * This version of protobuf's mergeDelimitedFrom avoid the hard-coded 64MB limit for decoding 2712 * buffers 2713 * @param builder current message builder 2714 * @param in Inputsream with delimited protobuf data 2715 */ 2716 public static void mergeDelimitedFrom(Message.Builder builder, InputStream in) 2717 throws IOException { 2718 // This used to be builder.mergeDelimitedFrom(in); 2719 // but is replaced to allow us to bump the protobuf size limit. 2720 final int firstByte = in.read(); 2721 if (firstByte != -1) { 2722 final int size = CodedInputStream.readRawVarint32(firstByte, in); 2723 final InputStream limitedInput = ByteStreams.limit(in, size); 2724 final CodedInputStream codedInput = CodedInputStream.newInstance(limitedInput); 2725 codedInput.setSizeLimit(size); 2726 builder.mergeFrom(codedInput); 2727 codedInput.checkLastTagWas(0); 2728 } 2729 } 2730 2731 /** 2732 * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding buffers 2733 * where the message size is known 2734 * @param builder current message builder 2735 * @param in InputStream containing protobuf data 2736 * @param size known size of protobuf data 2737 */ 2738 public static void mergeFrom(Message.Builder builder, InputStream in, int size) 2739 throws IOException { 2740 final CodedInputStream codedInput = CodedInputStream.newInstance(in); 2741 codedInput.setSizeLimit(size); 2742 builder.mergeFrom(codedInput); 2743 codedInput.checkLastTagWas(0); 2744 } 2745 2746 /** 2747 * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding buffers 2748 * where the message size is not known 2749 * @param builder current message builder 2750 * @param in InputStream containing protobuf data 2751 */ 2752 public static void mergeFrom(Message.Builder builder, InputStream in) throws IOException { 2753 final CodedInputStream codedInput = CodedInputStream.newInstance(in); 2754 codedInput.setSizeLimit(Integer.MAX_VALUE); 2755 builder.mergeFrom(codedInput); 2756 codedInput.checkLastTagWas(0); 2757 } 2758 2759 /** 2760 * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding buffers when 2761 * working with ByteStrings 2762 * @param builder current message builder 2763 * @param bs ByteString containing the 2764 */ 2765 public static void mergeFrom(Message.Builder builder, ByteString bs) throws IOException { 2766 final CodedInputStream codedInput = bs.newCodedInput(); 2767 codedInput.setSizeLimit(bs.size()); 2768 builder.mergeFrom(codedInput); 2769 codedInput.checkLastTagWas(0); 2770 } 2771 2772 /** 2773 * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding buffers when 2774 * working with byte arrays 2775 * @param builder current message builder 2776 * @param b byte array 2777 */ 2778 public static void mergeFrom(Message.Builder builder, byte[] b) throws IOException { 2779 final CodedInputStream codedInput = CodedInputStream.newInstance(b); 2780 codedInput.setSizeLimit(b.length); 2781 builder.mergeFrom(codedInput); 2782 codedInput.checkLastTagWas(0); 2783 } 2784 2785 /** 2786 * This version of protobuf's mergeFrom avoids the hard-coded 64MB limit for decoding buffers when 2787 * working with byte arrays 2788 * @param builder current message builder 2789 * @param b byte array 2790 */ 2791 public static void mergeFrom(Message.Builder builder, byte[] b, int offset, int length) 2792 throws IOException { 2793 final CodedInputStream codedInput = CodedInputStream.newInstance(b, offset, length); 2794 codedInput.setSizeLimit(length); 2795 builder.mergeFrom(codedInput); 2796 codedInput.checkLastTagWas(0); 2797 } 2798 2799 public static void mergeFrom(Message.Builder builder, CodedInputStream codedInput, int length) 2800 throws IOException { 2801 codedInput.resetSizeCounter(); 2802 int prevLimit = codedInput.setSizeLimit(length); 2803 2804 int limit = codedInput.pushLimit(length); 2805 builder.mergeFrom(codedInput); 2806 codedInput.popLimit(limit); 2807 2808 codedInput.checkLastTagWas(0); 2809 codedInput.setSizeLimit(prevLimit); 2810 } 2811 2812 public static ReplicationLoadSink 2813 toReplicationLoadSink(ClusterStatusProtos.ReplicationLoadSink rls) { 2814 ReplicationLoadSink.ReplicationLoadSinkBuilder builder = ReplicationLoadSink.newBuilder(); 2815 builder.setAgeOfLastAppliedOp(rls.getAgeOfLastAppliedOp()) 2816 .setTimestampsOfLastAppliedOp(rls.getTimeStampsOfLastAppliedOp()) 2817 .setTimestampStarted(rls.hasTimestampStarted() ? rls.getTimestampStarted() : -1L) 2818 .setTotalOpsProcessed(rls.hasTotalOpsProcessed() ? rls.getTotalOpsProcessed() : -1L); 2819 return builder.build(); 2820 } 2821 2822 public static ReplicationLoadSource 2823 toReplicationLoadSource(ClusterStatusProtos.ReplicationLoadSource rls) { 2824 ReplicationLoadSource.ReplicationLoadSourceBuilder builder = ReplicationLoadSource.newBuilder(); 2825 builder.setPeerID(rls.getPeerID()).setAgeOfLastShippedOp(rls.getAgeOfLastShippedOp()) 2826 .setSizeOfLogQueue(rls.getSizeOfLogQueue()) 2827 .setTimestampOfLastShippedOp(rls.getTimeStampOfLastShippedOp()) 2828 .setTimeStampOfNextToReplicate(rls.getTimeStampOfNextToReplicate()) 2829 .setReplicationLag(rls.getReplicationLag()).setQueueId(rls.getQueueId()) 2830 .setRecovered(rls.getRecovered()).setRunning(rls.getRunning()) 2831 .setEditsSinceRestart(rls.getEditsSinceRestart()).setEditsRead(rls.getEditsRead()) 2832 .setoPsShipped(rls.getOPsShipped()); 2833 return builder.build(); 2834 } 2835 2836 /** 2837 * Get a protocol buffer VersionInfo 2838 * @return the converted protocol buffer VersionInfo 2839 */ 2840 public static HBaseProtos.VersionInfo getVersionInfo() { 2841 HBaseProtos.VersionInfo.Builder builder = HBaseProtos.VersionInfo.newBuilder(); 2842 String version = VersionInfo.getVersion(); 2843 builder.setVersion(version); 2844 String[] components = version.split("\\."); 2845 if (components != null && components.length > 2) { 2846 builder.setVersionMajor(Integer.parseInt(components[0])); 2847 builder.setVersionMinor(Integer.parseInt(components[1])); 2848 } 2849 builder.setUrl(VersionInfo.getUrl()); 2850 builder.setRevision(VersionInfo.getRevision()); 2851 builder.setUser(VersionInfo.getUser()); 2852 builder.setDate(VersionInfo.getDate()); 2853 builder.setSrcChecksum(VersionInfo.getSrcChecksum()); 2854 return builder.build(); 2855 } 2856 2857 /** 2858 * Convert SecurityCapabilitiesResponse.Capability to SecurityCapability 2859 * @param capabilities capabilities returned in the SecurityCapabilitiesResponse message 2860 * @return the converted list of SecurityCapability elements 2861 */ 2862 public static List<SecurityCapability> toSecurityCapabilityList( 2863 List<MasterProtos.SecurityCapabilitiesResponse.Capability> capabilities) { 2864 List<SecurityCapability> scList = new ArrayList<>(capabilities.size()); 2865 for (MasterProtos.SecurityCapabilitiesResponse.Capability c : capabilities) { 2866 try { 2867 scList.add(SecurityCapability.valueOf(c.getNumber())); 2868 } catch (IllegalArgumentException e) { 2869 // Unknown capability, just ignore it. We don't understand the new capability 2870 // but don't care since by definition we cannot take advantage of it. 2871 } 2872 } 2873 return scList; 2874 } 2875 2876 public static TimeRange toTimeRange(HBaseProtos.TimeRange timeRange) { 2877 if (timeRange == null) { 2878 return TimeRange.allTime(); 2879 } 2880 if (timeRange.hasFrom()) { 2881 if (timeRange.hasTo()) { 2882 return TimeRange.between(timeRange.getFrom(), timeRange.getTo()); 2883 } else { 2884 return TimeRange.from(timeRange.getFrom()); 2885 } 2886 } else { 2887 return TimeRange.until(timeRange.getTo()); 2888 } 2889 } 2890 2891 /** 2892 * Converts an ColumnFamilyDescriptor to ColumnFamilySchema 2893 * @param hcd the ColumnFamilySchema 2894 * @return Convert this instance to a the pb column family type 2895 */ 2896 public static ColumnFamilySchema toColumnFamilySchema(ColumnFamilyDescriptor hcd) { 2897 ColumnFamilySchema.Builder builder = ColumnFamilySchema.newBuilder(); 2898 builder.setName(UnsafeByteOperations.unsafeWrap(hcd.getName())); 2899 for (Map.Entry<Bytes, Bytes> e : hcd.getValues().entrySet()) { 2900 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder(); 2901 aBuilder.setFirst(UnsafeByteOperations.unsafeWrap(e.getKey().get())); 2902 aBuilder.setSecond(UnsafeByteOperations.unsafeWrap(e.getValue().get())); 2903 builder.addAttributes(aBuilder.build()); 2904 } 2905 for (Map.Entry<String, String> e : hcd.getConfiguration().entrySet()) { 2906 NameStringPair.Builder aBuilder = NameStringPair.newBuilder(); 2907 aBuilder.setName(e.getKey()); 2908 aBuilder.setValue(e.getValue()); 2909 builder.addConfiguration(aBuilder.build()); 2910 } 2911 return builder.build(); 2912 } 2913 2914 /** 2915 * Converts a ColumnFamilySchema to ColumnFamilyDescriptor 2916 * @param cfs the ColumnFamilySchema 2917 * @return An {@link ColumnFamilyDescriptor} made from the passed in <code>cfs</code> 2918 */ 2919 public static ColumnFamilyDescriptor toColumnFamilyDescriptor(final ColumnFamilySchema cfs) { 2920 // Use the empty constructor so we preserve the initial values set on construction for things 2921 // like maxVersion. Otherwise, we pick up wrong values on deserialization which makes for 2922 // unrelated-looking test failures that are hard to trace back to here. 2923 ColumnFamilyDescriptorBuilder builder = 2924 ColumnFamilyDescriptorBuilder.newBuilder(cfs.getName().toByteArray()); 2925 cfs.getAttributesList() 2926 .forEach(a -> builder.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray())); 2927 cfs.getConfigurationList().forEach(a -> builder.setConfiguration(a.getName(), a.getValue())); 2928 return builder.build(); 2929 } 2930 2931 /** 2932 * Converts an TableDescriptor to TableSchema 2933 * @param htd the TableDescriptor 2934 * @return Convert the current {@link TableDescriptor} into a pb TableSchema instance. 2935 */ 2936 public static TableSchema toTableSchema(TableDescriptor htd) { 2937 TableSchema.Builder builder = TableSchema.newBuilder(); 2938 builder.setTableName(toProtoTableName(htd.getTableName())); 2939 for (Map.Entry<Bytes, Bytes> e : htd.getValues().entrySet()) { 2940 BytesBytesPair.Builder aBuilder = BytesBytesPair.newBuilder(); 2941 aBuilder.setFirst(UnsafeByteOperations.unsafeWrap(e.getKey().get())); 2942 aBuilder.setSecond(UnsafeByteOperations.unsafeWrap(e.getValue().get())); 2943 builder.addAttributes(aBuilder.build()); 2944 } 2945 for (ColumnFamilyDescriptor hcd : htd.getColumnFamilies()) { 2946 builder.addColumnFamilies(toColumnFamilySchema(hcd)); 2947 } 2948 return builder.build(); 2949 } 2950 2951 /** 2952 * Converts a TableSchema to TableDescriptor 2953 * @param ts A pb TableSchema instance. 2954 * @return An {@link TableDescriptor} made from the passed in pb <code>ts</code>. 2955 */ 2956 public static TableDescriptor toTableDescriptor(final TableSchema ts) { 2957 TableDescriptorBuilder builder = 2958 TableDescriptorBuilder.newBuilder(ProtobufUtil.toTableName(ts.getTableName())); 2959 ts.getColumnFamiliesList().stream().map(ProtobufUtil::toColumnFamilyDescriptor) 2960 .forEach(builder::setColumnFamily); 2961 ts.getAttributesList() 2962 .forEach(a -> builder.setValue(a.getFirst().toByteArray(), a.getSecond().toByteArray())); 2963 ts.getConfigurationList().forEach(a -> builder.setValue(a.getName(), a.getValue())); 2964 return builder.build(); 2965 } 2966 2967 /** 2968 * Creates {@link CompactionState} from {@link GetRegionInfoResponse.CompactionState} state 2969 * @param state the protobuf CompactionState 2970 */ 2971 public static CompactionState createCompactionState(GetRegionInfoResponse.CompactionState state) { 2972 return CompactionState.valueOf(state.toString()); 2973 } 2974 2975 public static GetRegionInfoResponse.CompactionState createCompactionState(CompactionState state) { 2976 return GetRegionInfoResponse.CompactionState.valueOf(state.toString()); 2977 } 2978 2979 /** 2980 * Creates {@link CompactionState} from {@link RegionLoad.CompactionState} state 2981 * @param state the protobuf CompactionState 2982 */ 2983 public static CompactionState 2984 createCompactionStateForRegionLoad(RegionLoad.CompactionState state) { 2985 return CompactionState.valueOf(state.toString()); 2986 } 2987 2988 public static RegionLoad.CompactionState 2989 createCompactionStateForRegionLoad(CompactionState state) { 2990 return RegionLoad.CompactionState.valueOf(state.toString()); 2991 } 2992 2993 public static Optional<Long> toOptionalTimestamp(MajorCompactionTimestampResponse resp) { 2994 long timestamp = resp.getCompactionTimestamp(); 2995 return timestamp == 0 ? Optional.empty() : Optional.of(timestamp); 2996 } 2997 2998 /** 2999 * Creates {@link SnapshotProtos.SnapshotDescription.Type} from {@link SnapshotType} 3000 * @param type the SnapshotDescription type 3001 * @return the protobuf SnapshotDescription type 3002 */ 3003 public static SnapshotProtos.SnapshotDescription.Type 3004 createProtosSnapShotDescType(SnapshotType type) { 3005 return SnapshotProtos.SnapshotDescription.Type.valueOf(type.name()); 3006 } 3007 3008 /** 3009 * Creates {@link SnapshotProtos.SnapshotDescription.Type} from the type of SnapshotDescription 3010 * string 3011 * @param snapshotDesc string representing the snapshot description type 3012 * @return the protobuf SnapshotDescription type 3013 */ 3014 public static SnapshotProtos.SnapshotDescription.Type 3015 createProtosSnapShotDescType(String snapshotDesc) { 3016 return SnapshotProtos.SnapshotDescription.Type.valueOf(snapshotDesc.toUpperCase(Locale.ROOT)); 3017 } 3018 3019 /** 3020 * Creates {@link SnapshotType} from the {@link SnapshotProtos.SnapshotDescription.Type} 3021 * @param type the snapshot description type 3022 * @return the protobuf SnapshotDescription type 3023 */ 3024 public static SnapshotType createSnapshotType(SnapshotProtos.SnapshotDescription.Type type) { 3025 return SnapshotType.valueOf(type.toString()); 3026 } 3027 3028 /** 3029 * Convert from {@link SnapshotDescription} to {@link SnapshotProtos.SnapshotDescription} 3030 * @param snapshotDesc the POJO SnapshotDescription 3031 * @return the protobuf SnapshotDescription 3032 */ 3033 public static SnapshotProtos.SnapshotDescription 3034 createHBaseProtosSnapshotDesc(SnapshotDescription snapshotDesc) { 3035 SnapshotProtos.SnapshotDescription.Builder builder = 3036 SnapshotProtos.SnapshotDescription.newBuilder(); 3037 if (snapshotDesc.getTableName() != null) { 3038 builder.setTable(snapshotDesc.getTableNameAsString()); 3039 } 3040 if (snapshotDesc.getName() != null) { 3041 builder.setName(snapshotDesc.getName()); 3042 } 3043 if (snapshotDesc.getOwner() != null) { 3044 builder.setOwner(snapshotDesc.getOwner()); 3045 } 3046 if (snapshotDesc.getCreationTime() != -1L) { 3047 builder.setCreationTime(snapshotDesc.getCreationTime()); 3048 } 3049 if ( 3050 snapshotDesc.getTtl() != -1L 3051 && snapshotDesc.getTtl() < TimeUnit.MILLISECONDS.toSeconds(Long.MAX_VALUE) 3052 ) { 3053 builder.setTtl(snapshotDesc.getTtl()); 3054 } 3055 if (snapshotDesc.getVersion() != -1) { 3056 builder.setVersion(snapshotDesc.getVersion()); 3057 } 3058 if (snapshotDesc.getMaxFileSize() != -1) { 3059 builder.setMaxFileSize(snapshotDesc.getMaxFileSize()); 3060 } 3061 builder.setType(ProtobufUtil.createProtosSnapShotDescType(snapshotDesc.getType())); 3062 return builder.build(); 3063 } 3064 3065 /** 3066 * Convert from {@link SnapshotProtos.SnapshotDescription} to {@link SnapshotDescription} 3067 * @param snapshotDesc the protobuf SnapshotDescription 3068 * @return the POJO SnapshotDescription 3069 */ 3070 public static SnapshotDescription 3071 createSnapshotDesc(SnapshotProtos.SnapshotDescription snapshotDesc) { 3072 final Map<String, Object> snapshotProps = new HashMap<>(); 3073 snapshotProps.put("TTL", snapshotDesc.getTtl()); 3074 snapshotProps.put(TableDescriptorBuilder.MAX_FILESIZE, snapshotDesc.getMaxFileSize()); 3075 return new SnapshotDescription(snapshotDesc.getName(), 3076 snapshotDesc.hasTable() ? TableName.valueOf(snapshotDesc.getTable()) : null, 3077 createSnapshotType(snapshotDesc.getType()), snapshotDesc.getOwner(), 3078 snapshotDesc.getCreationTime(), snapshotDesc.getVersion(), snapshotProps); 3079 } 3080 3081 public static RegionLoadStats createRegionLoadStats(ClientProtos.RegionLoadStats stats) { 3082 return new RegionLoadStats(stats.getMemStoreLoad(), stats.getHeapOccupancy(), 3083 stats.getCompactionPressure()); 3084 } 3085 3086 /** Returns A String version of the passed in <code>msg</code> */ 3087 public static String toText(Message msg) { 3088 return TextFormat.shortDebugString(msg); 3089 } 3090 3091 public static byte[] toBytes(ByteString bs) { 3092 return bs.toByteArray(); 3093 } 3094 3095 /** 3096 * Contain ServiceException inside here. Take a callable that is doing our pb rpc and run it. 3097 */ 3098 public static <T> T call(Callable<T> callable) throws IOException { 3099 try { 3100 return callable.call(); 3101 } catch (Exception e) { 3102 throw ProtobufUtil.handleRemoteException(e); 3103 } 3104 } 3105 3106 /** 3107 * Create a protocol buffer GetStoreFileRequest for a given region name 3108 * @param regionName the name of the region to get info 3109 * @param family the family to get store file list 3110 * @return a protocol buffer GetStoreFileRequest 3111 */ 3112 public static GetStoreFileRequest buildGetStoreFileRequest(final byte[] regionName, 3113 final byte[] family) { 3114 GetStoreFileRequest.Builder builder = GetStoreFileRequest.newBuilder(); 3115 RegionSpecifier region = 3116 RequestConverter.buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName); 3117 builder.setRegion(region); 3118 builder.addFamily(UnsafeByteOperations.unsafeWrap(family)); 3119 return builder.build(); 3120 } 3121 3122 /** 3123 * Create a CloseRegionRequest for a given region name 3124 * @param regionName the name of the region to close 3125 * @return a CloseRegionRequest 3126 */ 3127 public static CloseRegionRequest buildCloseRegionRequest(ServerName server, byte[] regionName) { 3128 return ProtobufUtil.buildCloseRegionRequest(server, regionName, null); 3129 } 3130 3131 public static CloseRegionRequest buildCloseRegionRequest(ServerName server, byte[] regionName, 3132 ServerName destinationServer) { 3133 return buildCloseRegionRequest(server, regionName, destinationServer, -1); 3134 } 3135 3136 public static CloseRegionRequest buildCloseRegionRequest(ServerName server, byte[] regionName, 3137 ServerName destinationServer, long closeProcId) { 3138 return ProtobufUtil.getBuilder(server, regionName, destinationServer, closeProcId).build(); 3139 } 3140 3141 public static CloseRegionRequest buildCloseRegionRequest(ServerName server, byte[] regionName, 3142 ServerName destinationServer, long closeProcId, boolean evictCache, 3143 long initiatingMasterActiveTime) { 3144 CloseRegionRequest.Builder builder = 3145 getBuilder(server, regionName, destinationServer, closeProcId); 3146 builder.setEvictCache(evictCache); 3147 builder.setInitiatingMasterActiveTime(initiatingMasterActiveTime); 3148 return builder.build(); 3149 } 3150 3151 public static CloseRegionRequest.Builder getBuilder(ServerName server, byte[] regionName, 3152 ServerName destinationServer, long closeProcId) { 3153 CloseRegionRequest.Builder builder = CloseRegionRequest.newBuilder(); 3154 RegionSpecifier region = 3155 RequestConverter.buildRegionSpecifier(RegionSpecifierType.REGION_NAME, regionName); 3156 builder.setRegion(region); 3157 if (destinationServer != null) { 3158 builder.setDestinationServer(toServerName(destinationServer)); 3159 } 3160 if (server != null) { 3161 builder.setServerStartCode(server.getStartcode()); 3162 } 3163 builder.setCloseProcId(closeProcId); 3164 return builder; 3165 } 3166 3167 public static ProcedureDescription buildProcedureDescription(String signature, String instance, 3168 Map<String, String> props) { 3169 ProcedureDescription.Builder builder = 3170 ProcedureDescription.newBuilder().setSignature(signature).setInstance(instance); 3171 if (props != null && !props.isEmpty()) { 3172 props.entrySet().forEach(entry -> builder.addConfiguration( 3173 NameStringPair.newBuilder().setName(entry.getKey()).setValue(entry.getValue()).build())); 3174 } 3175 return builder.build(); 3176 } 3177 3178 /** 3179 * Get the Meta region state from the passed data bytes. Can handle both old and new style server 3180 * names. 3181 * @param data protobuf serialized data with meta server name. 3182 * @param replicaId replica ID for this region 3183 * @return RegionState instance corresponding to the serialized data. 3184 * @throws DeserializationException if the data is invalid. 3185 */ 3186 public static RegionState parseMetaRegionStateFrom(final byte[] data, int replicaId) 3187 throws DeserializationException { 3188 RegionState.State state = RegionState.State.OPEN; 3189 ServerName serverName; 3190 if (data != null && data.length > 0 && ProtobufUtil.isPBMagicPrefix(data)) { 3191 try { 3192 int prefixLen = ProtobufUtil.lengthOfPBMagic(); 3193 ZooKeeperProtos.MetaRegionServer rl = ZooKeeperProtos.MetaRegionServer.parser() 3194 .parseFrom(data, prefixLen, data.length - prefixLen); 3195 if (rl.hasState()) { 3196 state = RegionState.State.convert(rl.getState()); 3197 } 3198 HBaseProtos.ServerName sn = rl.getServer(); 3199 serverName = ServerName.valueOf(sn.getHostName(), sn.getPort(), sn.getStartCode()); 3200 } catch (InvalidProtocolBufferException e) { 3201 throw new DeserializationException("Unable to parse meta region location"); 3202 } 3203 } else { 3204 // old style of meta region location? 3205 serverName = parseServerNameFrom(data); 3206 } 3207 if (serverName == null) { 3208 state = RegionState.State.OFFLINE; 3209 } 3210 return new RegionState( 3211 RegionReplicaUtil.getRegionInfoForReplica(RegionInfoBuilder.FIRST_META_REGIONINFO, replicaId), 3212 state, serverName); 3213 } 3214 3215 /** 3216 * Get a ServerName from the passed in data bytes. 3217 * @param data Data with a serialize server name in it; can handle the old style servername where 3218 * servername was host and port. Works too with data that begins w/ the pb 'PBUF' 3219 * magic and that is then followed by a protobuf that has a serialized 3220 * {@link ServerName} in it. 3221 * @return Returns null if <code>data</code> is null else converts passed data to a ServerName 3222 * instance. 3223 */ 3224 public static ServerName parseServerNameFrom(final byte[] data) throws DeserializationException { 3225 if (data == null || data.length <= 0) return null; 3226 if (ProtobufMagic.isPBMagicPrefix(data)) { 3227 int prefixLen = ProtobufMagic.lengthOfPBMagic(); 3228 try { 3229 ZooKeeperProtos.Master rss = 3230 ZooKeeperProtos.Master.parser().parseFrom(data, prefixLen, data.length - prefixLen); 3231 org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ServerName sn = 3232 rss.getMaster(); 3233 return ServerName.valueOf(sn.getHostName(), sn.getPort(), sn.getStartCode()); 3234 } catch (/* InvalidProtocolBufferException */IOException e) { 3235 // A failed parse of the znode is pretty catastrophic. Rather than loop 3236 // retrying hoping the bad bytes will changes, and rather than change 3237 // the signature on this method to add an IOE which will send ripples all 3238 // over the code base, throw a RuntimeException. This should "never" happen. 3239 // Fail fast if it does. 3240 throw new DeserializationException(e); 3241 } 3242 } 3243 // The str returned could be old style -- pre hbase-1502 -- which was 3244 // hostname and port seperated by a colon rather than hostname, port and 3245 // startcode delimited by a ','. 3246 String str = Bytes.toString(data); 3247 int index = str.indexOf(ServerName.SERVERNAME_SEPARATOR); 3248 if (index != -1) { 3249 // Presume its ServerName serialized with versioned bytes. 3250 return ServerName.parseVersionedServerName(data); 3251 } 3252 // Presume it a hostname:port format. 3253 String hostname = Addressing.parseHostname(str); 3254 int port = Addressing.parsePort(str); 3255 return ServerName.valueOf(hostname, port, -1L); 3256 } 3257 3258 /** 3259 * Helper to convert the protobuf Procedure to JSON String 3260 * @return Convert the current Protocol Buffers Procedure to JSON String 3261 */ 3262 public static String toProcedureJson(List<ProcedureProtos.Procedure> procProtos) { 3263 JsonArray procJsons = new JsonArray(procProtos.size()); 3264 for (ProcedureProtos.Procedure procProto : procProtos) { 3265 try { 3266 JsonElement procJson = ProtobufMessageConverter.toJsonElement(procProto); 3267 procJsons.add(procJson); 3268 } catch (InvalidProtocolBufferException e) { 3269 procJsons.add(e.toString()); 3270 } 3271 } 3272 return procJsons.toString(); 3273 } 3274 3275 public static String toLockJson(List<LockServiceProtos.LockedResource> lockedResourceProtos) { 3276 JsonArray lockedResourceJsons = new JsonArray(lockedResourceProtos.size()); 3277 for (LockServiceProtos.LockedResource lockedResourceProto : lockedResourceProtos) { 3278 try { 3279 JsonElement lockedResourceJson = 3280 ProtobufMessageConverter.toJsonElement(lockedResourceProto); 3281 lockedResourceJsons.add(lockedResourceJson); 3282 } catch (InvalidProtocolBufferException e) { 3283 lockedResourceJsons.add(e.toString()); 3284 } 3285 } 3286 return lockedResourceJsons.toString(); 3287 } 3288 3289 /** 3290 * Convert a RegionInfo to a Proto RegionInfo 3291 * @param info the RegionInfo to convert 3292 * @return the converted Proto RegionInfo 3293 */ 3294 public static HBaseProtos.RegionInfo 3295 toRegionInfo(final org.apache.hadoop.hbase.client.RegionInfo info) { 3296 if (info == null) { 3297 return null; 3298 } 3299 HBaseProtos.RegionInfo.Builder builder = HBaseProtos.RegionInfo.newBuilder(); 3300 builder.setTableName(ProtobufUtil.toProtoTableName(info.getTable())); 3301 builder.setRegionId(info.getRegionId()); 3302 if (info.getStartKey() != null) { 3303 builder.setStartKey(UnsafeByteOperations.unsafeWrap(info.getStartKey())); 3304 } 3305 if (info.getEndKey() != null) { 3306 builder.setEndKey(UnsafeByteOperations.unsafeWrap(info.getEndKey())); 3307 } 3308 builder.setOffline(info.isOffline()); 3309 builder.setSplit(info.isSplit()); 3310 builder.setReplicaId(info.getReplicaId()); 3311 return builder.build(); 3312 } 3313 3314 /** 3315 * Convert HBaseProto.RegionInfo to a RegionInfo 3316 * @param proto the RegionInfo to convert 3317 * @return the converted RegionInfo 3318 */ 3319 public static org.apache.hadoop.hbase.client.RegionInfo 3320 toRegionInfo(final HBaseProtos.RegionInfo proto) { 3321 if (proto == null) { 3322 return null; 3323 } 3324 TableName tableName = ProtobufUtil.toTableName(proto.getTableName()); 3325 long regionId = proto.getRegionId(); 3326 int defaultReplicaId = org.apache.hadoop.hbase.client.RegionInfo.DEFAULT_REPLICA_ID; 3327 int replicaId = proto.hasReplicaId() ? proto.getReplicaId() : defaultReplicaId; 3328 if (tableName.equals(TableName.META_TABLE_NAME) && replicaId == defaultReplicaId) { 3329 return RegionInfoBuilder.FIRST_META_REGIONINFO; 3330 } 3331 byte[] startKey = null; 3332 byte[] endKey = null; 3333 if (proto.hasStartKey()) { 3334 startKey = proto.getStartKey().toByteArray(); 3335 } 3336 if (proto.hasEndKey()) { 3337 endKey = proto.getEndKey().toByteArray(); 3338 } 3339 boolean split = false; 3340 if (proto.hasSplit()) { 3341 split = proto.getSplit(); 3342 } 3343 RegionInfoBuilder rib = RegionInfoBuilder.newBuilder(tableName).setStartKey(startKey) 3344 .setEndKey(endKey).setRegionId(regionId).setReplicaId(replicaId).setSplit(split); 3345 if (proto.hasOffline()) { 3346 rib.setOffline(proto.getOffline()); 3347 } 3348 return rib.build(); 3349 } 3350 3351 public static HBaseProtos.RegionLocation toRegionLocation(HRegionLocation loc) { 3352 HBaseProtos.RegionLocation.Builder builder = HBaseProtos.RegionLocation.newBuilder(); 3353 builder.setRegionInfo(toRegionInfo(loc.getRegion())); 3354 if (loc.getServerName() != null) { 3355 builder.setServerName(toServerName(loc.getServerName())); 3356 } 3357 builder.setSeqNum(loc.getSeqNum()); 3358 return builder.build(); 3359 } 3360 3361 public static HRegionLocation toRegionLocation(HBaseProtos.RegionLocation proto) { 3362 org.apache.hadoop.hbase.client.RegionInfo regionInfo = toRegionInfo(proto.getRegionInfo()); 3363 ServerName serverName = proto.hasServerName() ? toServerName(proto.getServerName()) : null; 3364 return new HRegionLocation(regionInfo, serverName, proto.getSeqNum()); 3365 } 3366 3367 public static List<SnapshotDescription> 3368 toSnapshotDescriptionList(GetCompletedSnapshotsResponse response, Pattern pattern) { 3369 return response.getSnapshotsList().stream().map(ProtobufUtil::createSnapshotDesc) 3370 .filter(snap -> pattern != null ? pattern.matcher(snap.getName()).matches() : true) 3371 .collect(Collectors.toList()); 3372 } 3373 3374 public static CacheEvictionStats toCacheEvictionStats(HBaseProtos.CacheEvictionStats stats) 3375 throws IOException { 3376 CacheEvictionStatsBuilder builder = CacheEvictionStats.builder(); 3377 builder.withEvictedBlocks(stats.getEvictedBlocks()).withMaxCacheSize(stats.getMaxCacheSize()); 3378 if (stats.getExceptionCount() > 0) { 3379 for (HBaseProtos.RegionExceptionMessage exception : stats.getExceptionList()) { 3380 HBaseProtos.RegionSpecifier rs = exception.getRegion(); 3381 byte[] regionName = rs.getValue().toByteArray(); 3382 builder.addException(regionName, ProtobufUtil.toException(exception.getException())); 3383 } 3384 } 3385 return builder.build(); 3386 } 3387 3388 public static HBaseProtos.CacheEvictionStats 3389 toCacheEvictionStats(CacheEvictionStats cacheEvictionStats) { 3390 HBaseProtos.CacheEvictionStats.Builder builder = HBaseProtos.CacheEvictionStats.newBuilder(); 3391 for (Map.Entry<byte[], Throwable> entry : cacheEvictionStats.getExceptions().entrySet()) { 3392 builder.addException(RegionExceptionMessage.newBuilder() 3393 .setRegion( 3394 RequestConverter.buildRegionSpecifier(RegionSpecifierType.REGION_NAME, entry.getKey())) 3395 .setException(ResponseConverter.buildException(entry.getValue())).build()); 3396 } 3397 return builder.setEvictedBlocks(cacheEvictionStats.getEvictedBlocks()) 3398 .setMaxCacheSize(cacheEvictionStats.getMaxCacheSize()).build(); 3399 } 3400 3401 public static ClusterStatusProtos.ReplicationLoadSource 3402 toReplicationLoadSource(ReplicationLoadSource rls) { 3403 return ClusterStatusProtos.ReplicationLoadSource.newBuilder().setPeerID(rls.getPeerID()) 3404 .setAgeOfLastShippedOp(rls.getAgeOfLastShippedOp()) 3405 .setSizeOfLogQueue((int) rls.getSizeOfLogQueue()) 3406 .setTimeStampOfLastShippedOp(rls.getTimestampOfLastShippedOp()) 3407 .setReplicationLag(rls.getReplicationLag()).setQueueId(rls.getQueueId()) 3408 .setRecovered(rls.isRecovered()).setRunning(rls.isRunning()) 3409 .setEditsSinceRestart(rls.hasEditsSinceRestart()) 3410 .setTimeStampOfNextToReplicate(rls.getTimeStampOfNextToReplicate()) 3411 .setOPsShipped(rls.getOPsShipped()).setEditsRead(rls.getEditsRead()).build(); 3412 } 3413 3414 public static ClusterStatusProtos.ReplicationLoadSink 3415 toReplicationLoadSink(ReplicationLoadSink rls) { 3416 return ClusterStatusProtos.ReplicationLoadSink.newBuilder() 3417 .setAgeOfLastAppliedOp(rls.getAgeOfLastAppliedOp()) 3418 .setTimeStampsOfLastAppliedOp(rls.getTimestampsOfLastAppliedOp()) 3419 .setTimestampStarted(rls.getTimestampStarted()) 3420 .setTotalOpsProcessed(rls.getTotalOpsProcessed()).build(); 3421 } 3422 3423 public static HBaseProtos.TimeRange toTimeRange(TimeRange timeRange) { 3424 if (timeRange == null) { 3425 timeRange = TimeRange.allTime(); 3426 } 3427 return HBaseProtos.TimeRange.newBuilder().setFrom(timeRange.getMin()).setTo(timeRange.getMax()) 3428 .build(); 3429 } 3430 3431 public static byte[] toCompactionEventTrackerBytes(Set<String> storeFiles) { 3432 HFileProtos.CompactionEventTracker.Builder builder = 3433 HFileProtos.CompactionEventTracker.newBuilder(); 3434 storeFiles.forEach(sf -> builder.addCompactedStoreFile(ByteString.copyFromUtf8(sf))); 3435 return ProtobufUtil.prependPBMagic(builder.build().toByteArray()); 3436 } 3437 3438 public static Set<String> toCompactedStoreFiles(byte[] bytes) throws IOException { 3439 if (bytes != null && ProtobufUtil.isPBMagicPrefix(bytes)) { 3440 int pbLen = ProtobufUtil.lengthOfPBMagic(); 3441 HFileProtos.CompactionEventTracker.Builder builder = 3442 HFileProtos.CompactionEventTracker.newBuilder(); 3443 ProtobufUtil.mergeFrom(builder, bytes, pbLen, bytes.length - pbLen); 3444 HFileProtos.CompactionEventTracker compactionEventTracker = builder.build(); 3445 List<ByteString> compactedStoreFiles = compactionEventTracker.getCompactedStoreFileList(); 3446 if (compactedStoreFiles != null && compactedStoreFiles.size() != 0) { 3447 return compactedStoreFiles.stream().map(ByteString::toStringUtf8) 3448 .collect(Collectors.toSet()); 3449 } 3450 } 3451 return Collections.emptySet(); 3452 } 3453 3454 public static ClusterStatusProtos.RegionStatesCount 3455 toTableRegionStatesCount(RegionStatesCount regionStatesCount) { 3456 int openRegions = 0; 3457 int splitRegions = 0; 3458 int closedRegions = 0; 3459 int regionsInTransition = 0; 3460 int totalRegions = 0; 3461 if (regionStatesCount != null) { 3462 openRegions = regionStatesCount.getOpenRegions(); 3463 splitRegions = regionStatesCount.getSplitRegions(); 3464 closedRegions = regionStatesCount.getClosedRegions(); 3465 regionsInTransition = regionStatesCount.getRegionsInTransition(); 3466 totalRegions = regionStatesCount.getTotalRegions(); 3467 } 3468 return ClusterStatusProtos.RegionStatesCount.newBuilder().setOpenRegions(openRegions) 3469 .setSplitRegions(splitRegions).setClosedRegions(closedRegions) 3470 .setRegionsInTransition(regionsInTransition).setTotalRegions(totalRegions).build(); 3471 } 3472 3473 public static RegionStatesCount 3474 toTableRegionStatesCount(ClusterStatusProtos.RegionStatesCount regionStatesCount) { 3475 int openRegions = 0; 3476 int splitRegions = 0; 3477 int closedRegions = 0; 3478 int regionsInTransition = 0; 3479 int totalRegions = 0; 3480 if (regionStatesCount != null) { 3481 closedRegions = regionStatesCount.getClosedRegions(); 3482 regionsInTransition = regionStatesCount.getRegionsInTransition(); 3483 openRegions = regionStatesCount.getOpenRegions(); 3484 splitRegions = regionStatesCount.getSplitRegions(); 3485 totalRegions = regionStatesCount.getTotalRegions(); 3486 } 3487 return new RegionStatesCount.RegionStatesCountBuilder().setOpenRegions(openRegions) 3488 .setSplitRegions(splitRegions).setClosedRegions(closedRegions) 3489 .setRegionsInTransition(regionsInTransition).setTotalRegions(totalRegions).build(); 3490 } 3491 3492 /** 3493 * Convert Protobuf class 3494 * {@link org.apache.hadoop.hbase.shaded.protobuf.generated.TooSlowLog.SlowLogPayload} To client 3495 * SlowLog Payload class {@link OnlineLogRecord} 3496 * @param slowLogPayload SlowLog Payload protobuf instance 3497 * @return SlowLog Payload for client usecase 3498 */ 3499 private static LogEntry getSlowLogRecord(final TooSlowLog.SlowLogPayload slowLogPayload) { 3500 OnlineLogRecord.OnlineLogRecordBuilder onlineLogRecord = 3501 new OnlineLogRecord.OnlineLogRecordBuilder().setCallDetails(slowLogPayload.getCallDetails()) 3502 .setClientAddress(slowLogPayload.getClientAddress()) 3503 .setMethodName(slowLogPayload.getMethodName()) 3504 .setMultiGetsCount(slowLogPayload.getMultiGets()) 3505 .setMultiMutationsCount(slowLogPayload.getMultiMutations()) 3506 .setMultiServiceCalls(slowLogPayload.getMultiServiceCalls()) 3507 .setParam(slowLogPayload.getParam()).setProcessingTime(slowLogPayload.getProcessingTime()) 3508 .setQueueTime(slowLogPayload.getQueueTime()).setRegionName(slowLogPayload.getRegionName()) 3509 .setResponseSize(slowLogPayload.getResponseSize()) 3510 .setBlockBytesScanned(slowLogPayload.getBlockBytesScanned()) 3511 .setFsReadTime(slowLogPayload.getFsReadTime()) 3512 .setServerClass(slowLogPayload.getServerClass()).setStartTime(slowLogPayload.getStartTime()) 3513 .setUserName(slowLogPayload.getUserName()) 3514 .setRequestAttributes(convertNameBytesPairsToMap(slowLogPayload.getRequestAttributeList())) 3515 .setConnectionAttributes( 3516 convertNameBytesPairsToMap(slowLogPayload.getConnectionAttributeList())); 3517 if (slowLogPayload.hasScan()) { 3518 try { 3519 onlineLogRecord.setScan(ProtobufUtil.toScan(slowLogPayload.getScan())); 3520 } catch (Exception e) { 3521 LOG.warn("Failed to convert Scan proto {}", slowLogPayload.getScan(), e); 3522 } 3523 } 3524 return onlineLogRecord.build(); 3525 } 3526 3527 private static Map<String, byte[]> 3528 convertNameBytesPairsToMap(List<NameBytesPair> nameBytesPairs) { 3529 return nameBytesPairs.stream().collect(Collectors.toMap(NameBytesPair::getName, 3530 nameBytesPair -> nameBytesPair.getValue().toByteArray())); 3531 } 3532 3533 /** 3534 * Convert AdminProtos#SlowLogResponses to list of {@link OnlineLogRecord} 3535 * @param logEntry slowlog response protobuf instance 3536 * @return list of SlowLog payloads for client usecase 3537 */ 3538 public static List<LogEntry> toSlowLogPayloads(final HBaseProtos.LogEntry logEntry) { 3539 try { 3540 final String logClassName = logEntry.getLogClassName(); 3541 Class<?> logClass = Class.forName(logClassName).asSubclass(Message.class); 3542 Method method = logClass.getMethod("parseFrom", ByteString.class); 3543 if (logClassName.contains("SlowLogResponses")) { 3544 AdminProtos.SlowLogResponses slowLogResponses = 3545 (AdminProtos.SlowLogResponses) method.invoke(null, logEntry.getLogMessage()); 3546 return slowLogResponses.getSlowLogPayloadsList().stream() 3547 .map(ProtobufUtil::getSlowLogRecord).collect(Collectors.toList()); 3548 } 3549 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException 3550 | InvocationTargetException e) { 3551 throw new RuntimeException("Error while retrieving response from server"); 3552 } 3553 throw new RuntimeException("Invalid response from server"); 3554 } 3555 3556 /** 3557 * Convert {@link ClearSlowLogResponses} to boolean 3558 * @param clearSlowLogResponses Clear slowlog response protobuf instance 3559 * @return boolean representing clear slowlog response 3560 */ 3561 public static boolean toClearSlowLogPayload(final ClearSlowLogResponses clearSlowLogResponses) { 3562 return clearSlowLogResponses.getIsCleaned(); 3563 } 3564 3565 public static void populateBalanceRSGroupResponse( 3566 RSGroupAdminProtos.BalanceRSGroupResponse.Builder responseBuilder, BalanceResponse response) { 3567 responseBuilder.setBalanceRan(response.isBalancerRan()) 3568 .setMovesCalculated(response.getMovesCalculated()) 3569 .setMovesExecuted(response.getMovesExecuted()); 3570 } 3571 3572 public static BalanceResponse 3573 toBalanceResponse(RSGroupAdminProtos.BalanceRSGroupResponse response) { 3574 return BalanceResponse.newBuilder().setBalancerRan(response.getBalanceRan()) 3575 .setMovesExecuted(response.hasMovesExecuted() ? response.getMovesExecuted() : 0) 3576 .setMovesCalculated(response.hasMovesCalculated() ? response.getMovesCalculated() : 0) 3577 .build(); 3578 } 3579 3580 public static RSGroupAdminProtos.BalanceRSGroupRequest 3581 createBalanceRSGroupRequest(String groupName, BalanceRequest request) { 3582 return RSGroupAdminProtos.BalanceRSGroupRequest.newBuilder().setRSGroupName(groupName) 3583 .setDryRun(request.isDryRun()).setIgnoreRit(request.isIgnoreRegionsInTransition()).build(); 3584 } 3585 3586 public static BalanceRequest toBalanceRequest(RSGroupAdminProtos.BalanceRSGroupRequest request) { 3587 return BalanceRequest.newBuilder().setDryRun(request.hasDryRun() && request.getDryRun()) 3588 .setIgnoreRegionsInTransition(request.hasIgnoreRit() && request.getIgnoreRit()).build(); 3589 } 3590 3591 public static RSGroupInfo toGroupInfo(RSGroupProtos.RSGroupInfo proto) { 3592 RSGroupInfo rsGroupInfo = new RSGroupInfo(proto.getName()); 3593 3594 Collection<Address> addresses = proto.getServersList().parallelStream() 3595 .map(serverName -> Address.fromParts(serverName.getHostName(), serverName.getPort())) 3596 .collect(Collectors.toList()); 3597 rsGroupInfo.addAllServers(addresses); 3598 3599 Collection<TableName> tables = proto.getTablesList().parallelStream() 3600 .map(ProtobufUtil::toTableName).collect(Collectors.toList()); 3601 rsGroupInfo.addAllTables(tables); 3602 3603 proto.getConfigurationList() 3604 .forEach(pair -> rsGroupInfo.setConfiguration(pair.getName(), pair.getValue())); 3605 return rsGroupInfo; 3606 } 3607 3608 public static RSGroupProtos.RSGroupInfo toProtoGroupInfo(RSGroupInfo pojo) { 3609 List<HBaseProtos.TableName> tables = new ArrayList<>(pojo.getTables().size()); 3610 for (TableName arg : pojo.getTables()) { 3611 tables.add(ProtobufUtil.toProtoTableName(arg)); 3612 } 3613 List<HBaseProtos.ServerName> hostports = new ArrayList<>(pojo.getServers().size()); 3614 for (Address el : pojo.getServers()) { 3615 hostports.add(HBaseProtos.ServerName.newBuilder().setHostName(el.getHostname()) 3616 .setPort(el.getPort()).build()); 3617 } 3618 List< 3619 NameStringPair> configuration = 3620 pojo 3621 .getConfiguration().entrySet().stream().map(entry -> NameStringPair.newBuilder() 3622 .setName(entry.getKey()).setValue(entry.getValue()).build()) 3623 .collect(Collectors.toList()); 3624 return RSGroupProtos.RSGroupInfo.newBuilder().setName(pojo.getName()).addAllServers(hostports) 3625 .addAllTables(tables).addAllConfiguration(configuration).build(); 3626 } 3627 3628 public static CheckAndMutate toCheckAndMutate(ClientProtos.Condition condition, 3629 MutationProto mutation, CellScanner cellScanner) throws IOException { 3630 byte[] row = condition.getRow().toByteArray(); 3631 CheckAndMutate.Builder builder = CheckAndMutate.newBuilder(row); 3632 Filter filter = condition.hasFilter() ? ProtobufUtil.toFilter(condition.getFilter()) : null; 3633 if (filter != null) { 3634 builder.ifMatches(filter); 3635 } else { 3636 builder.ifMatches(condition.getFamily().toByteArray(), condition.getQualifier().toByteArray(), 3637 CompareOperator.valueOf(condition.getCompareType().name()), 3638 ProtobufUtil.toComparator(condition.getComparator()).getValue()); 3639 } 3640 TimeRange timeRange = condition.hasTimeRange() 3641 ? ProtobufUtil.toTimeRange(condition.getTimeRange()) 3642 : TimeRange.allTime(); 3643 builder.timeRange(timeRange); 3644 builder.queryMetricsEnabled(condition.getQueryMetricsEnabled()); 3645 3646 try { 3647 MutationType type = mutation.getMutateType(); 3648 switch (type) { 3649 case PUT: 3650 return builder.build(ProtobufUtil.toPut(mutation, cellScanner)); 3651 case DELETE: 3652 return builder.build(ProtobufUtil.toDelete(mutation, cellScanner)); 3653 case INCREMENT: 3654 return builder.build(ProtobufUtil.toIncrement(mutation, cellScanner)); 3655 case APPEND: 3656 return builder.build(ProtobufUtil.toAppend(mutation, cellScanner)); 3657 default: 3658 throw new DoNotRetryIOException("Unsupported mutate type: " + type.name()); 3659 } 3660 } catch (IllegalArgumentException e) { 3661 throw new DoNotRetryIOException(e.getMessage()); 3662 } 3663 } 3664 3665 public static CheckAndMutate toCheckAndMutate(ClientProtos.Condition condition, 3666 List<Mutation> mutations) throws IOException { 3667 assert mutations.size() > 0; 3668 byte[] row = condition.getRow().toByteArray(); 3669 CheckAndMutate.Builder builder = CheckAndMutate.newBuilder(row); 3670 Filter filter = condition.hasFilter() ? ProtobufUtil.toFilter(condition.getFilter()) : null; 3671 if (filter != null) { 3672 builder.ifMatches(filter); 3673 } else { 3674 builder.ifMatches(condition.getFamily().toByteArray(), condition.getQualifier().toByteArray(), 3675 CompareOperator.valueOf(condition.getCompareType().name()), 3676 ProtobufUtil.toComparator(condition.getComparator()).getValue()); 3677 } 3678 TimeRange timeRange = condition.hasTimeRange() 3679 ? ProtobufUtil.toTimeRange(condition.getTimeRange()) 3680 : TimeRange.allTime(); 3681 builder.timeRange(timeRange); 3682 builder.queryMetricsEnabled(condition.getQueryMetricsEnabled()); 3683 3684 try { 3685 if (mutations.size() == 1) { 3686 Mutation m = mutations.get(0); 3687 if (m instanceof Put) { 3688 return builder.build((Put) m); 3689 } else if (m instanceof Delete) { 3690 return builder.build((Delete) m); 3691 } else if (m instanceof Increment) { 3692 return builder.build((Increment) m); 3693 } else if (m instanceof Append) { 3694 return builder.build((Append) m); 3695 } else { 3696 throw new DoNotRetryIOException( 3697 "Unsupported mutate type: " + m.getClass().getSimpleName().toUpperCase()); 3698 } 3699 } else { 3700 return builder.build(new RowMutations(mutations.get(0).getRow()).add(mutations)); 3701 } 3702 } catch (IllegalArgumentException e) { 3703 throw new DoNotRetryIOException(e.getMessage()); 3704 } 3705 } 3706 3707 public static ClientProtos.Condition toCondition(final byte[] row, final byte[] family, 3708 final byte[] qualifier, final CompareOperator op, final byte[] value, final Filter filter, 3709 final TimeRange timeRange, boolean queryMetricsEnabled) throws IOException { 3710 3711 ClientProtos.Condition.Builder builder = 3712 ClientProtos.Condition.newBuilder().setRow(UnsafeByteOperations.unsafeWrap(row)); 3713 3714 if (filter != null) { 3715 builder.setFilter(ProtobufUtil.toFilter(filter)); 3716 } else { 3717 builder.setFamily(UnsafeByteOperations.unsafeWrap(family)) 3718 .setQualifier(UnsafeByteOperations 3719 .unsafeWrap(qualifier == null ? HConstants.EMPTY_BYTE_ARRAY : qualifier)) 3720 .setComparator(ProtobufUtil.toComparator(new BinaryComparator(value))) 3721 .setCompareType(HBaseProtos.CompareType.valueOf(op.name())); 3722 } 3723 3724 builder.setQueryMetricsEnabled(queryMetricsEnabled); 3725 return builder.setTimeRange(ProtobufUtil.toTimeRange(timeRange)).build(); 3726 } 3727 3728 public static ClientProtos.Condition toCondition(final byte[] row, final Filter filter, 3729 final TimeRange timeRange) throws IOException { 3730 return toCondition(row, null, null, null, null, filter, timeRange, false); 3731 } 3732 3733 public static ClientProtos.Condition toCondition(final byte[] row, final byte[] family, 3734 final byte[] qualifier, final CompareOperator op, final byte[] value, final TimeRange timeRange) 3735 throws IOException { 3736 return toCondition(row, family, qualifier, op, value, null, timeRange, false); 3737 } 3738 3739 public static List<LogEntry> toBalancerDecisionResponse(HBaseProtos.LogEntry logEntry) { 3740 try { 3741 final String logClassName = logEntry.getLogClassName(); 3742 Class<?> logClass = Class.forName(logClassName).asSubclass(Message.class); 3743 Method method = logClass.getMethod("parseFrom", ByteString.class); 3744 if (logClassName.contains("BalancerDecisionsResponse")) { 3745 MasterProtos.BalancerDecisionsResponse response = 3746 (MasterProtos.BalancerDecisionsResponse) method.invoke(null, logEntry.getLogMessage()); 3747 return getBalancerDecisionEntries(response); 3748 } 3749 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException 3750 | InvocationTargetException e) { 3751 throw new RuntimeException("Error while retrieving response from server"); 3752 } 3753 throw new RuntimeException("Invalid response from server"); 3754 } 3755 3756 public static List<LogEntry> toBalancerRejectionResponse(HBaseProtos.LogEntry logEntry) { 3757 try { 3758 final String logClassName = logEntry.getLogClassName(); 3759 Class<?> logClass = Class.forName(logClassName).asSubclass(Message.class); 3760 Method method = logClass.getMethod("parseFrom", ByteString.class); 3761 if (logClassName.contains("BalancerRejectionsResponse")) { 3762 MasterProtos.BalancerRejectionsResponse response = 3763 (MasterProtos.BalancerRejectionsResponse) method.invoke(null, logEntry.getLogMessage()); 3764 return getBalancerRejectionEntries(response); 3765 } 3766 } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException 3767 | InvocationTargetException e) { 3768 throw new RuntimeException("Error while retrieving response from server"); 3769 } 3770 throw new RuntimeException("Invalid response from server"); 3771 } 3772 3773 public static List<LogEntry> 3774 getBalancerDecisionEntries(MasterProtos.BalancerDecisionsResponse response) { 3775 List<RecentLogs.BalancerDecision> balancerDecisions = response.getBalancerDecisionList(); 3776 if (CollectionUtils.isEmpty(balancerDecisions)) { 3777 return Collections.emptyList(); 3778 } 3779 return balancerDecisions.stream() 3780 .map(balancerDecision -> new BalancerDecision.Builder() 3781 .setInitTotalCost(balancerDecision.getInitTotalCost()) 3782 .setInitialFunctionCosts(balancerDecision.getInitialFunctionCosts()) 3783 .setComputedTotalCost(balancerDecision.getComputedTotalCost()) 3784 .setFinalFunctionCosts(balancerDecision.getFinalFunctionCosts()) 3785 .setComputedSteps(balancerDecision.getComputedSteps()) 3786 .setRegionPlans(balancerDecision.getRegionPlansList()).build()) 3787 .collect(Collectors.toList()); 3788 } 3789 3790 public static List<LogEntry> 3791 getBalancerRejectionEntries(MasterProtos.BalancerRejectionsResponse response) { 3792 List<RecentLogs.BalancerRejection> balancerRejections = response.getBalancerRejectionList(); 3793 if (CollectionUtils.isEmpty(balancerRejections)) { 3794 return Collections.emptyList(); 3795 } 3796 return balancerRejections.stream() 3797 .map(balancerRejection -> new BalancerRejection.Builder() 3798 .setReason(balancerRejection.getReason()) 3799 .setCostFuncInfoList(balancerRejection.getCostFuncInfoList()).build()) 3800 .collect(Collectors.toList()); 3801 } 3802 3803 public static HBaseProtos.LogRequest toBalancerDecisionRequest(int limit) { 3804 MasterProtos.BalancerDecisionsRequest balancerDecisionsRequest = 3805 MasterProtos.BalancerDecisionsRequest.newBuilder().setLimit(limit).build(); 3806 return HBaseProtos.LogRequest.newBuilder() 3807 .setLogClassName(balancerDecisionsRequest.getClass().getName()) 3808 .setLogMessage(balancerDecisionsRequest.toByteString()).build(); 3809 } 3810 3811 public static HBaseProtos.LogRequest toBalancerRejectionRequest(int limit) { 3812 MasterProtos.BalancerRejectionsRequest balancerRejectionsRequest = 3813 MasterProtos.BalancerRejectionsRequest.newBuilder().setLimit(limit).build(); 3814 return HBaseProtos.LogRequest.newBuilder() 3815 .setLogClassName(balancerRejectionsRequest.getClass().getName()) 3816 .setLogMessage(balancerRejectionsRequest.toByteString()).build(); 3817 } 3818 3819 public static MasterProtos.BalanceRequest toBalanceRequest(BalanceRequest request) { 3820 return MasterProtos.BalanceRequest.newBuilder().setDryRun(request.isDryRun()) 3821 .setIgnoreRit(request.isIgnoreRegionsInTransition()).build(); 3822 } 3823 3824 public static BalanceRequest toBalanceRequest(MasterProtos.BalanceRequest request) { 3825 return BalanceRequest.newBuilder().setDryRun(request.hasDryRun() && request.getDryRun()) 3826 .setIgnoreRegionsInTransition(request.hasIgnoreRit() && request.getIgnoreRit()).build(); 3827 } 3828 3829 public static MasterProtos.BalanceResponse toBalanceResponse(BalanceResponse response) { 3830 return MasterProtos.BalanceResponse.newBuilder().setBalancerRan(response.isBalancerRan()) 3831 .setMovesCalculated(response.getMovesCalculated()) 3832 .setMovesExecuted(response.getMovesExecuted()).build(); 3833 } 3834 3835 public static BalanceResponse toBalanceResponse(MasterProtos.BalanceResponse response) { 3836 return BalanceResponse.newBuilder() 3837 .setBalancerRan(response.hasBalancerRan() && response.getBalancerRan()) 3838 .setMovesCalculated(response.hasMovesCalculated() ? response.getMovesExecuted() : 0) 3839 .setMovesExecuted(response.hasMovesExecuted() ? response.getMovesExecuted() : 0).build(); 3840 } 3841 3842 public static ServerTask getServerTask(ClusterStatusProtos.ServerTask task) { 3843 return ServerTaskBuilder.newBuilder().setDescription(task.getDescription()) 3844 .setStatus(task.getStatus()).setState(ServerTask.State.valueOf(task.getState().name())) 3845 .setStartTime(task.getStartTime()).setCompletionTime(task.getCompletionTime()).build(); 3846 } 3847 3848 public static ClusterStatusProtos.ServerTask toServerTask(ServerTask task) { 3849 return ClusterStatusProtos.ServerTask.newBuilder().setDescription(task.getDescription()) 3850 .setStatus(task.getStatus()) 3851 .setState(ClusterStatusProtos.ServerTask.State.valueOf(task.getState().name())) 3852 .setStartTime(task.getStartTime()).setCompletionTime(task.getCompletionTime()).build(); 3853 } 3854 3855 public static ClientProtos.QueryMetrics toQueryMetrics(QueryMetrics metrics) { 3856 return ClientProtos.QueryMetrics.newBuilder() 3857 .setBlockBytesScanned(metrics.getBlockBytesScanned()).build(); 3858 } 3859 3860 public static QueryMetrics toQueryMetrics(ClientProtos.QueryMetrics metrics) { 3861 return new QueryMetrics(metrics.getBlockBytesScanned()); 3862 } 3863 3864 /** 3865 * Check whether this IPBE indicates EOF or not. 3866 * <p/> 3867 * We will check the exception message, if it is likely the one of 3868 * InvalidProtocolBufferException.truncatedMessage, we will consider it as EOF, otherwise not. 3869 */ 3870 public static boolean isEOF(InvalidProtocolBufferException e) { 3871 return e.getMessage().contains("input has been truncated"); 3872 } 3873 3874 /** 3875 * This is a wrapper of the PB message's parseDelimitedFrom. The difference is, if we can not 3876 * determine whether there are enough bytes in stream, i.e, the available method does not have a 3877 * valid return value, we will try to read all the bytes to a byte array first, and then parse the 3878 * pb message with {@link Parser#parseFrom(byte[])} instead of call 3879 * {@link Parser#parseDelimitedFrom(InputStream)} directly. This is because even if the bytes are 3880 * not enough bytes, {@link Parser#parseDelimitedFrom(InputStream)} could still return without any 3881 * errors but just leave us a partial PB message. 3882 * @return The PB message if we can parse it successfully, otherwise there will always be an 3883 * exception thrown, will never return {@code null}. 3884 */ 3885 public static <T extends Message> T parseDelimitedFrom(InputStream in, Parser<T> parser) 3886 throws IOException { 3887 int firstByte = in.read(); 3888 if (firstByte < 0) { 3889 throw new EOFException("EOF while reading message size"); 3890 } 3891 int size = CodedInputStream.readRawVarint32(firstByte, in); 3892 int available = in.available(); 3893 if (available > 0) { 3894 if (available < size) { 3895 throw new EOFException("Available bytes not enough for parsing PB message, expect at least " 3896 + size + " bytes, but only " + available + " bytes available"); 3897 } 3898 // this piece of code is copied from GeneratedMessageV3.parseFrom 3899 try { 3900 return parser.parseFrom(ByteStreams.limit(in, size)); 3901 } catch (InvalidProtocolBufferException e) { 3902 throw e.unwrapIOException(); 3903 } 3904 } else { 3905 // this usually means the stream does not have a proper available implementation, let's read 3906 // the content to an byte array before parsing. 3907 byte[] bytes = new byte[size]; 3908 ByteStreams.readFully(in, bytes); 3909 return parser.parseFrom(bytes); 3910 } 3911 } 3912}