package com.alibaba.doris.dataserver.store.log.db; import com.alibaba.doris.common.data.ActionPair; import com.alibaba.doris.common.data.Pair; import com.alibaba.doris.common.data.Value; import com.alibaba.doris.common.data.impl.ActionPairImpl; import com.alibaba.doris.common.data.impl.ByteWrapperValueImpl; import com.alibaba.doris.dataserver.store.ClosableIterator; import com.alibaba.doris.dataserver.store.log.LogStorageException; import com.alibaba.doris.dataserver.store.log.entry.LogEntry; /** * @author ajun Email:jack.yuj@alibaba-inc.com */ public class LogClumpsIterator implements ClosableIterator<Pair> { public LogClumpsIterator(LogClump[] clumpArray) { this.clumpArray = clumpArray; this.index = 0; nextLogClump(); this.currentLogEntry = getNextLogEntry(); } public boolean hasNext() { return currentLogEntry != null; } public Pair next() { if (null != currentLogEntry) { LogEntry preLogEntry = currentLogEntry; currentLogEntry = getNextLogEntry(); return convertLogEntryToPair(preLogEntry); } throw new IndexOutOfBoundsException(); } protected LogEntry getNextLogEntry() { while (null != currentReadWindow) { if (currentReadWindow.hasNext()) { LogEntry logEntry = currentReadWindow.next(); if (doFilter(logEntry)) { return logEntry; } } else { nextLogClump(); } } return null; } protected boolean doFilter(LogEntry logEntry) { return true; } private Pair convertLogEntryToPair(LogEntry entry) { Value value = entry.getValue(); if (value instanceof ByteWrapperValueImpl) { //It is important to copy the log value data, , because the data buffer of reading is shared by all threads. value = ((ByteWrapperValueImpl) value).checkAndCopyValue(); } switch (entry.getType()) { case DELETE: { return new ActionPairImpl(ActionPair.Type.DELETE, entry.getKey(), value); } case SET: { return new ActionPairImpl(ActionPair.Type.SET, entry.getKey(), value); } default: { throw new LogStorageException("Unknown log entry type " + entry.getType()); } } } public void remove() { throw new UnsupportedOperationException("Log storage can't remove one log entry."); } private void nextLogClump() { if (index < clumpArray.length) { if (null != currentReadWindow) { currentReadWindow.close(); } currentLogClump = clumpArray[index++]; currentReadWindow = currentLogClump.getReadWindow(); return; } currentLogClump = null; if (null != currentReadWindow) { currentReadWindow.close();// Here, It's important to free file handler. currentReadWindow = null; } return; } public void close() { if (null != currentReadWindow) { currentReadWindow.close(); } } private LogClump[] clumpArray; private LogClump currentLogClump; private LogEntry currentLogEntry; private int index; private ReadWindow currentReadWindow; }