1 19 package org.netbeans.mdr.persistence.btreeimpl.btreestorage; 20 21 import java.io.*; 22 import java.text.*; 23 import java.util.*; 24 25 import org.netbeans.mdr.persistence.*; 26 27 39 class LogFile { 40 41 42 private int pageSize; 43 44 45 private int numFiles; 46 47 48 private final String baseName; 49 50 51 private String name; 52 53 54 private BitSet pageBitmaps[]; 55 56 57 private MapPage currentMap; 58 59 60 private FileCache cache; 61 62 63 long fileId; 64 65 66 private int beforeWriteFailure = -1; 67 private int afterCommitFailure = -1; 68 private int recoveryFailure = -1; 69 70 82 LogFile(FileCache fCache, String baseName, int pgSz, int files, long id) 83 throws StorageException { 84 cache = fCache; 87 pageSize = pgSz; 88 this.baseName = baseName; 89 numFiles = files; 90 fileId = id; 91 pageBitmaps = new BitSet[files]; 92 for (int i = 0; i < files; i++) 93 pageBitmaps[i] = new BitSet(); 94 95 if (new File(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL)).exists()) 96 recover(); 97 } 98 99 100 private boolean isPageLogged(CachedPage page) { 101 return pageBitmaps[page.key.fileIndex].get(page.key.offset/pageSize); 102 } 103 104 105 private RandomAccessFile createPhysicalLog() throws StorageException { 106 String name = BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL); 107 RandomAccessFile file = null; 108 try { 109 file = FileCache.getFile(name); 110 file.setLength(0); 111 writeMap(file); 112 return file; 113 } catch (IOException ex) { 114 throw new StorageIOException(ex); 115 } finally { 116 if (file != null) { 117 this.name = name; 118 } 119 } 120 } 121 122 126 void addPageToLog(CachedPage page) throws StorageException { 127 128 if (page.key.offset >= currentMap.getEOF(page.key.fileIndex)) { 129 return; 130 } 131 132 if (isPageLogged(page)) 133 return; 134 135 RandomAccessFile file; 136 try { 137 file = name == null ? createPhysicalLog() : FileCache.getFile(name); 138 file.seek(currentMap.nextPageOffset()); 139 file.write(page.contents); 140 } 141 catch (IOException ex) { 142 throw new StorageIOException(ex); 143 } 144 145 beforeWriteFailure = 146 cache.checkForForcedFailure( 147 "org.netbeans.mdr.persistence.btreeimpl.btreestorage.LogFile.beforeWriteFailure", 148 beforeWriteFailure); 149 pageBitmaps[page.key.fileIndex].set(page.key.offset/pageSize); 150 151 152 currentMap.add(page); 153 if (currentMap.isFull()) { 154 155 writeMap(file); 157 } 158 159 160 cache.holdForLog(page); 161 } 162 163 164 private void writeMap(RandomAccessFile file) throws StorageException{ 165 flushFile(file); 166 currentMap.write(file); 167 flushFile(file); 168 if (currentMap.isFull()) 169 currentMap = new MapPage(currentMap); 170 } 171 172 173 private void flushFile(RandomAccessFile file) throws StorageException{ 174 try { 175 file.getFD().sync(); 176 } 177 catch (IOException ex) { 178 throw new StorageIOException(ex); 179 } 180 } 181 182 185 void flush() throws StorageException{ 186 try { 187 writeMap(FileCache.getFile(name)); 188 cache.logWasFlushed(); 189 } catch (IOException e) { 190 throw new StorageIOException(e); 191 } 192 } 193 194 200 void begin(String fileNames[], long timeStamp, long newTimeStamp) 201 throws StorageException { 202 203 name = null; 204 currentMap = new MapPage(pageSize, numFiles, 0); 205 RandomAccessFile files[]; 206 try { 207 files = FileCache.getFiles(fileNames); 208 } catch (IOException e) { 209 throw new StorageIOException(e); 210 } 211 currentMap.setEOFs(files); 212 for (int i = 0; i < numFiles; i++) { 213 pageBitmaps[i].xor(pageBitmaps[i]); 214 } 215 currentMap.setTimeStamps(timeStamp, newTimeStamp); 216 currentMap.setFileID(fileId); 217 } 218 219 222 void commit() throws StorageException{ 223 try { 224 if (name != null) { 225 FileCache.closeFile(name); 226 new File(name).delete(); 227 } 228 } 229 catch (IOException ex) { 230 throw new StorageIOException(ex); 231 } 232 name = null; 233 afterCommitFailure = 234 cache.checkForForcedFailure( 235 "org.netbeans.mdr.persistence.btreeimpl.btreestorage.LogFile.afterCommitFailure", 236 afterCommitFailure); 237 } 238 239 242 void close() throws StorageException{ 243 try { 244 if (name != null) { 245 FileCache.closeFile(name); 246 } 247 } catch (IOException ex) { 248 throw new StorageIOException(ex); 249 } 250 } 251 252 253 int fileSize() { 254 return currentMap.nextPageOffset(); 255 } 256 257 263 void recover() throws StorageException { 264 RandomAccessFile files[] = null; 265 RandomAccessFile logFile = null; 266 267 try { 268 try { 269 logFile = new RandomAccessFile(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL), "r"); 270 files = cache.getFiles(); 271 if (files.length != numFiles) { 272 throw new StorageBadRequestException( 273 MessageFormat.format( 274 "Log file contains {0} files; {1} were requested", 275 new Object [] { 276 new Integer (numFiles), 277 new Integer (files.length)})); 278 } 279 280 int numPages = (int)logFile.length() / pageSize; 281 if (numPages > 0) { 282 byte pageBuffer[] = new byte[pageSize]; 283 284 MapPage page = new MapPage(logFile, 0, pageSize); 285 page.checkParameters(pageSize, numFiles); 286 287 for (int i = 0; i < numFiles; i++) { 288 page.checkFileHeader(files[i]); 289 290 } 291 while (true) { 292 page.recover(files, logFile, numPages, pageBuffer); 293 294 recoveryFailure = 295 cache.checkForForcedFailure( 296 "org.netbeans.mdr.persistence.btreeimpl.btreestorage.LogFile.recoveryFailure", 297 recoveryFailure); 298 MapPage newPage = page.getNext(logFile, numPages); 299 if (newPage != null && !newPage.isEmpty()) { 300 page = newPage; 301 } 302 else { 303 break; 304 } 305 } 306 307 page.truncateFiles(files); 308 logFile.close(); 309 (new File(BtreeDatabase.getFileName(baseName, BtreeDatabase.LFL))).delete(); 310 } 311 } 312 finally { 313 if (logFile != null) { 314 logFile.close(); 315 316 } 317 } 318 } 319 catch (IOException ex) { 320 throw new StorageIOException(ex); 321 } 322 } 323 } 324 325 326 | Popular Tags |