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.wal; 019 020import java.io.IOException; 021import java.util.ArrayList; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.NavigableMap; 026import java.util.TreeMap; 027import java.util.UUID; 028import org.apache.hadoop.hbase.HBaseInterfaceAudience; 029import org.apache.hadoop.hbase.HConstants; 030import org.apache.hadoop.hbase.TableName; 031import org.apache.hadoop.hbase.regionserver.MultiVersionConcurrencyControl; 032import org.apache.hadoop.hbase.regionserver.SequenceId; 033import org.apache.hadoop.hbase.regionserver.wal.CompressionContext; 034import org.apache.hadoop.hbase.regionserver.wal.WALCellCodec; 035import org.apache.hadoop.hbase.util.Bytes; 036import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 037import org.apache.yetus.audience.InterfaceAudience; 038 039import org.apache.hbase.thirdparty.com.google.protobuf.ByteString; 040 041import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos; 042import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos; 043import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.FamilyScope; 044import org.apache.hadoop.hbase.shaded.protobuf.generated.WALProtos.ScopeType; 045 046/** 047 * Default implementation of Key for an Entry in the WAL. For internal use only though Replication 048 * needs to have access. The log intermingles edits to many tables and rows, so each log entry 049 * identifies the appropriate table and row. Within a table and row, they're also sorted. 050 * <p> 051 * Some Transactional edits (START, COMMIT, ABORT) will not have an associated row. 052 */ 053// TODO: Key and WALEdit are never used separately, or in one-to-many relation, for practical 054// purposes. They need to be merged into WALEntry. 055@InterfaceAudience.LimitedPrivate({ HBaseInterfaceAudience.REPLICATION }) 056public class WALKeyImpl implements WALKey { 057 public static final WALKeyImpl EMPTY_WALKEYIMPL = new WALKeyImpl(); 058 059 public MultiVersionConcurrencyControl getMvcc() { 060 return mvcc; 061 } 062 063 /** 064 * Use it to complete mvcc transaction. This WALKeyImpl was part of (the transaction is started 065 * when you call append; see the comment on FSHLog#append). To complete call 066 * {@link MultiVersionConcurrencyControl#complete(MultiVersionConcurrencyControl.WriteEntry)} or 067 * {@link MultiVersionConcurrencyControl#complete(MultiVersionConcurrencyControl.WriteEntry)} 068 * @return A WriteEntry gotten from local WAL subsystem. 069 * @see #setWriteEntry(MultiVersionConcurrencyControl.WriteEntry) 070 */ 071 public MultiVersionConcurrencyControl.WriteEntry getWriteEntry() { 072 return this.writeEntry; 073 } 074 075 public void setWriteEntry(MultiVersionConcurrencyControl.WriteEntry writeEntry) { 076 assert this.writeEntry == null; 077 this.writeEntry = writeEntry; 078 // Set our sequenceid now using WriteEntry. 079 this.sequenceId = writeEntry.getWriteNumber(); 080 } 081 082 private byte[] encodedRegionName; 083 084 private TableName tablename; 085 086 /** 087 * SequenceId for this edit. Set post-construction at write-to-WAL time. Until then it is 088 * NO_SEQUENCE_ID. Change it so multiple threads can read it -- e.g. access is synchronized. 089 */ 090 private long sequenceId; 091 092 /** 093 * Used during WAL replay; the sequenceId of the edit when it came into the system. 094 */ 095 private long origLogSeqNum = 0; 096 097 /** Time at which this edit was written. */ 098 private long writeTime; 099 100 /** The first element in the list is the cluster id on which the change has originated */ 101 private List<UUID> clusterIds; 102 103 private NavigableMap<byte[], Integer> replicationScope; 104 105 private long nonceGroup = HConstants.NO_NONCE; 106 private long nonce = HConstants.NO_NONCE; 107 private MultiVersionConcurrencyControl mvcc; 108 109 /** 110 * Set in a way visible to multiple threads; e.g. synchronized getter/setters. 111 */ 112 private MultiVersionConcurrencyControl.WriteEntry writeEntry; 113 114 private Map<String, byte[]> extendedAttributes; 115 116 public WALKeyImpl() { 117 init(null, null, 0L, HConstants.LATEST_TIMESTAMP, new ArrayList<>(), HConstants.NO_NONCE, 118 HConstants.NO_NONCE, null, null, null); 119 } 120 121 public WALKeyImpl(final NavigableMap<byte[], Integer> replicationScope) { 122 init(null, null, 0L, HConstants.LATEST_TIMESTAMP, new ArrayList<>(), HConstants.NO_NONCE, 123 HConstants.NO_NONCE, null, replicationScope, null); 124 } 125 126 @InterfaceAudience.Private 127 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 128 final long now, UUID clusterId) { 129 List<UUID> clusterIds = new ArrayList<>(1); 130 clusterIds.add(clusterId); 131 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, HConstants.NO_NONCE, 132 HConstants.NO_NONCE, null, null, null); 133 } 134 135 // TODO: Fix being able to pass in sequenceid. 136 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now) { 137 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 138 HConstants.NO_NONCE, null, null, null); 139 } 140 141 // TODO: Fix being able to pass in sequenceid. 142 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 143 final NavigableMap<byte[], Integer> replicationScope) { 144 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 145 HConstants.NO_NONCE, null, replicationScope, null); 146 } 147 148 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 149 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope) { 150 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 151 HConstants.NO_NONCE, mvcc, replicationScope, null); 152 } 153 154 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 155 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope, 156 Map<String, byte[]> extendedAttributes) { 157 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 158 HConstants.NO_NONCE, mvcc, replicationScope, extendedAttributes); 159 } 160 161 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 162 MultiVersionConcurrencyControl mvcc) { 163 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 164 HConstants.NO_NONCE, mvcc, null, null); 165 } 166 167 /** 168 * Copy constructor that takes in an existing WALKeyImpl plus some extended attributes. Intended 169 * for coprocessors to add annotations to a system-generated WALKey for persistence to the WAL. 170 * @param key Key to be copied into this new key 171 * @param extendedAttributes Extra attributes to copy into the new key 172 */ 173 public WALKeyImpl(WALKeyImpl key, Map<String, byte[]> extendedAttributes) { 174 init(key.getEncodedRegionName(), key.getTableName(), key.getSequenceId(), key.getWriteTime(), 175 key.getClusterIds(), key.getNonceGroup(), key.getNonce(), key.getMvcc(), 176 key.getReplicationScopes(), extendedAttributes); 177 178 } 179 180 /** 181 * Copy constructor that takes in an existing WALKey, the extra WALKeyImpl fields that the parent 182 * interface is missing, plus some extended attributes. Intended for coprocessors to add 183 * annotations to a system-generated WALKey for persistence to the WAL. 184 */ 185 public WALKeyImpl(WALKey key, List<UUID> clusterIds, MultiVersionConcurrencyControl mvcc, 186 final NavigableMap<byte[], Integer> replicationScopes, Map<String, byte[]> extendedAttributes) { 187 init(key.getEncodedRegionName(), key.getTableName(), key.getSequenceId(), key.getWriteTime(), 188 clusterIds, key.getNonceGroup(), key.getNonce(), mvcc, replicationScopes, extendedAttributes); 189 190 } 191 192 /** 193 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 194 * purposes. A regionName is always a sub-table object. 195 * <p> 196 * Used by log splitting and snapshots. 197 * @param encodedRegionName Encoded name of the region as returned by 198 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 199 * @param tablename - name of table 200 * @param logSeqNum - log sequence number 201 * @param now Time at which this edit was written. 202 * @param clusterIds the clusters that have consumed the change(used in Replication) 203 * @param nonceGroup the nonceGroup 204 * @param nonce the nonce 205 * @param mvcc the mvcc associate the WALKeyImpl 206 * @param replicationScope the non-default replication scope associated with the region's column 207 * families 208 */ 209 // TODO: Fix being able to pass in sequenceid. 210 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 211 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 212 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope) { 213 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, nonceGroup, nonce, mvcc, 214 replicationScope, null); 215 } 216 217 /** 218 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 219 * purposes. A regionName is always a sub-table object. 220 * <p> 221 * Used by log splitting and snapshots. 222 * @param encodedRegionName Encoded name of the region as returned by 223 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 224 * @param tablename - name of table 225 * @param logSeqNum - log sequence number 226 * @param now Time at which this edit was written. 227 * @param clusterIds the clusters that have consumed the change(used in Replication) 228 */ 229 // TODO: Fix being able to pass in sequenceid. 230 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 231 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 232 MultiVersionConcurrencyControl mvcc) { 233 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, nonceGroup, nonce, mvcc, null, 234 null); 235 } 236 237 /** 238 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 239 * purposes. A regionName is always a sub-table object. 240 * @param encodedRegionName Encoded name of the region as returned by 241 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 242 * @param tablename the tablename 243 * @param now Time at which this edit was written. 244 * @param clusterIds the clusters that have consumed the change(used in Replication) 245 * @param mvcc mvcc control used to generate sequence numbers and control read/write 246 * points 247 */ 248 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 249 List<UUID> clusterIds, long nonceGroup, final long nonce, 250 final MultiVersionConcurrencyControl mvcc) { 251 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 252 null, null); 253 } 254 255 /** 256 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 257 * purposes. A regionName is always a sub-table object. 258 * @param encodedRegionName Encoded name of the region as returned by 259 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 260 * @param now Time at which this edit was written. 261 * @param clusterIds the clusters that have consumed the change(used in Replication) 262 * @param nonceGroup the nonceGroup 263 * @param nonce the nonce 264 * @param mvcc mvcc control used to generate sequence numbers and control read/write 265 * points 266 * @param replicationScope the non-default replication scope of the column families 267 */ 268 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 269 List<UUID> clusterIds, long nonceGroup, final long nonce, 270 final MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope) { 271 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 272 replicationScope, null); 273 } 274 275 /** 276 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 277 * purposes. A regionName is always a sub-table object. 278 * @param encodedRegionName Encoded name of the region as returned by 279 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 280 */ 281 // TODO: Fix being able to pass in sequenceid. 282 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 283 long nonceGroup, long nonce, final MultiVersionConcurrencyControl mvcc) { 284 init(encodedRegionName, tablename, logSeqNum, EnvironmentEdgeManager.currentTime(), EMPTY_UUIDS, 285 nonceGroup, nonce, mvcc, null, null); 286 } 287 288 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 289 List<UUID> clusterIds, long nonceGroup, final long nonce, 290 final MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope, 291 Map<String, byte[]> extendedAttributes) { 292 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 293 replicationScope, extendedAttributes); 294 } 295 296 @InterfaceAudience.Private 297 protected void init(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 298 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 299 MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope, 300 Map<String, byte[]> extendedAttributes) { 301 this.sequenceId = logSeqNum; 302 this.writeTime = now; 303 this.clusterIds = clusterIds; 304 this.encodedRegionName = encodedRegionName; 305 this.tablename = tablename; 306 this.nonceGroup = nonceGroup; 307 this.nonce = nonce; 308 this.mvcc = mvcc; 309 if (logSeqNum != NO_SEQUENCE_ID) { 310 setSequenceId(logSeqNum); 311 } 312 this.replicationScope = replicationScope; 313 this.extendedAttributes = extendedAttributes; 314 } 315 316 // For deserialization. DO NOT USE. See setWriteEntry below. 317 @InterfaceAudience.Private 318 protected void setSequenceId(long sequenceId) { 319 this.sequenceId = sequenceId; 320 } 321 322 /** 323 * @param compressionContext Compression context to use 324 * @deprecated deparcated since hbase 2.1.0 325 */ 326 @Deprecated 327 public void setCompressionContext(CompressionContext compressionContext) { 328 // do nothing 329 } 330 331 /** Returns encoded region name */ 332 @Override 333 public byte[] getEncodedRegionName() { 334 return encodedRegionName; 335 } 336 337 /** Returns table name */ 338 @Override 339 public TableName getTableName() { 340 return tablename; 341 } 342 343 /** 344 * @return log sequence number 345 * @deprecated Use {@link #getSequenceId()} 346 */ 347 @Deprecated 348 public long getLogSeqNum() { 349 return getSequenceId(); 350 } 351 352 /** 353 * Used to set original sequenceId for WALKeyImpl during WAL replay 354 */ 355 public void setOrigLogSeqNum(final long sequenceId) { 356 this.origLogSeqNum = sequenceId; 357 } 358 359 /** 360 * Return a positive long if current WALKeyImpl is created from a replay edit; a replay edit is an 361 * edit that came in when replaying WALs of a crashed server. 362 * @return original sequence number of the WALEdit 363 */ 364 @Override 365 public long getOrigLogSeqNum() { 366 return this.origLogSeqNum; 367 } 368 369 /** 370 * SequenceId is only available post WAL-assign. Calls before this will get you a 371 * {@link SequenceId#NO_SEQUENCE_ID}. See the comment on FSHLog#append and #getWriteNumber in this 372 * method for more on when this sequenceId comes available. 373 * @return long the new assigned sequence number 374 */ 375 @Override 376 public long getSequenceId() { 377 return this.sequenceId; 378 } 379 380 /** Returns the write time */ 381 @Override 382 public long getWriteTime() { 383 return this.writeTime; 384 } 385 386 public NavigableMap<byte[], Integer> getReplicationScopes() { 387 return replicationScope; 388 } 389 390 /** Returns The nonce group */ 391 @Override 392 public long getNonceGroup() { 393 return nonceGroup; 394 } 395 396 /** Returns The nonce */ 397 @Override 398 public long getNonce() { 399 return nonce; 400 } 401 402 private void setReplicationScope(NavigableMap<byte[], Integer> replicationScope) { 403 this.replicationScope = replicationScope; 404 } 405 406 public void clearReplicationScope() { 407 setReplicationScope(null); 408 } 409 410 /** 411 * Marks that the cluster with the given clusterId has consumed the change 412 */ 413 public void addClusterId(UUID clusterId) { 414 if (!clusterIds.contains(clusterId)) { 415 clusterIds.add(clusterId); 416 } 417 } 418 419 /** Returns the set of cluster Ids that have consumed the change */ 420 public List<UUID> getClusterIds() { 421 return clusterIds; 422 } 423 424 /** 425 * @return the cluster id on which the change has originated. It there is no such cluster, it 426 * returns DEFAULT_CLUSTER_ID (cases where replication is not enabled) 427 */ 428 @Override 429 public UUID getOriginatingClusterId() { 430 return clusterIds.isEmpty() ? HConstants.DEFAULT_CLUSTER_ID : clusterIds.get(0); 431 } 432 433 @Override 434 public void addExtendedAttribute(String attributeKey, byte[] attributeValue) { 435 if (extendedAttributes == null) { 436 extendedAttributes = new HashMap<String, byte[]>(); 437 } 438 extendedAttributes.put(attributeKey, attributeValue); 439 } 440 441 @Override 442 public byte[] getExtendedAttribute(String attributeKey) { 443 return extendedAttributes != null ? extendedAttributes.get(attributeKey) : null; 444 } 445 446 @Override 447 public Map<String, byte[]> getExtendedAttributes() { 448 return extendedAttributes != null 449 ? new HashMap<String, byte[]>(extendedAttributes) 450 : new HashMap<String, byte[]>(); 451 } 452 453 @Override 454 public String toString() { 455 return tablename + "/" + Bytes.toString(encodedRegionName) + "/" + sequenceId; 456 } 457 458 @Override 459 public boolean equals(Object obj) { 460 if (this == obj) { 461 return true; 462 } 463 if (obj == null || getClass() != obj.getClass()) { 464 return false; 465 } 466 return compareTo((WALKey) obj) == 0; 467 } 468 469 @Override 470 public int hashCode() { 471 int result = Bytes.hashCode(this.encodedRegionName); 472 result = (int) (result ^ getSequenceId()); 473 result = (int) (result ^ this.writeTime); 474 return result; 475 } 476 477 @Override 478 public int compareTo(WALKey o) { 479 int result = Bytes.compareTo(this.encodedRegionName, o.getEncodedRegionName()); 480 if (result == 0) { 481 long sid = getSequenceId(); 482 long otherSid = o.getSequenceId(); 483 if (sid < otherSid) { 484 result = -1; 485 } else if (sid > otherSid) { 486 result = 1; 487 } 488 if (result == 0) { 489 if (this.writeTime < o.getWriteTime()) { 490 result = -1; 491 } else if (this.writeTime > o.getWriteTime()) { 492 return 1; 493 } 494 } 495 } 496 // why isn't cluster id accounted for? 497 return result; 498 } 499 500 /** 501 * Drop this instance's tablename byte array and instead hold a reference to the provided 502 * tablename. This is not meant to be a general purpose setter - it's only used to collapse 503 * references to conserve memory. 504 */ 505 void internTableName(TableName tablename) { 506 // We should not use this as a setter - only to swap 507 // in a new reference to the same table name. 508 assert tablename.equals(this.tablename); 509 this.tablename = tablename; 510 } 511 512 /** 513 * Drop this instance's region name byte array and instead hold a reference to the provided region 514 * name. This is not meant to be a general purpose setter - it's only used to collapse references 515 * to conserve memory. 516 */ 517 void internEncodedRegionName(byte[] encodedRegionName) { 518 // We should not use this as a setter - only to swap 519 // in a new reference to the same table name. 520 assert Bytes.equals(this.encodedRegionName, encodedRegionName); 521 this.encodedRegionName = encodedRegionName; 522 } 523 524 public WALProtos.WALKey.Builder getBuilder(WALCellCodec.ByteStringCompressor compressor) 525 throws IOException { 526 WALProtos.WALKey.Builder builder = WALProtos.WALKey.newBuilder(); 527 builder.setEncodedRegionName( 528 compressor.compress(this.encodedRegionName, CompressionContext.DictionaryIndex.REGION)); 529 builder.setTableName( 530 compressor.compress(this.tablename.getName(), CompressionContext.DictionaryIndex.TABLE)); 531 builder.setLogSequenceNumber(getSequenceId()); 532 builder.setWriteTime(writeTime); 533 if (this.origLogSeqNum > 0) { 534 builder.setOrigSequenceNumber(this.origLogSeqNum); 535 } 536 if (this.nonce != HConstants.NO_NONCE) { 537 builder.setNonce(nonce); 538 } 539 if (this.nonceGroup != HConstants.NO_NONCE) { 540 builder.setNonceGroup(nonceGroup); 541 } 542 HBaseProtos.UUID.Builder uuidBuilder = HBaseProtos.UUID.newBuilder(); 543 for (UUID clusterId : clusterIds) { 544 uuidBuilder.setLeastSigBits(clusterId.getLeastSignificantBits()); 545 uuidBuilder.setMostSigBits(clusterId.getMostSignificantBits()); 546 builder.addClusterIds(uuidBuilder.build()); 547 } 548 if (replicationScope != null) { 549 for (Map.Entry<byte[], Integer> e : replicationScope.entrySet()) { 550 ByteString family = 551 compressor.compress(e.getKey(), CompressionContext.DictionaryIndex.FAMILY); 552 builder.addScopes(FamilyScope.newBuilder().setFamily(family) 553 .setScopeType(ScopeType.forNumber(e.getValue()))); 554 } 555 } 556 if (extendedAttributes != null) { 557 for (Map.Entry<String, byte[]> e : extendedAttributes.entrySet()) { 558 WALProtos.Attribute attr = WALProtos.Attribute.newBuilder().setKey(e.getKey()) 559 .setValue(compressor.compress(e.getValue(), CompressionContext.DictionaryIndex.TABLE)) 560 .build(); 561 builder.addExtendedAttributes(attr); 562 } 563 } 564 return builder; 565 } 566 567 public void readFieldsFromPb(WALProtos.WALKey walKey, 568 WALCellCodec.ByteStringUncompressor uncompressor) throws IOException { 569 this.encodedRegionName = uncompressor.uncompress(walKey.getEncodedRegionName(), 570 CompressionContext.DictionaryIndex.REGION); 571 byte[] tablenameBytes = 572 uncompressor.uncompress(walKey.getTableName(), CompressionContext.DictionaryIndex.TABLE); 573 this.tablename = TableName.valueOf(tablenameBytes); 574 clusterIds.clear(); 575 for (HBaseProtos.UUID clusterId : walKey.getClusterIdsList()) { 576 clusterIds.add(new UUID(clusterId.getMostSigBits(), clusterId.getLeastSigBits())); 577 } 578 if (walKey.hasNonceGroup()) { 579 this.nonceGroup = walKey.getNonceGroup(); 580 } 581 if (walKey.hasNonce()) { 582 this.nonce = walKey.getNonce(); 583 } 584 this.replicationScope = null; 585 if (walKey.getScopesCount() > 0) { 586 this.replicationScope = new TreeMap<>(Bytes.BYTES_COMPARATOR); 587 for (FamilyScope scope : walKey.getScopesList()) { 588 byte[] family = 589 uncompressor.uncompress(scope.getFamily(), CompressionContext.DictionaryIndex.FAMILY); 590 this.replicationScope.put(family, scope.getScopeType().getNumber()); 591 } 592 } 593 setSequenceId(walKey.getLogSequenceNumber()); 594 this.writeTime = walKey.getWriteTime(); 595 if (walKey.hasOrigSequenceNumber()) { 596 this.origLogSeqNum = walKey.getOrigSequenceNumber(); 597 } 598 if (walKey.getExtendedAttributesCount() > 0) { 599 this.extendedAttributes = new HashMap<>(walKey.getExtendedAttributesCount()); 600 for (WALProtos.Attribute attr : walKey.getExtendedAttributesList()) { 601 byte[] value = 602 uncompressor.uncompress(attr.getValue(), CompressionContext.DictionaryIndex.TABLE); 603 extendedAttributes.put(attr.getKey(), value); 604 } 605 } 606 } 607 608 @Override 609 public long estimatedSerializedSizeOf() { 610 long size = encodedRegionName != null ? encodedRegionName.length : 0; 611 size += tablename != null ? tablename.toBytes().length : 0; 612 if (clusterIds != null) { 613 size += 16 * clusterIds.size(); 614 } 615 if (nonceGroup != HConstants.NO_NONCE) { 616 size += Bytes.SIZEOF_LONG; // nonce group 617 } 618 if (nonce != HConstants.NO_NONCE) { 619 size += Bytes.SIZEOF_LONG; // nonce 620 } 621 if (replicationScope != null) { 622 for (Map.Entry<byte[], Integer> scope : replicationScope.entrySet()) { 623 size += scope.getKey().length; 624 size += Bytes.SIZEOF_INT; 625 } 626 } 627 size += Bytes.SIZEOF_LONG; // sequence number 628 size += Bytes.SIZEOF_LONG; // write time 629 if (origLogSeqNum > 0) { 630 size += Bytes.SIZEOF_LONG; // original sequence number 631 } 632 return size; 633 } 634}