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