1 19 package org.netbeans.mdr.persistence.btreeimpl.btreestorage; 20 21 import java.io.*; 22 import java.text.*; 23 24 import org.netbeans.mdr.persistence.*; 25 26 28 class MapPage { 29 30 31 private int pageSize; 32 33 34 private int myOffset; 35 36 37 private short numFiles; 38 39 40 private short maxPages; 41 42 43 private long fileId; 44 private long timeStamp; 45 private long newTimeStamp; 46 47 48 private short pageCount; 49 50 51 private short checksum; 52 53 private static final int FIXED_SIZE = 40; 54 55 56 private int oldEOF[]; 57 58 59 private int offsets[]; 60 61 66 MapPage(int pgSz, int noFiles, int offset) { 67 myOffset = offset; 68 pageSize = pgSz; 69 numFiles = (short)noFiles; 70 oldEOF = new int[numFiles]; 71 maxPages = (short)((pageSize - FIXED_SIZE - (4 * numFiles)) / 4); 72 offsets = new int[maxPages]; 73 } 74 75 76 80 void setEOFs(RandomAccessFile files[] ) throws StorageException { 81 try { 82 for (int i = 0; i < numFiles; i++) { 83 oldEOF[i] = (int)files[i].length(); 84 } 85 } 86 catch (IOException ex) { 87 throw new StorageIOException(ex); 88 } 89 } 90 91 93 int getEOF(int index) { 94 return oldEOF[index]; 95 } 96 97 100 MapPage(MapPage previous) { 101 this(previous.pageSize, previous.numFiles, 102 previous.myOffset + ((previous.pageCount + 1) * previous.pageSize)); 103 setTimeStamps(previous.timeStamp, previous.newTimeStamp); 104 oldEOF = new int[previous.oldEOF.length]; 105 System.arraycopy(previous.oldEOF, 0, oldEOF, 0, oldEOF.length); 106 } 107 108 111 void setFileID(long id) { 112 fileId = id; 113 } 114 115 119 void setTimeStamps(long stamp, long newStamp) { 120 timeStamp = stamp; 121 newTimeStamp = newStamp; 122 } 123 124 128 void write(RandomAccessFile file) throws StorageException { 129 130 byte buffer[] = new byte[pageSize]; 131 IntHolder offset = new IntHolder(0); 132 checksum = computeChecksum(); 133 Converter.writeInt(buffer, offset, pageSize); 134 Converter.writeInt(buffer, offset, myOffset); 135 Converter.writeShort(buffer, offset, numFiles); 136 Converter.writeShort(buffer, offset, maxPages); 137 Converter.writeShort(buffer, offset, pageCount); 138 Converter.writeShort(buffer, offset, checksum); 139 Converter.writeLong(buffer, offset, fileId); 140 Converter.writeLong(buffer, offset, timeStamp); 141 Converter.writeLong(buffer, offset, newTimeStamp); 142 143 for (int i = 0; i < numFiles; i++) 144 Converter.writeInt(buffer, offset, oldEOF[i]); 145 146 for (int i = 0; i < pageCount; i++) 147 Converter.writeInt(buffer, offset, offsets[i]); 148 149 try { 150 file.seek(myOffset); 151 file.write(buffer); 152 } 153 catch (IOException ex) { 154 throw new StorageIOException(ex); 155 } 156 } 157 158 159 165 MapPage(RandomAccessFile file, int offset, int pgSz) 166 throws StorageException { 167 168 byte buffer[] = new byte[pgSz]; 169 170 try { 171 file.seek(offset); 172 file.readFully(buffer); 173 } 174 catch (IOException ex) { 175 throw new StorageIOException(ex); 176 } 177 178 IntHolder index = new IntHolder(0); 179 pageSize = Converter.readInt(buffer, index); 180 if (pageSize == 0) { 181 return; 182 } 183 else if (pageSize != pgSz) { 184 throw new StoragePersistentDataException( 185 MessageFormat.format( 186 "Invalid page size {0}: {1} expected", 187 new Object [] { 188 new Integer (pgSz), 189 new Integer (pageSize)})); 190 } 191 myOffset = Converter.readInt(buffer, index); 192 numFiles = Converter.readShort(buffer, index); 193 maxPages = Converter.readShort(buffer, index); 194 pageCount = Converter.readShort(buffer, index); 195 checksum = Converter.readShort(buffer, index); 196 fileId = Converter.readLong(buffer, index); 197 timeStamp = Converter.readLong(buffer, index); 198 newTimeStamp = Converter.readLong(buffer, index); 199 200 oldEOF = new int[numFiles]; 201 offsets = new int[pageCount]; 202 203 for (int i = 0; i < numFiles; i++) 204 oldEOF[i] = Converter.readInt(buffer, index); 205 for (int i = 0; i < pageCount; i++) 206 offsets[i] = Converter.readInt(buffer, index); 207 208 if (checksum != computeChecksum()) 209 throw new StoragePersistentDataException( 210 "Invalid checksum in MapPage"); 211 } 212 213 214 boolean isEmpty() { 215 return pageSize == 0; 216 } 217 218 222 MapPage getNext(RandomAccessFile file, int numPages) 223 throws StorageException { 224 if (!isFull()) 225 return null; 226 227 int offset = myOffset + (pageSize * (pageCount + 1)); 228 if (offset >= (numPages * pageSize)) 229 return null; 230 231 return new MapPage(file, offset, pageSize); 232 } 233 234 238 void checkParameters(int thePageSize, int theNumberOfFiles) 239 throws StorageException { 240 if (thePageSize != pageSize) { 241 throw new StoragePersistentDataException( 242 "Map page contains wrong page size."); 243 } 244 245 if (theNumberOfFiles != numFiles) { 246 throw new StoragePersistentDataException( 247 "Map page contains wrong number of files."); 248 } 249 } 250 251 257 void checkFileHeader(RandomAccessFile file) 258 throws StorageException { 259 FileHeader header = new FileHeader(file); 260 261 if (header.timeStamp != timeStamp && 262 header.timeStamp != newTimeStamp) { 263 264 throw new StoragePersistentDataException( 265 "Map page contains invalid timestamp" + 266 + header.timeStamp + " valid would be " + 267 timeStamp + " or " + newTimeStamp); 268 } 269 270 if (header.fileId != fileId) { 271 throw new StoragePersistentDataException( 272 "Map page contains invalid file id"); 273 } 274 } 275 276 279 int nextPageOffset() { 280 return myOffset + (pageCount + 1) * pageSize; 281 } 282 283 286 void add(CachedPage page) { 287 offsets[pageCount++] = encode(page.key); 288 } 289 290 292 boolean isFull() { 293 return pageCount == maxPages; 294 } 295 296 297 private int encode(PageID page) { 298 return (page.fileIndex << 20) | (page.offset / pageSize); 299 } 300 301 302 private PageID decode(int pageID) { 303 return new PageID(pageID >>> 20, (pageID & 0XFFFFF) * pageSize); 304 } 305 306 307 short computeChecksum() { 308 int sum = 0; 309 310 sum += fileId; 311 sum += timeStamp; 312 sum += newTimeStamp; 313 sum += pageCount; 314 for (int i = 0; i < numFiles; i++) 315 sum += (oldEOF[i]); 316 for (int i = 0; i < pageCount; i++) 317 sum += offsets[i]; 318 319 return (short) ((sum & 0xFFFF) + (sum >>> 16)); 320 } 321 322 325 void truncateFiles(RandomAccessFile files[]) throws StorageException{ 326 try { 327 for (int i = 0; i < files.length; i++) { 328 files[i].setLength(oldEOF[i]); 329 } 330 } 331 catch (IOException ex) { 332 throw new StorageIOException(ex); 333 } 334 } 335 336 339 void recover(RandomAccessFile files[], RandomAccessFile logFile, 340 int numPages, byte buffer[]) throws StorageException { 341 try { 342 for (int i = 0; i < pageCount; i++) { 343 int logOffset = myOffset + (pageSize * (i + 1)); 344 if (logOffset >= (numPages * pageSize)) 345 break; 346 347 PageID entry = decode(offsets[i]); 348 files[entry.fileIndex].seek(entry.offset); 349 logFile.seek(logOffset); 350 logFile.readFully(buffer); 351 files[entry.fileIndex].write(buffer); 352 } 353 } 354 catch (IOException ex) { 355 throw new StorageIOException(ex); 356 } 357 } 358 } 359 | Popular Tags |