package com.sleepycat.je.log; import java.io.IOException; import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.dbi.DatabaseId; import com.sleepycat.je.dbi.EnvironmentImpl; import com.sleepycat.je.log.entry.INLogEntry; import com.sleepycat.je.log.entry.LNLogEntry; import com.sleepycat.je.log.entry.LogEntry; import com.sleepycat.je.tree.IN; import com.sleepycat.je.tree.LN; import com.sleepycat.je.utilint.DbLsn; import de.ovgu.cide.jakutil.*; /** * CleanerFileReader scans log files for INs and LNs. */ public class CleanerFileReader extends FileReader { private static final byte IS_IN=0; private static final byte IS_LN=1; private static final byte IS_ROOT=2; private Map targetEntryMap; private LogEntry targetLogEntry; private byte targetCategory; /** * Create this reader to start at a given LSN. * @param env The relevant EnvironmentImpl. * @param readBufferSize buffer size in bytes for reading in log. * @param startLsn where to start in the log, or null for the beginning. * @param fileNum single file number. */ public CleanerFileReader( EnvironmentImpl env, int readBufferSize, long startLsn, Long fileNum) throws IOException, DatabaseException { super(env,readBufferSize,true,startLsn,fileNum,DbLsn.NULL_LSN,DbLsn.NULL_LSN); targetEntryMap=new HashMap(); addTargetType(IS_LN,LogEntryType.LOG_LN_TRANSACTIONAL); addTargetType(IS_LN,LogEntryType.LOG_LN); addTargetType(IS_LN,LogEntryType.LOG_NAMELN_TRANSACTIONAL); addTargetType(IS_LN,LogEntryType.LOG_NAMELN); addTargetType(IS_LN,LogEntryType.LOG_MAPLN_TRANSACTIONAL); addTargetType(IS_LN,LogEntryType.LOG_MAPLN); addTargetType(IS_LN,LogEntryType.LOG_DEL_DUPLN_TRANSACTIONAL); addTargetType(IS_LN,LogEntryType.LOG_DEL_DUPLN); addTargetType(IS_LN,LogEntryType.LOG_DUPCOUNTLN_TRANSACTIONAL); addTargetType(IS_LN,LogEntryType.LOG_DUPCOUNTLN); addTargetType(IS_LN,LogEntryType.LOG_FILESUMMARYLN); addTargetType(IS_IN,LogEntryType.LOG_IN); addTargetType(IS_IN,LogEntryType.LOG_BIN); addTargetType(IS_IN,LogEntryType.LOG_DIN); addTargetType(IS_IN,LogEntryType.LOG_DBIN); addTargetType(IS_ROOT,LogEntryType.LOG_ROOT); } private void addTargetType( byte category, LogEntryType entryType) throws DatabaseException { targetEntryMap.put(entryType,new EntryInfo(entryType.getNewLogEntry(),category)); } /** * Helper for determining the starting position and opening * up a file at the desired location. */ protected void initStartingPosition( long endOfFileLsn, Long fileNum) throws IOException, DatabaseException { eof=false; readBufferFileNum=fileNum.longValue(); readBufferFileEnd=0; nextEntryOffset=readBufferFileEnd; } /** * @return true if this is a type we're interested in. */ protected boolean isTargetEntry( byte entryTypeNum, byte entryTypeVersion){ LogEntryType fromLogType=new LogEntryType(entryTypeNum,entryTypeVersion); EntryInfo info=(EntryInfo)targetEntryMap.get(fromLogType); if (info == null) { return false; } else { targetCategory=info.targetCategory; targetLogEntry=info.targetLogEntry; return true; } } /** * This reader instantiates an LN and key for every LN entry. */ protected boolean processEntry( ByteBuffer entryBuffer) throws DatabaseException { targetLogEntry.readEntry(entryBuffer,currentEntrySize,currentEntryTypeVersion,true); return true; } /** * @return true if the last entry was an IN. */ public boolean isIN(){ return (targetCategory == IS_IN); } /** * @return true if the last entry was a LN. */ public boolean isLN(){ return (targetCategory == IS_LN); } /** * @return true if the last entry was a root */ public boolean isRoot(){ return (targetCategory == IS_ROOT); } /** * Get the last LN seen by the reader. */ public LN getLN(){ return ((LNLogEntry)targetLogEntry).getLN(); } /** * Get the last entry seen by the reader as an IN. */ public IN getIN() throws DatabaseException { return ((INLogEntry)targetLogEntry).getIN(env); } /** * Get the last databaseId seen by the reader. */ public DatabaseId getDatabaseId(){ if (targetCategory == IS_LN) { return ((LNLogEntry)targetLogEntry).getDbId(); } else if (targetCategory == IS_IN) { return ((INLogEntry)targetLogEntry).getDbId(); } else { return null; } } /** * Get the last key seen by the reader. */ public byte[] getKey(){ return ((LNLogEntry)targetLogEntry).getKey(); } /** * Get the last key seen by the reader. */ public byte[] getDupTreeKey(){ return ((LNLogEntry)targetLogEntry).getDupKey(); } private static class EntryInfo { public LogEntry targetLogEntry; public byte targetCategory; EntryInfo( LogEntry targetLogEntry, byte targetCategory){ this.targetLogEntry=targetLogEntry; this.targetCategory=targetCategory; } } }