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.nio.ByteBuffer; 11 import java.util.HashMap; 12 import java.util.Map; 13 14 import javax.transaction.xa.Xid; 15 16 import com.sleepycat.je.DatabaseException; 17 import com.sleepycat.je.dbi.DatabaseId; 18 import com.sleepycat.je.dbi.EnvironmentImpl; 19 import com.sleepycat.je.log.entry.LNLogEntry; 20 import com.sleepycat.je.log.entry.LogEntry; 21 import com.sleepycat.je.log.entry.NameLNLogEntry; 22 import com.sleepycat.je.txn.RollbackEnd; 23 import com.sleepycat.je.txn.RollbackStart; 24 import com.sleepycat.je.txn.TxnAbort; 25 import com.sleepycat.je.txn.TxnCommit; 26 import com.sleepycat.je.txn.TxnPrepare; 27 28 /** 29 * LNFileReader scans log files for LNs. Also, if it's going backwards for the 30 * undo phase in recovery, it reads transaction commit entries. 31 */ 32 public class LNFileReader extends FileReader { 33 34 /* 35 * targetEntryMap maps DbLogEntryTypes to log entries. We use this 36 * collection to find the right LogEntry instance to read in the current 37 * entry. 38 */ 39 protected Map<LogEntryType, LogEntry> targetEntryMap; 40 protected LogEntry targetLogEntry; 41 42 private long ckptEnd; 43 44 /** 45 * Create this reader to start at a given LSN. 46 * @param env The relevant EnvironmentImpl 47 * @param readBufferSize buffer size in bytes for reading in log 48 * @param startLsn where to start in the log 49 * @param redo If true, we're going to go forward from 50 * the start LSN to the end of the log. If false, we're going 51 * backwards from the end of the log to the start LSN. 52 * @param finishLsn the last LSN to read in the log. May be null if we 53 * want to read to the end of the log. 54 * @param endOfFileLsn the virtual LSN that marks the end of the log. (The 55 * one off the end of the log). Only used if we're reading backwards. 56 * Different from the startLsn because the startLsn tells us where the 57 * beginning of the start entry is, but not the length/end of the start 58 * entry. May be null if we're going foward. 59 */ LNFileReader(EnvironmentImpl env, int readBufferSize, long startLsn, boolean redo, long endOfFileLsn, long finishLsn, Long singleFileNum, long ckptEnd)60 public LNFileReader(EnvironmentImpl env, 61 int readBufferSize, 62 long startLsn, 63 boolean redo, 64 long endOfFileLsn, 65 long finishLsn, 66 Long singleFileNum, 67 long ckptEnd) 68 throws DatabaseException { 69 70 super(env, readBufferSize, redo /*forward*/, startLsn, 71 singleFileNum, endOfFileLsn, finishLsn); 72 73 this.ckptEnd = ckptEnd; 74 targetEntryMap = new HashMap<LogEntryType, LogEntry>(); 75 } 76 addTargetType(LogEntryType entryType)77 public void addTargetType(LogEntryType entryType) 78 throws DatabaseException { 79 80 targetEntryMap.put(entryType, entryType.getNewLogEntry()); 81 } 82 83 /** 84 * @return true if this is a transactional LN or Locker Commit entry. 85 */ 86 @Override isTargetEntry()87 protected boolean isTargetEntry() { 88 89 if (currentEntryHeader.getProvisional().isProvisional 90 (getLastLsn(), ckptEnd)) { 91 /* Skip provisionial entries */ 92 targetLogEntry = null; 93 } else { 94 LogEntryType fromLogType = 95 new LogEntryType(currentEntryHeader.getType()); 96 97 /* Is it a target entry? */ 98 targetLogEntry = targetEntryMap.get(fromLogType); 99 } 100 return (targetLogEntry != null); 101 } 102 103 /** 104 * This reader instantiates an LN and key for every LN entry. 105 */ 106 @Override processEntry(ByteBuffer entryBuffer)107 protected boolean processEntry(ByteBuffer entryBuffer) 108 throws DatabaseException { 109 110 targetLogEntry.readEntry(envImpl, currentEntryHeader, entryBuffer); 111 return true; 112 } 113 114 /** 115 * @return true if the last entry was an LN. 116 */ isLN()117 public boolean isLN() { 118 return (targetLogEntry instanceof LNLogEntry); 119 } 120 121 /** 122 * Get the last LN log entry seen by the reader. Note that 123 * LNLogEntry.postFetchInit must be called before calling certain 124 * LNLogEntry methods. 125 */ getLNLogEntry()126 public LNLogEntry<?> getLNLogEntry() { 127 return (LNLogEntry<?>) targetLogEntry; 128 } 129 130 /** 131 * Returns a NameLNLogEntry if the LN is a NameLN, or null otherwise. 132 */ getNameLNLogEntry()133 public NameLNLogEntry getNameLNLogEntry() { 134 return (targetLogEntry instanceof NameLNLogEntry) ? 135 ((NameLNLogEntry) targetLogEntry) : 136 null; 137 } 138 139 /** 140 * Get the last databaseId seen by the reader. 141 */ getDatabaseId()142 public DatabaseId getDatabaseId() { 143 return targetLogEntry.getDbId(); 144 } 145 146 /** 147 * @return the transaction id of the current entry. 148 */ getTxnId()149 public Long getTxnId() { 150 return ((LNLogEntry<?>) targetLogEntry).getTxnId(); 151 } 152 153 /* 154 * @return true if the last entry was a TxnPrepare record. 155 */ isPrepare()156 public boolean isPrepare() { 157 return (targetLogEntry.getMainItem() instanceof TxnPrepare); 158 } 159 160 /** 161 * Get the last txn prepare id seen by the reader. 162 */ getTxnPrepareId()163 public long getTxnPrepareId() { 164 return ((TxnPrepare) targetLogEntry.getMainItem()).getId(); 165 } 166 167 /** 168 * Get the last txn prepare Xid seen by the reader. 169 */ getTxnPrepareXid()170 public Xid getTxnPrepareXid() { 171 return ((TxnPrepare) targetLogEntry.getMainItem()).getXid(); 172 } 173 174 /* 175 * @return true if the last entry was a TxnCommit record. 176 */ isCommit()177 public boolean isCommit() { 178 return (targetLogEntry.getMainItem() instanceof TxnCommit); 179 } 180 181 /* 182 * @return true if the last entry was a RollbackStart record. 183 */ isRollbackStart()184 public boolean isRollbackStart() { 185 return (targetLogEntry.getMainItem() instanceof RollbackStart); 186 } 187 188 /* 189 * @return true if the last entry was a RollbackStart record. 190 */ isRollbackEnd()191 public boolean isRollbackEnd() { 192 return (targetLogEntry.getMainItem() instanceof RollbackEnd); 193 } 194 getMainItem()195 public Object getMainItem() { 196 return targetLogEntry.getMainItem(); 197 } 198 199 /* 200 * For error message. 201 */ dumpCurrentHeader()202 public String dumpCurrentHeader() { 203 return currentEntryHeader.toString(); 204 } 205 206 /* 207 * @return true if the last entry was a TxnAbort record. 208 */ isAbort()209 public boolean isAbort() { 210 return (targetLogEntry.getMainItem() instanceof TxnAbort); 211 } 212 213 /** 214 * Get the last txn abort id seen by the reader. 215 */ getTxnAbortId()216 public long getTxnAbortId() { 217 return ((TxnAbort) targetLogEntry.getMainItem()).getId(); 218 } 219 220 /** 221 * Get the last txn commit id seen by the reader. 222 */ getTxnCommitId()223 public long getTxnCommitId() { 224 return ((TxnCommit) targetLogEntry.getMainItem()).getId(); 225 } 226 227 /** 228 * Get last abort LSN seen by the reader (may be null). 229 */ getAbortLsn()230 public long getAbortLsn() { 231 return ((LNLogEntry<?>) targetLogEntry).getAbortLsn(); 232 } 233 234 /** 235 * Get last abort known deleted seen by the reader. 236 */ getAbortKnownDeleted()237 public boolean getAbortKnownDeleted() { 238 return ((LNLogEntry<?>) targetLogEntry).getAbortKnownDeleted(); 239 } 240 isInvisible()241 public boolean isInvisible() { 242 return currentEntryHeader.isInvisible(); 243 } 244 245 /** 246 * Return the VLSN if this entry is in replicated stream. 247 */ getVLSN()248 public long getVLSN() { 249 assert entryIsReplicated(); 250 return currentEntryHeader.getVLSN().getSequence(); 251 } 252 } 253