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 @InterfaceAudience.Private 136 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 137 final long now, UUID clusterId, MultiVersionConcurrencyControl mvcc) { 138 List<UUID> clusterIds = new ArrayList<>(1); 139 clusterIds.add(clusterId); 140 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, HConstants.NO_NONCE, 141 HConstants.NO_NONCE, mvcc, null, null); 142 } 143 144 // TODO: Fix being able to pass in sequenceid. 145 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now) { 146 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 147 HConstants.NO_NONCE, null, null, null); 148 } 149 150 // TODO: Fix being able to pass in sequenceid. 151 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 152 final NavigableMap<byte[], Integer> replicationScope) { 153 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 154 HConstants.NO_NONCE, null, replicationScope, null); 155 } 156 157 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 158 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope) { 159 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 160 HConstants.NO_NONCE, mvcc, replicationScope, null); 161 } 162 163 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 164 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope, 165 Map<String, byte[]> extendedAttributes) { 166 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 167 HConstants.NO_NONCE, mvcc, replicationScope, extendedAttributes); 168 } 169 170 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 171 MultiVersionConcurrencyControl mvcc) { 172 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, EMPTY_UUIDS, HConstants.NO_NONCE, 173 HConstants.NO_NONCE, mvcc, null, null); 174 } 175 176 /** 177 * Copy constructor that takes in an existing WALKeyImpl plus some extended attributes. Intended 178 * for coprocessors to add annotations to a system-generated WALKey for persistence to the WAL. 179 * @param key Key to be copied into this new key 180 * @param extendedAttributes Extra attributes to copy into the new key 181 */ 182 public WALKeyImpl(WALKeyImpl key, Map<String, byte[]> extendedAttributes) { 183 init(key.getEncodedRegionName(), key.getTableName(), key.getSequenceId(), key.getWriteTime(), 184 key.getClusterIds(), key.getNonceGroup(), key.getNonce(), key.getMvcc(), 185 key.getReplicationScopes(), extendedAttributes); 186 187 } 188 189 /** 190 * Copy constructor that takes in an existing WALKey, the extra WALKeyImpl fields that the parent 191 * interface is missing, plus some extended attributes. Intended for coprocessors to add 192 * annotations to a system-generated WALKey for persistence to the WAL. 193 */ 194 public WALKeyImpl(WALKey key, List<UUID> clusterIds, MultiVersionConcurrencyControl mvcc, 195 final NavigableMap<byte[], Integer> replicationScopes, Map<String, byte[]> extendedAttributes) { 196 init(key.getEncodedRegionName(), key.getTableName(), key.getSequenceId(), key.getWriteTime(), 197 clusterIds, key.getNonceGroup(), key.getNonce(), mvcc, replicationScopes, extendedAttributes); 198 199 } 200 201 /** 202 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 203 * purposes. A regionName is always a sub-table object. 204 * <p> 205 * Used by log splitting and snapshots. 206 * @param encodedRegionName Encoded name of the region as returned by 207 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 208 * @param tablename - name of table 209 * @param logSeqNum - log sequence number 210 * @param now Time at which this edit was written. 211 * @param clusterIds the clusters that have consumed the change(used in Replication) 212 * @param nonceGroup the nonceGroup 213 * @param nonce the nonce 214 * @param mvcc the mvcc associate the WALKeyImpl 215 * @param replicationScope the non-default replication scope associated with the region's column 216 * families 217 */ 218 // TODO: Fix being able to pass in sequenceid. 219 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 220 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 221 MultiVersionConcurrencyControl mvcc, final NavigableMap<byte[], Integer> replicationScope) { 222 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, nonceGroup, nonce, mvcc, 223 replicationScope, null); 224 } 225 226 /** 227 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 228 * purposes. A regionName is always a sub-table object. 229 * <p> 230 * Used by log splitting and snapshots. 231 * @param encodedRegionName Encoded name of the region as returned by 232 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 233 * @param tablename - name of table 234 * @param logSeqNum - log sequence number 235 * @param now Time at which this edit was written. 236 * @param clusterIds the clusters that have consumed the change(used in Replication) 237 */ 238 // TODO: Fix being able to pass in sequenceid. 239 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 240 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 241 MultiVersionConcurrencyControl mvcc) { 242 init(encodedRegionName, tablename, logSeqNum, now, clusterIds, nonceGroup, nonce, mvcc, null, 243 null); 244 } 245 246 /** 247 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 248 * purposes. A regionName is always a sub-table object. 249 * @param encodedRegionName Encoded name of the region as returned by 250 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 251 * @param tablename the tablename 252 * @param now Time at which this edit was written. 253 * @param clusterIds the clusters that have consumed the change(used in Replication) * 254 * * @param mvcc mvcc control used to generate sequence numbers and 255 * control read/write points 256 */ 257 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 258 List<UUID> clusterIds, long nonceGroup, final long nonce, 259 final MultiVersionConcurrencyControl mvcc) { 260 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 261 null, null); 262 } 263 264 /** 265 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 266 * purposes. A regionName is always a sub-table object. 267 * @param encodedRegionName Encoded name of the region as returned by 268 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 269 * @param now Time at which this edit was written. 270 * @param clusterIds the clusters that have consumed the change(used in Replication) 271 * @param nonceGroup the nonceGroup 272 * @param nonce the nonce 273 * @param mvcc mvcc control used to generate sequence numbers and control read/write 274 * points 275 * @param replicationScope the non-default replication scope of the column families 276 */ 277 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 278 List<UUID> clusterIds, long nonceGroup, final long nonce, 279 final MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope) { 280 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 281 replicationScope, null); 282 } 283 284 /** 285 * Create the log key for writing to somewhere. We maintain the tablename mainly for debugging 286 * purposes. A regionName is always a sub-table object. 287 * @param encodedRegionName Encoded name of the region as returned by 288 * <code>HRegionInfo#getEncodedNameAsBytes()</code>. 289 */ 290 // TODO: Fix being able to pass in sequenceid. 291 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 292 long nonceGroup, long nonce, final MultiVersionConcurrencyControl mvcc) { 293 init(encodedRegionName, tablename, logSeqNum, EnvironmentEdgeManager.currentTime(), EMPTY_UUIDS, 294 nonceGroup, nonce, mvcc, null, null); 295 } 296 297 public WALKeyImpl(final byte[] encodedRegionName, final TableName tablename, final long now, 298 List<UUID> clusterIds, long nonceGroup, final long nonce, 299 final MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope, 300 Map<String, byte[]> extendedAttributes) { 301 init(encodedRegionName, tablename, NO_SEQUENCE_ID, now, clusterIds, nonceGroup, nonce, mvcc, 302 replicationScope, extendedAttributes); 303 } 304 305 @InterfaceAudience.Private 306 protected void init(final byte[] encodedRegionName, final TableName tablename, long logSeqNum, 307 final long now, List<UUID> clusterIds, long nonceGroup, long nonce, 308 MultiVersionConcurrencyControl mvcc, NavigableMap<byte[], Integer> replicationScope, 309 Map<String, byte[]> extendedAttributes) { 310 this.sequenceId = logSeqNum; 311 this.writeTime = now; 312 this.clusterIds = clusterIds; 313 this.encodedRegionName = encodedRegionName; 314 this.tablename = tablename; 315 this.nonceGroup = nonceGroup; 316 this.nonce = nonce; 317 this.mvcc = mvcc; 318 if (logSeqNum != NO_SEQUENCE_ID) { 319 setSequenceId(logSeqNum); 320 } 321 this.replicationScope = replicationScope; 322 this.extendedAttributes = extendedAttributes; 323 } 324 325 // For deserialization. DO NOT USE. See setWriteEntry below. 326 @InterfaceAudience.Private 327 protected void setSequenceId(long sequenceId) { 328 this.sequenceId = sequenceId; 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 * Used to set original sequenceId for WALKeyImpl during WAL replay 345 */ 346 public void setOrigLogSeqNum(final long sequenceId) { 347 this.origLogSeqNum = sequenceId; 348 } 349 350 /** 351 * Return a positive long if current WALKeyImpl is created from a replay edit; a replay edit is an 352 * edit that came in when replaying WALs of a crashed server. 353 * @return original sequence number of the WALEdit 354 */ 355 @Override 356 public long getOrigLogSeqNum() { 357 return this.origLogSeqNum; 358 } 359 360 /** 361 * SequenceId is only available post WAL-assign. Calls before this will get you a 362 * {@link SequenceId#NO_SEQUENCE_ID}. See the comment on FSHLog#append and #getWriteNumber in this 363 * method for more on when this sequenceId comes available. 364 * @return long the new assigned sequence number 365 */ 366 @Override 367 public long getSequenceId() { 368 return this.sequenceId; 369 } 370 371 /** Returns the write time */ 372 @Override 373 public long getWriteTime() { 374 return this.writeTime; 375 } 376 377 public NavigableMap<byte[], Integer> getReplicationScopes() { 378 return replicationScope; 379 } 380 381 /** Returns The nonce group */ 382 @Override 383 public long getNonceGroup() { 384 return nonceGroup; 385 } 386 387 /** Returns The nonce */ 388 @Override 389 public long getNonce() { 390 return nonce; 391 } 392 393 private void setReplicationScope(NavigableMap<byte[], Integer> replicationScope) { 394 this.replicationScope = replicationScope; 395 } 396 397 public void clearReplicationScope() { 398 setReplicationScope(null); 399 } 400 401 /** 402 * Marks that the cluster with the given clusterId has consumed the change 403 */ 404 public void addClusterId(UUID clusterId) { 405 if (!clusterIds.contains(clusterId)) { 406 clusterIds.add(clusterId); 407 } 408 } 409 410 /** Returns the set of cluster Ids that have consumed the change */ 411 public List<UUID> getClusterIds() { 412 return clusterIds; 413 } 414 415 /** 416 * @return the cluster id on which the change has originated. It there is no such cluster, it 417 * returns DEFAULT_CLUSTER_ID (cases where replication is not enabled) 418 */ 419 @Override 420 public UUID getOriginatingClusterId() { 421 return clusterIds.isEmpty() ? HConstants.DEFAULT_CLUSTER_ID : clusterIds.get(0); 422 } 423 424 @Override 425 public void addExtendedAttribute(String attributeKey, byte[] attributeValue) { 426 if (extendedAttributes == null) { 427 extendedAttributes = new HashMap<String, byte[]>(); 428 } 429 extendedAttributes.put(attributeKey, attributeValue); 430 } 431 432 @Override 433 public byte[] getExtendedAttribute(String attributeKey) { 434 return extendedAttributes != null ? extendedAttributes.get(attributeKey) : null; 435 } 436 437 @Override 438 public Map<String, byte[]> getExtendedAttributes() { 439 return extendedAttributes != null 440 ? new HashMap<String, byte[]>(extendedAttributes) 441 : new HashMap<String, byte[]>(); 442 } 443 444 @Override 445 public String toString() { 446 return tablename + "/" + Bytes.toString(encodedRegionName) + "/" + sequenceId; 447 } 448 449 @Override 450 public boolean equals(Object obj) { 451 if (this == obj) { 452 return true; 453 } 454 if (obj == null || getClass() != obj.getClass()) { 455 return false; 456 } 457 return compareTo((WALKey) obj) == 0; 458 } 459 460 @Override 461 public int hashCode() { 462 int result = Bytes.hashCode(this.encodedRegionName); 463 result = (int) (result ^ getSequenceId()); 464 result = (int) (result ^ this.writeTime); 465 return result; 466 } 467 468 @Override 469 public int compareTo(WALKey o) { 470 int result = Bytes.compareTo(this.encodedRegionName, o.getEncodedRegionName()); 471 if (result == 0) { 472 long sid = getSequenceId(); 473 long otherSid = o.getSequenceId(); 474 if (sid < otherSid) { 475 result = -1; 476 } else if (sid > otherSid) { 477 result = 1; 478 } 479 if (result == 0) { 480 if (this.writeTime < o.getWriteTime()) { 481 result = -1; 482 } else if (this.writeTime > o.getWriteTime()) { 483 return 1; 484 } 485 } 486 } 487 // why isn't cluster id accounted for? 488 return result; 489 } 490 491 /** 492 * Drop this instance's tablename byte array and instead hold a reference to the provided 493 * tablename. This is not meant to be a general purpose setter - it's only used to collapse 494 * references to conserve memory. 495 */ 496 void internTableName(TableName tablename) { 497 // We should not use this as a setter - only to swap 498 // in a new reference to the same table name. 499 assert tablename.equals(this.tablename); 500 this.tablename = tablename; 501 } 502 503 /** 504 * Drop this instance's region name byte array and instead hold a reference to the provided region 505 * name. This is not meant to be a general purpose setter - it's only used to collapse references 506 * to conserve memory. 507 */ 508 void internEncodedRegionName(byte[] encodedRegionName) { 509 // We should not use this as a setter - only to swap 510 // in a new reference to the same table name. 511 assert Bytes.equals(this.encodedRegionName, encodedRegionName); 512 this.encodedRegionName = encodedRegionName; 513 } 514 515 public WALProtos.WALKey.Builder getBuilder(WALCellCodec.ByteStringCompressor compressor) 516 throws IOException { 517 WALProtos.WALKey.Builder builder = WALProtos.WALKey.newBuilder(); 518 builder.setEncodedRegionName( 519 compressor.compress(this.encodedRegionName, CompressionContext.DictionaryIndex.REGION)); 520 builder.setTableName( 521 compressor.compress(this.tablename.getName(), CompressionContext.DictionaryIndex.TABLE)); 522 builder.setLogSequenceNumber(getSequenceId()); 523 builder.setWriteTime(writeTime); 524 if (this.origLogSeqNum > 0) { 525 builder.setOrigSequenceNumber(this.origLogSeqNum); 526 } 527 if (this.nonce != HConstants.NO_NONCE) { 528 builder.setNonce(nonce); 529 } 530 if (this.nonceGroup != HConstants.NO_NONCE) { 531 builder.setNonceGroup(nonceGroup); 532 } 533 HBaseProtos.UUID.Builder uuidBuilder = HBaseProtos.UUID.newBuilder(); 534 for (UUID clusterId : clusterIds) { 535 uuidBuilder.setLeastSigBits(clusterId.getLeastSignificantBits()); 536 uuidBuilder.setMostSigBits(clusterId.getMostSignificantBits()); 537 builder.addClusterIds(uuidBuilder.build()); 538 } 539 if (replicationScope != null) { 540 for (Map.Entry<byte[], Integer> e : replicationScope.entrySet()) { 541 ByteString family = 542 compressor.compress(e.getKey(), CompressionContext.DictionaryIndex.FAMILY); 543 builder.addScopes(FamilyScope.newBuilder().setFamily(family) 544 .setScopeType(ScopeType.forNumber(e.getValue()))); 545 } 546 } 547 if (extendedAttributes != null) { 548 for (Map.Entry<String, byte[]> e : extendedAttributes.entrySet()) { 549 WALProtos.Attribute attr = WALProtos.Attribute.newBuilder().setKey(e.getKey()) 550 .setValue(compressor.compress(e.getValue(), CompressionContext.DictionaryIndex.TABLE)) 551 .build(); 552 builder.addExtendedAttributes(attr); 553 } 554 } 555 return builder; 556 } 557 558 public void readFieldsFromPb(WALProtos.WALKey walKey, 559 WALCellCodec.ByteStringUncompressor uncompressor) throws IOException { 560 this.encodedRegionName = uncompressor.uncompress(walKey.getEncodedRegionName(), 561 CompressionContext.DictionaryIndex.REGION); 562 byte[] tablenameBytes = 563 uncompressor.uncompress(walKey.getTableName(), CompressionContext.DictionaryIndex.TABLE); 564 this.tablename = TableName.valueOf(tablenameBytes); 565 clusterIds.clear(); 566 for (HBaseProtos.UUID clusterId : walKey.getClusterIdsList()) { 567 clusterIds.add(new UUID(clusterId.getMostSigBits(), clusterId.getLeastSigBits())); 568 } 569 if (walKey.hasNonceGroup()) { 570 this.nonceGroup = walKey.getNonceGroup(); 571 } 572 if (walKey.hasNonce()) { 573 this.nonce = walKey.getNonce(); 574 } 575 this.replicationScope = null; 576 if (walKey.getScopesCount() > 0) { 577 this.replicationScope = new TreeMap<>(Bytes.BYTES_COMPARATOR); 578 for (FamilyScope scope : walKey.getScopesList()) { 579 byte[] family = 580 uncompressor.uncompress(scope.getFamily(), CompressionContext.DictionaryIndex.FAMILY); 581 this.replicationScope.put(family, scope.getScopeType().getNumber()); 582 } 583 } 584 setSequenceId(walKey.getLogSequenceNumber()); 585 this.writeTime = walKey.getWriteTime(); 586 if (walKey.hasOrigSequenceNumber()) { 587 this.origLogSeqNum = walKey.getOrigSequenceNumber(); 588 } 589 if (walKey.getExtendedAttributesCount() > 0) { 590 this.extendedAttributes = new HashMap<>(walKey.getExtendedAttributesCount()); 591 for (WALProtos.Attribute attr : walKey.getExtendedAttributesList()) { 592 byte[] value = 593 uncompressor.uncompress(attr.getValue(), CompressionContext.DictionaryIndex.TABLE); 594 extendedAttributes.put(attr.getKey(), value); 595 } 596 } 597 } 598 599 @Override 600 public long estimatedSerializedSizeOf() { 601 long size = encodedRegionName != null ? encodedRegionName.length : 0; 602 size += tablename != null ? tablename.toBytes().length : 0; 603 if (clusterIds != null) { 604 size += 16 * clusterIds.size(); 605 } 606 if (nonceGroup != HConstants.NO_NONCE) { 607 size += Bytes.SIZEOF_LONG; // nonce group 608 } 609 if (nonce != HConstants.NO_NONCE) { 610 size += Bytes.SIZEOF_LONG; // nonce 611 } 612 if (replicationScope != null) { 613 for (Map.Entry<byte[], Integer> scope : replicationScope.entrySet()) { 614 size += scope.getKey().length; 615 size += Bytes.SIZEOF_INT; 616 } 617 } 618 size += Bytes.SIZEOF_LONG; // sequence number 619 size += Bytes.SIZEOF_LONG; // write time 620 if (origLogSeqNum > 0) { 621 size += Bytes.SIZEOF_LONG; // original sequence number 622 } 623 return size; 624 } 625}