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