package com.github.ltsopensource.kv.replay; import com.github.ltsopensource.core.logger.Logger; import com.github.ltsopensource.core.support.SystemClock; import com.github.ltsopensource.kv.*; import com.github.ltsopensource.kv.cache.DataCache; import com.github.ltsopensource.kv.data.DataAppendResult; import com.github.ltsopensource.kv.data.DataBlockEngine; import com.github.ltsopensource.kv.index.Index; import com.github.ltsopensource.kv.index.IndexItem; import com.github.ltsopensource.kv.txlog.StoreTxLogCursorEntry; import com.github.ltsopensource.kv.txlog.StoreTxLogEngine; import com.github.ltsopensource.kv.txlog.StoreTxLogEntry; import com.github.ltsopensource.kv.txlog.StoreTxLogPosition; /** * @author Robert HG (254963746@qq.com) on 12/19/15. */ public class TxLogReplay<K, V> { private static final Logger LOGGER = DB.LOGGER; private StoreTxLogEngine<K, V> storeTxLogEngine; private DataBlockEngine<K, V> dataBlockEngine; private Index<K, V> index; private DataCache<K, V> dataCache; public TxLogReplay(StoreTxLogEngine<K, V> storeTxLogEngine, DataBlockEngine<K, V> dataBlockEngine, Index<K, V> index, DataCache<K, V> dataCache) { this.storeTxLogEngine = storeTxLogEngine; this.dataBlockEngine = dataBlockEngine; this.index = index; this.dataCache = dataCache; } public void replay(StoreTxLogPosition startPosition) { LOGGER.info("start to replay txLog ..."); Cursor<StoreTxLogCursorEntry<K, V>> cursor = storeTxLogEngine.cursor(startPosition); int count = 0; long startTime = SystemClock.now(); while (cursor.hasNext()) { StoreTxLogCursorEntry<K, V> storeTxLogCursorEntry = cursor.next(); StoreTxLogEntry<K, V> storeTxLogEntry = storeTxLogCursorEntry.getStoreTxLogEntry(); Operation op = storeTxLogEntry.getOp(); StoreTxLogPosition position = storeTxLogCursorEntry.getPosition(); K key = storeTxLogEntry.getKey(); V value = storeTxLogEntry.getValue(); if (op == Operation.PUT) { // 1. 写Data DataAppendResult dataAppendResult = dataBlockEngine.append(position, key, value); // 2. 写Index index.putIndexItem(position, key, DBImpl.convertToIndex(key, dataAppendResult)); // 3. 写缓存 // dataCache.put(key, value); } else if (op == Operation.REMOVE) { // 1. 移除Index IndexItem<K> indexItem = index.removeIndexItem(position, key); if (indexItem != null) { // 2. 移除Data dataBlockEngine.remove(position, indexItem); } // // 2. 移除缓存 // dataCache.remove(key); } else { throw new DBException("error op=" + op); } count++; } LOGGER.info("replay txLog complete, txLog size:" + count + ", cost mills:" + (SystemClock.now() - startTime)); } }