/** Synchs in-core transactions to data file and opens a fresh log */ private void synchronizeLogFromMemory() throws IOException { close(); TreeSet<BlockIo> blockList = new TreeSet<BlockIo>(new BlockIoComparator()); int numBlocks = 0; int writtenBlocks = 0; for (int i = 0; i < _maxTxns; i++) { if (txns[i] == null) continue; // Add each block to the blockList, replacing the old copy of this // block if necessary, thus avoiding writing the same block twice for (Iterator<BlockIo> k = txns[i].iterator(); k.hasNext(); ) { BlockIo block = k.next(); if (blockList.contains(block)) { block.decrementTransactionCount(); } else { writtenBlocks++; boolean result = blockList.add(block); } numBlocks++; } txns[i] = null; } // Write the blocks from the blockList to disk synchronizeBlocks(blockList, true); owner.sync(); open(); }
/** Startup recovery on all files */ private void recover() throws IOException { String logName = makeLogName(); File logFile = new File(logName); if (!logFile.exists()) return; if (logFile.length() == 0) { logFile.delete(); return; } FileInputStream fis = new FileInputStream(logFile); DataInputStream ois = new DataInputStream(new BufferedInputStream(fis)); try { if (ois.readShort() != Magic.LOGFILE_HEADER) throw new Error("Bad magic on log file"); } catch (IOException e) { // corrupted/empty logfile logFile.delete(); return; } while (true) { ArrayList<BlockIo> blocks = null; try { blocks = (ArrayList<BlockIo>) Serialization.readObject(ois); } catch (ClassNotFoundException e) { throw new Error("Unexcepted exception: " + e); } catch (IOException e) { // corrupted logfile, ignore rest of transactions break; } synchronizeBlocks(blocks, false); // ObjectInputStream must match exactly each // ObjectOutputStream created during writes // try { ois = new DataInputStream(fis); // } catch (IOException e) { // // corrupted logfile, ignore rest of transactions // break; // } } owner.sync(); fis.close(); logFile.delete(); }