1 /*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. 5 * 6 */ 7 8 package com.sleepycat.je.log; 9 10 import java.util.HashSet; 11 import java.util.Set; 12 13 import com.sleepycat.je.DatabaseException; 14 import com.sleepycat.je.log.entry.AbortLogEntry; 15 import com.sleepycat.je.log.entry.BINDeltaLogEntry; 16 import com.sleepycat.je.log.entry.CommitLogEntry; 17 import com.sleepycat.je.log.entry.DeletedDupLNLogEntry; 18 import com.sleepycat.je.log.entry.FileHeaderEntry; 19 import com.sleepycat.je.log.entry.INLogEntry; 20 import com.sleepycat.je.log.entry.LNLogEntry; 21 import com.sleepycat.je.log.entry.LogEntry; 22 import com.sleepycat.je.log.entry.MatchpointLogEntry; 23 import com.sleepycat.je.log.entry.NameLNLogEntry; 24 import com.sleepycat.je.log.entry.OldBINDeltaLogEntry; 25 import com.sleepycat.je.log.entry.ReplicableLogEntry; 26 import com.sleepycat.je.log.entry.SingleItemEntry; 27 import com.sleepycat.je.log.entry.TraceLogEntry; 28 29 /** 30 * LogEntryType is an enumeration of all log entry types. 31 * 32 * <p>Log entries are versioned. When changing the persistent form of a log 33 * entry in any way that is incompatible with prior releases, make sure the 34 * LogEntry instance is capable of reading in older versions from the log and 35 * be sure to increment LOG_VERSION. The LogEntry.readEntry and 36 * Loggable.readFromLog methods should check the actual version of the entry. 37 * If it is less than LOG_VERSION, the old version should be converted to the 38 * current version. 39 * 40 * <p>Prior to LOG_VERSION 6, each log entry type had a separate version number 41 * that was incremented only when that log version changed. From LOG_VERSION 6 42 * onward, all types use the same version, the LOG_VERSION constant. For 43 * versions prior to 6, the readEntry and readFromLog methods will be checking 44 * the old per-type version. There is no overlap between the old per-type 45 * versions and the LOG_VERSION values, because the per-type values are all 46 * below 6. [#15365]</p> 47 48 * <p>The LogEntry instance must be sure that older versions are converted in 49 * memory into a correct instance of the newest version, so when that LogEntry 50 * object is written again as the result of migration, eviction, the resulting 51 * new log entry conforms to the requirements of the new version. If context 52 * objects are required for data conversion, the conversion can be done in the 53 * Node.postFetchInit method.</p> 54 * 55 * <p>Starting with LOG_VERSION 9, log entries that can be included in the 56 * replication stream must be able to write themselves in the format for the 57 * immediately previous log version, to allow replication during an upgrade 58 * when the master has been upgraded and a replica has not. Starting with 59 * LOG_VERSION 8, log entries that support replication must implement {@link 60 * ReplicableLogEntry}. When changes are made to replicable log entries for 61 * LOG_VERSION 9 and later, those entries need to support writing in the 62 * previous version's format.</p> 63 */ 64 public class LogEntryType { 65 66 /** 67 * Version of the file header, which identifies the version of all entries 68 * in that file. 69 * 70 * Changes to log entries for each version are: 71 * 72 * Version 3 73 * --------- 74 * [12328] Add main and dupe tree fanout values for DatabaseImpl. 75 * [12557] Add IN LSN array compression. 76 * [11597] Add a change to FileSummaryLNs: obsolete offset tracking was 77 * added and multiple records are stored for a single file rather than a 78 * single record. Each record contains the offsets that were tracked since 79 * the last record was written. 80 * [11597] Add the full obsolete LSN in LNLogEntry. 81 * 82 * Version 4 83 * --------- 84 * [#14422] Bump MapLN version from 1 to 2. Instead of a String for the 85 * comparator class name, store either a serialized string or Comparator. 86 * 87 * Version 5 88 * --------- 89 * [#15195] FileSummaryLN version 3. Add FileSummary.obsoleteLNSize and 90 * obsoleteLNSizeCounted fields. 91 * 92 * Version 6 (in JE 3.3.X) 93 * --------- 94 * [#15365] From this point onward, all log entries have the same version, 95 * LOG_VERSION, rather than using per-type versions. 96 * [#15365] DatabaseImpl stores a map of DbFileSummaries. 97 * 98 * [#13467] Convert duplicatesAllowed boolean to DUPS_ALLOWED_BIT flag in 99 * DatabaseImpl. Add REPLICATED_BIT flag to DatabaseImpl. 100 * [#13467] Add REPLICATED_BIT to DbTree. 101 * [#13467] Add ReplicatedDatabaseConfig to NameLN_TX to support 102 * replication of database operations. 103 * 104 * [#15581] Add lastAllocateReplicatedDbId to DbTree 105 * [#16083] Add replication master node ID to txn commit/abort 106 * 107 * Version 7 (in JE 4.0) 108 * --------------------- 109 * Add the invisible bit in the entry header version field. 110 * Add the RollbackStart log entry type 111 * Add the RollbackEnd log entry type 112 * Add the Matchpoint log entry type. 113 * 114 * Version 8 (in JE 5.0) 115 * --------------------- 116 * Made provisions for storing Triggers in a DatabaseImpl. 117 * 118 * Database IDs enlarged from int or packed int, to long or packed long 119 * (note that packed int and packed long are compatible). [#18540] 120 * 121 * Add new log entry types for LN delete, insert and update. [#18055] 122 * 123 * Apply optimization to omit key size for some internal LNs, in addition 124 * to user LNs. [#18055] 125 * 126 * LN no longer has node ID. [#18633] 127 * 128 * Add FileSummary.maxLNSize. [#18633] 129 * 130 * VLSN is optionally maintained in LogEntryHeader for cleaner migrated LNs 131 * and a new VLSN_PRESENT entry header flag is used to signify the presence 132 * of the VLSN. PRESERVE_VLSN_BIT was added to DbTree to correspond to the 133 * je.env.preserveRecordVersion environment config param. [#19476] 134 * 135 * Dup tree representation changed to use two-part keys. Deprecated: DIN, 136 * DBIN, DupCountLN, INDeleteInfo, INDupDeleteInfo. Removed 137 * DatabaseImpl.maxDupTreeEntriesPerNode. [#19165] 138 * 139 * Version 9 (in JE 6.0) 140 * --------------------- 141 * See comment above about ReplicableLogEntry. 142 * 143 * BIN-deltas are now represented as BINs using the new BINDeltaLogEntry 144 * (log entry type NewBINDelta). 145 * 146 * Version 10 (in JE 6.2) 147 * ---------------------- 148 * 149 * Each BIN-delta stores the total and max number of entries in the 150 * previous full version of the same BIN. A BIN-delta may also store a 151 * bloom filter for the keys in the full BIN. 152 */ 153 public static final int LOG_VERSION = 10; 154 155 public static final int FIRST_LOG_VERSION = 1; 156 157 /** 158 * The earliest log version for which replicable log entries support 159 * writing themselves in the previous version, to support replication to 160 * older nodes during upgrades. 161 */ 162 public static final int LOG_VERSION_REPLICATE_PREVIOUS = 9; 163 164 /** 165 * The highest log version of any replicable log entry class, so that 166 * replication can determine the earliest log version it can generate. 167 * This field is needed to account for cases where log entry format changes 168 * only apply to non-replicable entries, as was the case for log version 169 * 10. 170 */ 171 /* 172 * TODO: Modify the requirements for writing replicable log entries in the 173 * the current version minus one format to account for the fact that there 174 * is a gap in the numbering, since no replicable entry classes had format 175 * changes for log versions 9 or 10. Make this change the next time the 176 * format of a replicable log entry is modified. 177 */ 178 public static final int LOG_VERSION_HIGHEST_REPLICABLE = 8; 179 180 /** 181 * Should be used for reading the entry header of the file header, since 182 * the actual version is not known until the FileHeader item is read. 183 */ 184 public static final int UNKNOWN_FILE_HEADER_VERSION = -1; 185 186 /* 187 * Collection of log entry type classes, used to read the log. Note that 188 * this must be declared before any instances of LogEntryType, since the 189 * constructor uses this map. Each statically defined LogEntryType should 190 * register itself with this collection. 191 */ 192 private static final int MAX_TYPE_NUM = 37; 193 private static LogEntryType[] LOG_TYPES = new LogEntryType[MAX_TYPE_NUM]; 194 195 /* 196 * Enumeration of log entry types. The log entry type represents the 2 byte 197 * field that starts every log entry. The top byte is the log type, the 198 * bottom byte holds the version value, provisional bit, replicated bit, 199 * and invisible bit. 200 * 201 * Log type(8 bits) 202 * Provisional(2 bits) Replicated(1 bit) Invisible(1 bit) Version(5 bits) 203 * 204 * The top byte (log type) identifies the type and can be used to lookup 205 * the LogEntryType object, while the bottom byte has information about the 206 * entry (instance) of this type. The bottom byte is effectively entry 207 * header information that is common to all types and is managed by methods 208 * in LogEntryHeader. See LogEntryHeader.java 209 */ 210 211 /* Node types */ 212 213 /* 214 * Deprecated transactional LN entry type, use LOG_DEL_LN_TRANSACTIONAL, 215 * LOG_INS_LN_TRANSACTIONAL, LOG_UPD_LN_TRANSACTIONAL instead according to 216 * the operation type. 217 */ 218 public static final LogEntryType LOG_OLD_LN_TRANSACTIONAL = 219 createReplicableLogEntryType( 220 (byte) 1, "LN_TX", 221 LNLogEntry.create(com.sleepycat.je.tree.LN.class), 222 Txnal.TXNAL, 223 Marshall.OUTSIDE_LATCH, 224 Replicable.REPLICABLE_NO_MATCH, 225 NodeType.LN_USER); 226 227 /* 228 * Deprecated LN entry type, use LOG_DEL_LN, LOG_INS_LN, LOG_UPD_LN instead 229 * according to the operation type. 230 */ 231 public static final LogEntryType LOG_OLD_LN = 232 createReplicableLogEntryType( 233 (byte) 2, "LN", 234 LNLogEntry.create(com.sleepycat.je.tree.LN.class), 235 Txnal.NON_TXNAL, 236 Marshall.OUTSIDE_LATCH, 237 Replicable.REPLICABLE_NO_MATCH, 238 NodeType.LN_USER); 239 240 public static final LogEntryType LOG_MAPLN_TRANSACTIONAL = 241 new LogEntryType 242 ((byte) 3, "MapLN_TX", 243 LNLogEntry.create(com.sleepycat.je.tree.MapLN.class), 244 Txnal.TXNAL, 245 Marshall.INSIDE_LATCH, 246 NodeType.LN_INTERNAL); 247 248 public static final LogEntryType LOG_MAPLN = 249 new LogEntryType 250 ((byte) 4, "MapLN", 251 LNLogEntry.create(com.sleepycat.je.tree.MapLN.class), 252 Txnal.NON_TXNAL, 253 Marshall.INSIDE_LATCH, 254 NodeType.LN_INTERNAL); 255 256 public static final LogEntryType LOG_NAMELN_TRANSACTIONAL = 257 createReplicableLogEntryType( 258 (byte) 5, "NameLN_TX", 259 new NameLNLogEntry(), 260 Txnal.TXNAL, 261 Marshall.OUTSIDE_LATCH, 262 Replicable.REPLICABLE_NO_MATCH, 263 NodeType.LN_INTERNAL); 264 265 public static final LogEntryType LOG_NAMELN = 266 createReplicableLogEntryType( 267 (byte) 6, "NameLN", 268 new NameLNLogEntry(), 269 Txnal.NON_TXNAL, 270 Marshall.OUTSIDE_LATCH, 271 Replicable.REPLICABLE_NO_MATCH, 272 NodeType.LN_INTERNAL); 273 274 /* Obsolete in version 8, only used by some log readers. */ 275 public static final LogEntryType LOG_DEL_DUPLN_TRANSACTIONAL = 276 createReplicableLogEntryType( 277 (byte) 7, "DelDupLN_TX", 278 new DeletedDupLNLogEntry(), 279 Txnal.TXNAL, 280 Marshall.OUTSIDE_LATCH, 281 Replicable.REPLICABLE_NO_MATCH, 282 NodeType.LN_USER); 283 284 /* Obsolete in version 8, only used by some log readers. */ 285 public static final LogEntryType LOG_DEL_DUPLN = 286 createReplicableLogEntryType( 287 (byte) 8, "DelDupLN", 288 new DeletedDupLNLogEntry(), 289 Txnal.NON_TXNAL, 290 Marshall.OUTSIDE_LATCH, 291 Replicable.REPLICABLE_NO_MATCH, 292 NodeType.LN_USER); 293 294 /* Obsolete in version 8, only used by DupConvert and some log readers. */ 295 public static final LogEntryType LOG_DUPCOUNTLN_TRANSACTIONAL = 296 new LogEntryType 297 ((byte) 9, "DupCountLN_TX", 298 LNLogEntry.create(com.sleepycat.je.tree.dupConvert.DupCountLN.class), 299 Txnal.TXNAL, 300 Marshall.OUTSIDE_LATCH, 301 NodeType.OLD_DUP); 302 303 /* Obsolete in version 8, only used by DupConvert and some log readers. */ 304 public static final LogEntryType LOG_DUPCOUNTLN = 305 new LogEntryType 306 ((byte) 10, "DupCountLN", 307 LNLogEntry.create(com.sleepycat.je.tree.dupConvert.DupCountLN.class), 308 Txnal.NON_TXNAL, 309 Marshall.OUTSIDE_LATCH, 310 NodeType.OLD_DUP); 311 312 public static final LogEntryType LOG_FILESUMMARYLN = 313 new LogEntryType 314 ((byte) 11, "FileSummaryLN", 315 LNLogEntry.create(com.sleepycat.je.tree.FileSummaryLN.class), 316 Txnal.NON_TXNAL, 317 Marshall.INSIDE_LATCH, 318 NodeType.LN_INTERNAL); 319 320 public static final LogEntryType LOG_IN = 321 new LogEntryType 322 ((byte) 12, "IN", 323 INLogEntry.create(com.sleepycat.je.tree.IN.class), 324 Txnal.NON_TXNAL, 325 Marshall.OUTSIDE_LATCH, 326 NodeType.IN); 327 328 public static final LogEntryType LOG_BIN = 329 new LogEntryType 330 ((byte) 13, "BIN", 331 INLogEntry.create(com.sleepycat.je.tree.BIN.class), 332 Txnal.NON_TXNAL, 333 Marshall.OUTSIDE_LATCH, 334 NodeType.IN); 335 336 /* Obsolete in version 8, only used by DupConvert and some log readers. */ 337 public static final LogEntryType LOG_DIN = 338 new LogEntryType 339 ((byte) 14, "DIN", 340 INLogEntry.create(com.sleepycat.je.tree.dupConvert.DIN.class), 341 Txnal.NON_TXNAL, 342 Marshall.OUTSIDE_LATCH, 343 NodeType.OLD_DUP); 344 345 /* Obsolete in version 8, only used by DupConvert and some log readers. */ 346 public static final LogEntryType LOG_DBIN = 347 new LogEntryType 348 ((byte) 15, "DBIN", 349 INLogEntry.create(com.sleepycat.je.tree.dupConvert.DBIN.class), 350 Txnal.NON_TXNAL, 351 Marshall.OUTSIDE_LATCH, 352 NodeType.OLD_DUP); 353 354 /* 355 * The root entry of the DbTree, it saves the root information for name 356 * and id database. 357 */ 358 public static final LogEntryType LOG_DBTREE = 359 new LogEntryType 360 ((byte) 16, "DbTree", 361 SingleItemEntry.create( 362 com.sleepycat.je.dbi.DbTree.class), 363 Txnal.NON_TXNAL, 364 Marshall.INSIDE_LATCH, 365 NodeType.NONE); 366 367 /* Transactional entries */ 368 public static final LogEntryType LOG_TXN_COMMIT = 369 createReplicableLogEntryType( 370 (byte) 17, "Commit", 371 new CommitLogEntry(), 372 Txnal.TXNAL, 373 Marshall.OUTSIDE_LATCH, 374 Replicable.REPLICABLE_MATCH, 375 NodeType.NONE); 376 377 public static final LogEntryType LOG_TXN_ABORT = 378 createReplicableLogEntryType( 379 (byte) 18, "Abort", 380 new AbortLogEntry(), 381 Txnal.TXNAL, 382 Marshall.OUTSIDE_LATCH, 383 Replicable.REPLICABLE_MATCH, 384 NodeType.NONE); 385 386 public static final LogEntryType LOG_CKPT_START = 387 new LogEntryType 388 ((byte) 19, "CkptStart", 389 SingleItemEntry.create( 390 com.sleepycat.je.recovery.CheckpointStart.class), 391 Txnal.NON_TXNAL, 392 Marshall.OUTSIDE_LATCH, 393 NodeType.NONE); 394 395 public static final LogEntryType LOG_CKPT_END = 396 new LogEntryType 397 ((byte) 20, "CkptEnd", 398 SingleItemEntry.create( 399 com.sleepycat.je.recovery.CheckpointEnd.class), 400 Txnal.NON_TXNAL, 401 Marshall.OUTSIDE_LATCH, 402 NodeType.NONE); 403 404 /* Obsolete in version 8, only used by some log readers. */ 405 public static final LogEntryType LOG_IN_DELETE_INFO = 406 new LogEntryType 407 ((byte) 21, "INDelete", 408 SingleItemEntry.create( 409 com.sleepycat.je.tree.dupConvert.INDeleteInfo.class), 410 Txnal.NON_TXNAL, 411 Marshall.OUTSIDE_LATCH, 412 NodeType.NONE); 413 414 /* Obsolete in version 9, replaced by "live" LOG_BIN_DELTA. */ 415 public static final LogEntryType LOG_OLD_BIN_DELTA = 416 new LogEntryType 417 ((byte) 22, "BINDelta", 418 new OldBINDeltaLogEntry 419 (com.sleepycat.je.tree.OldBINDelta.class), 420 Txnal.NON_TXNAL, 421 Marshall.OUTSIDE_LATCH, 422 NodeType.NONE); 423 424 /* Obsolete in version 8, only used by some log readers. */ 425 public static final LogEntryType LOG_OLD_DUP_BIN_DELTA = 426 new LogEntryType 427 ((byte) 23, "DupBINDelta", 428 new OldBINDeltaLogEntry 429 (com.sleepycat.je.tree.OldBINDelta.class), 430 Txnal.NON_TXNAL, 431 Marshall.OUTSIDE_LATCH, 432 NodeType.NONE); 433 434 /* Administrative entries */ 435 public static final LogEntryType LOG_TRACE = 436 createReplicableLogEntryType( 437 (byte) 24, "Trace", 438 new TraceLogEntry(), 439 Txnal.NON_TXNAL, 440 Marshall.OUTSIDE_LATCH, 441 Replicable.REPLICABLE_NO_MATCH, 442 NodeType.NONE); 443 444 /* File header */ 445 public static final LogEntryType LOG_FILE_HEADER = 446 new LogEntryType 447 ((byte) 25, "FileHeader", 448 new FileHeaderEntry 449 (com.sleepycat.je.log.FileHeader.class), 450 Txnal.NON_TXNAL, 451 Marshall.OUTSIDE_LATCH, 452 NodeType.NONE); 453 454 /* Obsolete in version 8, only used by some log readers. */ 455 public static final LogEntryType LOG_IN_DUPDELETE_INFO = 456 new LogEntryType 457 ((byte) 26, "INDupDelete", 458 SingleItemEntry.create( 459 com.sleepycat.je.tree.dupConvert.INDupDeleteInfo.class), 460 Txnal.NON_TXNAL, 461 Marshall.OUTSIDE_LATCH, 462 NodeType.NONE); 463 464 public static final LogEntryType LOG_TXN_PREPARE = 465 new LogEntryType 466 ((byte) 27, "Prepare", 467 SingleItemEntry.create( 468 com.sleepycat.je.txn.TxnPrepare.class), 469 Txnal.TXNAL, 470 Marshall.OUTSIDE_LATCH, 471 NodeType.NONE); 472 473 public static final LogEntryType LOG_ROLLBACK_START = 474 new LogEntryType 475 ((byte) 28, "RollbackStart", 476 SingleItemEntry.create( 477 com.sleepycat.je.txn.RollbackStart.class), 478 Txnal.NON_TXNAL, 479 Marshall.OUTSIDE_LATCH, 480 NodeType.NONE); 481 482 public static final LogEntryType LOG_ROLLBACK_END = 483 new LogEntryType 484 ((byte) 29, "RollbackEnd", 485 SingleItemEntry.create( 486 com.sleepycat.je.txn.RollbackEnd.class), 487 Txnal.NON_TXNAL, 488 Marshall.OUTSIDE_LATCH, 489 NodeType.NONE); 490 491 public static final LogEntryType LOG_MATCHPOINT = 492 createReplicableLogEntryType( 493 (byte) 30, "Matchpoint", 494 new MatchpointLogEntry(), 495 Txnal.NON_TXNAL, 496 Marshall.OUTSIDE_LATCH, 497 Replicable.REPLICABLE_MATCH, 498 NodeType.NONE); 499 500 public static final LogEntryType LOG_DEL_LN_TRANSACTIONAL = 501 new UserLNLogEntryType((byte) 31, "DEL_LN_TX", Txnal.TXNAL); 502 503 public static final LogEntryType LOG_DEL_LN = 504 new UserLNLogEntryType((byte) 32, "DEL_LN", Txnal.NON_TXNAL); 505 506 public static final LogEntryType LOG_INS_LN_TRANSACTIONAL = 507 new UserLNLogEntryType((byte) 33, "INS_LN_TX", Txnal.TXNAL); 508 509 public static final LogEntryType LOG_INS_LN = 510 new UserLNLogEntryType((byte) 34, "INS_LN", Txnal.NON_TXNAL); 511 512 public static final LogEntryType LOG_UPD_LN_TRANSACTIONAL = 513 new UserLNLogEntryType((byte) 35, "UPD_LN_TX", Txnal.TXNAL); 514 515 public static final LogEntryType LOG_UPD_LN = 516 new UserLNLogEntryType((byte) 36, "UPD_LN", Txnal.NON_TXNAL); 517 518 public static final LogEntryType LOG_BIN_DELTA = 519 new LogEntryType( 520 (byte) 37, "NewBINDelta", 521 new BINDeltaLogEntry(com.sleepycat.je.tree.BIN.class), 522 Txnal.NON_TXNAL, 523 Marshall.OUTSIDE_LATCH, 524 NodeType.IN); 525 526 /*** If you add new types, be sure to update MAX_TYPE_NUM at the top.***/ 527 528 /* Persistent fields */ 529 private final byte typeNum; // persistent value for this entry type 530 531 /* Transient fields */ 532 private final String displayName; 533 private final LogEntry logEntry; 534 535 /* 536 * Attributes 537 */ 538 539 /* Whether the log entry holds a transactional information. */ 540 private Txnal isTransactional; 541 542 /* 543 * Does this log entry be marshalled outside or inside the log write 544 * latch. 545 */ 546 private Marshall marshallBehavior; 547 548 /* Can this log entry be put in the replication stream? */ 549 private Replicable replicationPossible; 550 551 private NodeType nodeType; 552 553 /* 554 * Constructors 555 */ 556 557 /** 558 * For base class support. 559 */ 560 561 /* 562 * This constructor only used when the LogEntryType is being used as a key 563 * for a map. No log types can be defined outside this package. 564 */ LogEntryType(byte typeNum)565 LogEntryType(byte typeNum) { 566 this.typeNum = typeNum; 567 displayName = null; 568 logEntry = null; 569 } 570 571 /** 572 * Used to create a map key for reporting that is not a real type. 573 */ LogEntryType(byte typeNum, String displayName)574 LogEntryType(byte typeNum, String displayName) { 575 assert typeNum > MAX_TYPE_NUM; 576 this.typeNum = typeNum; 577 this.displayName = displayName; 578 logEntry = null; 579 } 580 581 /** 582 * Create a non-replicable log type. 583 * 584 * @param isTransactional whether this type of log entry holds data 585 * involved in a transaction. For example, transaction commit and LN data 586 * records are transactional, but INs are not. 587 * @param marshallBehavior whether this type of log entry may be serialized 588 * outside the log write latch. This is true of the majority of 589 * types. Certain types like the FileSummaryLN rely on the log write latch 590 * to enforce serial semantics. 591 */ LogEntryType(final byte typeNum, final String displayName, final LogEntry logEntry, final Txnal isTransactional, final Marshall marshallBehavior, final NodeType nodeType)592 private LogEntryType(final byte typeNum, 593 final String displayName, 594 final LogEntry logEntry, 595 final Txnal isTransactional, 596 final Marshall marshallBehavior, 597 final NodeType nodeType) { 598 599 this(typeNum, displayName, logEntry, isTransactional, marshallBehavior, 600 Replicable.LOCAL, nodeType); 601 } 602 603 /** 604 * Create a replicable log type. 605 * 606 * @param isTransactional whether this type of log entry holds data 607 * involved in a transaction 608 * @param marshallBehavior whether this type of log entry may be serialized 609 * outside the log write latch 610 * @param replicationPossible whether this type of log entry can be shared 611 * with a replication group 612 */ createReplicableLogEntryType( final byte typeNum, final String displayName, final ReplicableLogEntry logEntry, final Txnal isTransactional, final Marshall marshallBehavior, final Replicable replicationPossible, final NodeType nodeType)613 private static LogEntryType createReplicableLogEntryType( 614 final byte typeNum, 615 final String displayName, 616 final ReplicableLogEntry logEntry, 617 final Txnal isTransactional, 618 final Marshall marshallBehavior, 619 final Replicable replicationPossible, 620 final NodeType nodeType) { 621 622 return new LogEntryType(typeNum, displayName, logEntry, 623 isTransactional, marshallBehavior, 624 replicationPossible, nodeType); 625 } 626 627 /** 628 * Internal constructor for all log types. Don't create instances using 629 * this directly, to improve error checking. 630 */ LogEntryType(final byte typeNum, final String displayName, final LogEntry logEntry, final Txnal isTransactional, final Marshall marshallBehavior, final Replicable replicationPossible, final NodeType nodeType)631 private LogEntryType(final byte typeNum, 632 final String displayName, 633 final LogEntry logEntry, 634 final Txnal isTransactional, 635 final Marshall marshallBehavior, 636 final Replicable replicationPossible, 637 final NodeType nodeType) { 638 639 this.typeNum = typeNum; 640 this.displayName = displayName; 641 this.logEntry = logEntry; 642 this.isTransactional = isTransactional; 643 this.marshallBehavior = marshallBehavior; 644 this.replicationPossible = replicationPossible; 645 this.nodeType = nodeType; 646 logEntry.setLogType(this); 647 LOG_TYPES[typeNum - 1] = this; 648 649 assert logEntry != null && replicationPossible != null; 650 assert !replicationPossible.isReplicable() || 651 logEntry instanceof ReplicableLogEntry 652 : "Replicable log types must have replicable log entries"; 653 } 654 655 /** 656 * @return the static version of this type 657 */ findType(byte typeNum)658 public static LogEntryType findType(byte typeNum) { 659 if (typeNum <= 0 || typeNum > MAX_TYPE_NUM) { 660 return null; 661 } 662 return LOG_TYPES[typeNum - 1]; 663 } 664 665 /** 666 * Get a copy of all types for unit testing. 667 */ getAllTypes()668 public static Set<LogEntryType> getAllTypes() { 669 HashSet<LogEntryType> ret = new HashSet<LogEntryType>(); 670 671 for (int i = 0; i < MAX_TYPE_NUM; i++) { 672 ret.add(LOG_TYPES[i]); 673 } 674 return ret; 675 } 676 677 /** 678 * @return the log entry type owned by the shared, static version 679 */ getSharedLogEntry()680 public LogEntry getSharedLogEntry() { 681 return logEntry; 682 } 683 684 /** 685 * @return a clone of the log entry type for a given log type. 686 */ getNewLogEntry()687 public LogEntry getNewLogEntry() 688 throws DatabaseException { 689 690 return logEntry.clone(); 691 } 692 getTypeNum()693 public byte getTypeNum() { 694 return typeNum; 695 } 696 697 /** 698 * @return true if type number is valid. 699 */ isValidType(byte typeNum)700 static boolean isValidType(byte typeNum) { 701 return typeNum > 0 && typeNum <= MAX_TYPE_NUM; 702 } 703 toStringNoVersion()704 public String toStringNoVersion() { 705 return displayName; 706 } 707 708 @Override toString()709 public String toString() { 710 return displayName; 711 } 712 713 /** 714 * Check for equality without making a new object. 715 */ equalsType(byte type)716 public boolean equalsType(byte type) { 717 return (this.typeNum == type); 718 } 719 720 /* 721 * Override Object.equals. Ignore provisional bit when checking for 722 * equality. 723 */ 724 @Override equals(Object obj)725 public boolean equals(Object obj) { 726 /* Same instance? */ 727 if (this == obj) { 728 return true; 729 } 730 731 /* Is it the right type of object? */ 732 if (!(obj instanceof LogEntryType)) { 733 return false; 734 } 735 736 return typeNum == ((LogEntryType) obj).typeNum; 737 } 738 739 /** 740 * This is used as a hash key. 741 */ 742 @Override hashCode()743 public int hashCode() { 744 return typeNum; 745 } 746 747 static enum Txnal { 748 TXNAL(true), 749 NON_TXNAL(false); 750 751 private final boolean isTxnal; 752 Txnal(boolean isTxnal)753 Txnal(boolean isTxnal) { 754 this.isTxnal = isTxnal; 755 } 756 isTransactional()757 boolean isTransactional() { 758 return isTxnal; 759 } 760 } 761 762 /** 763 * Return true if this log entry has transactional information in it, 764 * like a commit or abort record, or a transactional LN. 765 */ isTransactional()766 public boolean isTransactional() { 767 return isTransactional.isTransactional(); 768 } 769 770 static enum Marshall { 771 OUTSIDE_LATCH(true), 772 INSIDE_LATCH(false); 773 774 private final boolean marshallOutsideLatch; 775 Marshall(boolean marshallOutsideLatch)776 Marshall(boolean marshallOutsideLatch) { 777 this.marshallOutsideLatch = marshallOutsideLatch; 778 } 779 marshallOutsideLatch()780 boolean marshallOutsideLatch() { 781 return marshallOutsideLatch; 782 } 783 } 784 785 /** 786 * Return true if this log entry should be marshalled into a buffer outside 787 * the log write latch. Currently, only the FileSummaryLN and MapLN (which 788 * contains DbFileSummary objects) need to be logged inside the log write 789 * latch. 790 */ marshallOutsideLatch()791 public boolean marshallOutsideLatch() { 792 return marshallBehavior.marshallOutsideLatch(); 793 } 794 795 /** 796 * Return true if the type of this LogEntryType is equivalent to typeB. 797 * Version is used as a factor in the comparison when new log entry types 798 * are introduced in one release, which supercede existing types. 799 */ compareTypeAndVersion(@uppressWarningsR) int versionA, @SuppressWarnings(R) int versionB, final byte typeB)800 public boolean compareTypeAndVersion(@SuppressWarnings("unused") 801 int versionA, 802 @SuppressWarnings("unused") 803 int versionB, 804 final byte typeB) { 805 return typeNum == typeB; 806 } 807 808 /* 809 * Indicates whether this type of log entry is shared in a replicated 810 * environment or not, and whether it can be used as a replication 811 * matchpoint. 812 */ 813 static enum Replicable { 814 REPLICABLE_MATCH(true, true), 815 REPLICABLE_NO_MATCH(true, false), 816 LOCAL(false, false); 817 818 private final boolean isReplicable; 819 private final boolean isMatchable; 820 Replicable(boolean isReplicable, boolean isMatchable)821 Replicable(boolean isReplicable, boolean isMatchable) { 822 this.isReplicable = isReplicable; 823 this.isMatchable = isMatchable; 824 } 825 isReplicable()826 boolean isReplicable() { 827 return isReplicable; 828 } 829 isMatchable()830 boolean isMatchable() { 831 return isMatchable; 832 } 833 } 834 835 /** 836 * Return true if this type of log entry can be part of the replication 837 * stream. For example, INs can never be replicated, while LNs are 838 * replicated only if their owning database is replicated. 839 */ isReplicationPossible()840 public boolean isReplicationPossible() { 841 return replicationPossible.isReplicable(); 842 } 843 844 /** 845 * Return true if this type of log entry can serve as the synchronization 846 * matchpoint for the replication stream. That generally means that this 847 * log entry contains an replication node ID. 848 */ isSyncPoint()849 public boolean isSyncPoint() { 850 return replicationPossible.isMatchable(); 851 } 852 853 /** 854 * Return true if this type of log entry can serve as the synchronization 855 * matchpoint for the replication stream. 856 */ isSyncPoint(byte entryType)857 public static boolean isSyncPoint(byte entryType) { 858 return findType(entryType).isSyncPoint(); 859 } 860 861 /* Type of Btree node. */ 862 static enum NodeType { 863 864 /* Not a Btree node. */ 865 NONE, 866 867 /* Internal node. Does not include old-format DIN/DBIN. */ 868 IN, 869 870 /* DIN/DBIN/DupCountLN in old-format duplicates database. */ 871 OLD_DUP, 872 873 /* LNs representing records in internal databases. */ 874 LN_INTERNAL, 875 876 /* LNs representing ordinary user records. */ 877 LN_USER; 878 } 879 isNodeType()880 public boolean isNodeType() { 881 return nodeType != NodeType.NONE; 882 } 883 isUserLNType()884 public boolean isUserLNType() { 885 return nodeType == NodeType.LN_USER; 886 } 887 isLNType()888 public boolean isLNType() { 889 return nodeType == NodeType.LN_INTERNAL || isUserLNType(); 890 } 891 isINType()892 public boolean isINType() { 893 return nodeType == NodeType.IN; 894 } 895 isOldDupType()896 public boolean isOldDupType() { 897 return nodeType == NodeType.OLD_DUP; 898 } 899 900 /** 901 * Return true if the two types are equal. Handles the situation where new 902 * log entry types were introduced in one release, that are actually 903 * equivalent to old, deprecated types. 904 */ compareTypeAndVersion(int versionA, byte typeA, int versionB, byte typeB)905 public static boolean compareTypeAndVersion(int versionA, 906 byte typeA, 907 int versionB, 908 byte typeB) { 909 LogEntryType entryA = findType(typeA); 910 return entryA.compareTypeAndVersion(versionA, versionB, typeB); 911 } 912 913 private static class UserLNLogEntryType extends LogEntryType { UserLNLogEntryType(byte typeNum, String displayName, Txnal txnal)914 public UserLNLogEntryType(byte typeNum, 915 String displayName, 916 Txnal txnal) { 917 super(typeNum, displayName, 918 LNLogEntry.create(com.sleepycat.je.tree.LN.class), 919 txnal, Marshall.OUTSIDE_LATCH, 920 Replicable.REPLICABLE_NO_MATCH, NodeType.LN_USER); 921 } 922 923 @Override compareTypeAndVersion(int versionA, int versionB, byte typeB)924 public boolean compareTypeAndVersion(int versionA, 925 int versionB, 926 byte typeB) { 927 /* If the other entry is newer, the types should match. */ 928 if (versionA <= versionB && getTypeNum() == typeB) { 929 return true; 930 } 931 932 /* 933 * If the other entry is older, the type might be an old, 934 * deprecated, equivalent type. 935 */ 936 if ((versionA > versionB) && isEquivalentOldType(typeB)) { 937 return true; 938 } 939 940 /* 941 * In this case, the other entry's version is older or newer but it 942 * doesn't matter -- it's completely the wrong type. 943 */ 944 return false; 945 } 946 isEquivalentOldType(byte typeB)947 private boolean isEquivalentOldType(byte typeB) { 948 if ((!isTransactional() && (typeB == LOG_OLD_LN.getTypeNum())) || 949 (isTransactional() && 950 (typeB == LOG_OLD_LN_TRANSACTIONAL.getTypeNum()))) { 951 return true; 952 } 953 954 return false; 955 } 956 } 957 } 958