1 23 24 28 50 package com.sun.jts.CosTransactions; 51 52 54 import java.util.*; 55 import java.io.*; 56 57 65 72 class LogHandle { 73 74 77 79 final static int BUFFER = 0; 80 81 84 final static int FORCE = 1; 85 86 88 90 final static int TAIL_NOT_INCLUSIVE = 0; 91 92 94 final static int TAIL_INCLUSIVE = 1; 95 96 98 100 final static int START_CKPT = 0; 101 102 104 final static int INDV_CKPT = 1; 105 106 108 final static int END_CKPT = 2; 109 110 112 final static int NEW_JRNL = 3; 113 114 116 final static int RECORD_TYPE_MAX = 0xFFFF; 117 118 121 final static int MARKER = RECORD_TYPE_MAX; 122 123 126 final static int LINK = RECORD_TYPE_MAX + 1; 127 128 130 132 final static int MAX_NUMBER_EXTENTS = 0xFFFFFFFF; 133 134 137 final static int CONTROL_FORCE_INTERVAL = 100; 139 140 142 final static int MAX_EXTENT_SIZE = LogFileHandle.FILESYSTEM_BLOCKSIZE*16; 143 144 147 final static int CUSHION_SIZE = MAX_EXTENT_SIZE; 148 149 152 final static int NAME_LENGTH = 8; 153 154 158 final static int MAX_NAMES = 4096; 159 160 163 final static int FILENAME_PREFIX_LEN = 5; 164 165 168 final static int EXTENT_TABLE_SIZE = 16; 169 170 177 179 181 final static int CALLBACK_REASON_SOS = 1; 182 183 185 final static int RESTART_OFFSET_1 = LogFileHandle.FILESYSTEM_BLOCKSIZE; 186 187 189 final static int RESTART_OFFSET_2 = LogFileHandle.FILESYSTEM_BLOCKSIZE*5; 190 191 193 final static int MAX_RECORD_SIZE = MAX_EXTENT_SIZE - 2*LogRecordHeader.SIZEOF - 2*LogRecordEnding.SIZEOF; 194 195 197 final static int MAX_RESTART_SIZE = LogFileHandle.FILESYSTEM_BLOCKSIZE*4 - 2*LogRestartDescriptor.SIZEOF; 198 199 201 final static int CONTROL_FILE_SIZE = RESTART_OFFSET_2 + MAX_RESTART_SIZE + 2*LogRestartDescriptor.SIZEOF; 202 203 205 final static int ALLOCATE_SIZE = MAX_EXTENT_SIZE; 206 207 209 LogHandle blockValid = null; 210 int restartDataLength = 0; 211 int recordsWritten = 0; 212 int chunkRemaining = 0; 213 int activeRestartVersion = 0; 214 LogUpcallTarget upcallTarget = null; 215 ArrayList cursors = null; 216 boolean cushionExists = false; 217 boolean upcallInProgress = false; 218 Hashtable extentTable = null; 219 String logFileName = null; 220 LogFileHandle logFileHandle = null; 221 LogControlDescriptor logControlDescriptor = null; 222 LogControl logControl = null; 223 224 225 238 LogHandle( LogControl control, 239 String logName, 240 LogFileHandle controlFH, 241 LogUpcallTarget upcall ) 242 throws LogException { 243 244 246 logFileName = new String (logName); 247 upcallTarget = upcall; 248 logControl = control; 249 logFileHandle = controlFH; 250 blockValid = this; 251 logControlDescriptor = new LogControlDescriptor(); 252 cursors = new ArrayList(); 253 extentTable = new Hashtable(EXTENT_TABLE_SIZE); 254 255 } 256 257 269 synchronized LogLSN writeRecord( byte[] record, 270 int recordType, 271 int writeMode ) 272 throws LogException { 273 274 279 if( blockValid != this ) 280 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 281 282 285 if( !logControl.logInitialised ) 286 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 287 288 291 if( logControl.logReadOnly ) 292 throw new LogException(null,LogException.LOG_READ_ONLY_ACCESS,3); 293 294 296 if( recordType > RECORD_TYPE_MAX ) 297 throw new LogException(null,LogException.LOG_INVALID_RECORDTYPE,5); 298 299 if( writeMode != FORCE && writeMode != BUFFER ) 300 throw new LogException(null,LogException.LOG_INVALID_WRITEMODE,6); 301 302 305 int recordSize = record.length + LogRecordHeader.SIZEOF + LogRecordEnding.SIZEOF; 306 307 308 312 if( recordSize > MAX_RECORD_SIZE ) 313 throw new LogException(null,LogException.LOG_RECORD_TOO_LARGE,7); 314 315 319 int remainingSpace = MAX_EXTENT_SIZE - ( logControlDescriptor.nextLSN.offset 320 + 2*LogRecordHeader.SIZEOF 321 + LogRecordEnding.SIZEOF ); 322 323 324 330 LogExtent logEDP = positionFilePointer(logControlDescriptor.nextLSN,0,LogExtent.ACCESSTYPE_WRITE); 331 332 334 if( remainingSpace < recordSize ) { 335 LogRecordHeader link = new LogRecordHeader(); 336 337 342 int nextExtent = logControlDescriptor.headLSN.extent+1; 343 if( nextExtent < 0 ) 344 throw new LogException(null,LogException.LOG_WRITE_FAILURE,8); 345 346 350 if( extentTable.containsKey(new Integer (LogExtent.modExtent(nextExtent))) ) 351 throw new LogException(null,LogException.LOG_WRITE_FAILURE,9); 352 353 360 link.recordType = LINK; 361 link.previousLSN = new LogLSN(logControlDescriptor.headLSN); 362 link.currentLSN = new LogLSN(logControlDescriptor.nextLSN); 363 link.nextLSN = new LogLSN(nextExtent,0); 364 365 367 LogExtent nextEDP = positionFilePointer(link.nextLSN,0,LogExtent.ACCESSTYPE_WRITE); 368 369 377 byte[] linkBytes = new byte[link.SIZEOF]; 378 link.toBytes(linkBytes,0); 379 int bytesWritten = 0; 380 try { 381 bytesWritten = logEDP.fileHandle.fileWrite(linkBytes); 382 } catch( LogException le ) { 383 extentTable.remove(new Integer (logControlDescriptor.headLSN.extent)); 384 nextEDP.finalize(); 385 throw new LogException(null,LogException.LOG_WRITE_FAILURE,10); 386 } 387 388 390 logEDP.writtenSinceLastForce = true; 391 logEDP.cursorPosition += bytesWritten; 392 393 398 logControlDescriptor.headLSN.copy(link.currentLSN); 399 logControlDescriptor.nextLSN.copy(link.nextLSN); 400 401 403 logEDP = nextEDP; 404 405 407 chunkRemaining = 0; 408 } 409 410 414 LogLSN nextFree = new LogLSN(logControlDescriptor.nextLSN.extent, 415 logControlDescriptor.nextLSN.offset + recordSize); 416 417 425 LogRecordHeader logRH = new LogRecordHeader(); 426 427 logRH.recordType = recordType; 428 logRH.recordLength = record.length; 429 logRH.nextLSN = nextFree; 430 logRH.previousLSN = new LogLSN(logControlDescriptor.headLSN); 431 logRH.currentLSN = new LogLSN(logControlDescriptor.nextLSN); 432 433 436 LogRecordEnding logRE = new LogRecordEnding(); 437 438 logRE.currentLSN = logRH.currentLSN; 439 440 441 451 byte[] writeBytes = new byte[LogRecordHeader.SIZEOF+record.length+LogRecordEnding.SIZEOF]; 452 453 logRH.toBytes(writeBytes,0); 454 System.arraycopy(record,0,writeBytes,LogRecordHeader.SIZEOF,record.length); 455 logRE.toBytes(writeBytes,LogRecordHeader.SIZEOF+record.length); 456 457 460 boolean cushionFreed = false; 461 462 if( chunkRemaining > recordSize ) 463 chunkRemaining -= recordSize; 464 else { 465 466 468 int grabSize = chunkRemaining + ALLOCATE_SIZE; 469 470 473 if( grabSize + logControlDescriptor.nextLSN.offset > MAX_EXTENT_SIZE ) 474 grabSize = MAX_EXTENT_SIZE - logControlDescriptor.nextLSN.offset; 475 476 477 479 boolean allocateSuccess = false; 480 481 do { 482 487 try { 488 logEDP.fileHandle.allocFileStorage(grabSize); 489 } catch( LogException le ) { 490 491 502 if( le.errorCode == LogException.LOG_NO_SPACE ) { 503 if( cushionExists ) { 504 freeCushion(); 505 cushionFreed = true; 506 } else { 507 if( cushionFreed ) 508 restoreCushion(false); 509 510 throw new LogException(null,LogException.LOG_NO_SPACE,11); 511 } 512 513 try { 514 logEDP = positionFilePointer(logControlDescriptor.nextLSN,0,LogExtent.ACCESSTYPE_WRITE); 515 } catch( Throwable e ) {}; 516 } 517 else 518 allocateSuccess = false; 519 } 520 allocateSuccess = true; 521 } 522 while( !allocateSuccess ); 523 524 528 if( !allocateSuccess ) 529 throw new LogException(null,LogException.LOG_WRITE_FAILURE,12); 530 531 533 chunkRemaining = grabSize - recordSize; 534 } 535 536 540 int bytesWritten = logEDP.fileHandle.fileWrite(writeBytes); 541 542 544 logEDP.writtenSinceLastForce = true; 545 logEDP.cursorPosition += bytesWritten; 546 547 557 if( writeMode == FORCE ) { 558 Enumeration extents = extentTable.elements(); 559 while( extents.hasMoreElements() ) { 560 LogExtent nextEDP = (LogExtent)extents.nextElement(); 561 if( nextEDP.writtenSinceLastForce ) 562 try { 563 nextEDP.fileHandle.fileSync(); 564 nextEDP.writtenSinceLastForce = false; 565 } catch( LogException le ) { 566 throw new LogException(null,LogException.LOG_ERROR_FORCING_LOG,14); 567 } 568 } 569 } 570 571 574 logControlDescriptor.headLSN.copy(logRH.currentLSN); 575 logControlDescriptor.nextLSN.copy(logRH.nextLSN); 576 577 579 recordsWritten++; 580 581 589 if( recordsWritten >= CONTROL_FORCE_INTERVAL ) { 590 writeControlFile(); 591 recordsWritten = 0; 592 } 593 594 if( cushionFreed ) 595 restoreCushion(true); 596 597 599 LogLSN result = new LogLSN(logRH.currentLSN); 600 601 602 return result; 603 } 604 605 617 synchronized byte[] readRecord( LogLSN readLSN, 618 int[] type ) 619 throws LogException { 620 621 626 if( blockValid != this ) 627 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 628 629 632 if( !logControl.logInitialised ) 633 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 634 635 639 if( logControlDescriptor.headLSN.isNULL() ) 640 throw new LogException(null,LogException.LOG_INVALID_LSN,3); 641 642 652 LogLSN lsn; 653 654 if( readLSN.equals(LogLSN.HEAD_LSN) ) 655 lsn = logControlDescriptor.headLSN; 656 else if( readLSN.equals(LogLSN.TAIL_LSN) ) 657 lsn = logControlDescriptor.tailLSN; 658 else if( readLSN.lessThan(logControlDescriptor.tailLSN) || 659 readLSN.greaterThan(logControlDescriptor.headLSN) ) 660 throw new LogException(null,LogException.LOG_INVALID_LSN,4); 661 else 662 lsn = readLSN; 663 664 667 LogExtent logEDP = positionFilePointer(lsn,0,LogExtent.ACCESSTYPE_READ); 668 669 674 byte[] headerBytes = new byte[LogRecordHeader.SIZEOF]; 675 int bytesRead = 0; 676 try { 677 bytesRead = logEDP.fileHandle.fileRead(headerBytes); 678 } catch( LogException le ) { 679 logEDP.lastAccess = LogExtent.ACCESSTYPE_UNKNOWN; 680 throw new LogException(null,le.errorCode,6); 681 } 682 683 LogRecordHeader logRH = new LogRecordHeader(headerBytes,0); 684 685 logEDP.cursorPosition += bytesRead; 686 687 693 if( logRH.recordType == LINK || 694 !logRH.currentLSN.equals(lsn) ) 695 throw new LogException(null,LogException.LOG_INVALID_LSN,7); 696 697 705 byte[][] readVect = new byte[2][]; 706 readVect[0] = new byte[logRH.recordLength]; 707 readVect[1] = new byte[LogRecordEnding.SIZEOF]; 708 709 try { 710 bytesRead = logEDP.fileHandle.readVector(readVect); 711 } catch( LogException le ) { 712 logEDP.lastAccess = LogExtent.ACCESSTYPE_UNKNOWN; 713 throw new LogException(null,le.errorCode,9); 714 } 715 716 LogRecordEnding logRE = new LogRecordEnding(readVect[1],0); 717 logEDP.cursorPosition += bytesRead; 718 719 723 if( !logRE.currentLSN.equals(lsn) ) 724 throw new LogException(null,LogException.LOG_CORRUPTED,10); 725 726 729 type[0] = logRH.recordType; 730 731 return readVect[0]; 732 } 733 734 744 synchronized void writeRestart( byte[] buffer ) 745 throws LogException { 746 747 752 if( blockValid != this ) 753 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 754 755 758 if( !logControl.logInitialised ) 759 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 760 761 764 if( logControl.logReadOnly ) 765 throw new LogException(null,LogException.LOG_READ_ONLY_ACCESS,3); 766 767 770 if( buffer.length > MAX_RESTART_SIZE ) 771 throw new LogException(null,LogException.LOG_RECORD_TOO_LARGE,4); 772 773 776 if( blockValid != this ) 777 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,5); 778 779 783 int alternate = alternateRestart(activeRestartVersion); 784 int restartOffset = restartPosition(alternate); 785 logFileHandle.fileSeek(restartOffset,LogFileHandle.SEEK_ABSOLUTE); 786 787 792 LogRestartDescriptor logRD = new LogRestartDescriptor(); 793 794 logRD.restartDataLength = buffer.length; 795 logRD.timeStamp = (int)new Date().getTime(); 796 logRD.restartValid = restartOffset; 797 798 799 803 byte[] writeBytes = new byte[LogRestartDescriptor.SIZEOF*2+buffer.length]; 804 805 logRD.toBytes(writeBytes,0); 806 System.arraycopy(buffer,0,writeBytes,LogRestartDescriptor.SIZEOF,buffer.length); 807 logRD.toBytes(writeBytes,LogRestartDescriptor.SIZEOF+buffer.length); 808 809 818 int bytesWritten = logFileHandle.fileWrite(writeBytes); 819 820 activeRestartVersion = alternate; 821 822 } 823 824 834 synchronized byte[] readRestart() 835 throws LogException { 836 841 if( blockValid != this ) 842 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 843 844 847 if( !logControl.logInitialised ) 848 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 849 850 853 if( blockValid != this ) 854 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,3); 855 856 860 if( restartDataLength == 0 ) 861 return new byte[0]; 862 863 869 int restartOffset = restartPosition(activeRestartVersion); 870 logFileHandle.fileSeek(restartOffset,LogFileHandle.SEEK_ABSOLUTE); 871 872 877 byte[][] readVect = new byte[3][]; 878 879 readVect[0] = new byte[LogRestartDescriptor.SIZEOF]; 880 readVect[1] = new byte[restartDataLength]; 881 readVect[2] = new byte[LogRestartDescriptor.SIZEOF]; 882 883 886 int bytesRead = logFileHandle.readVector(readVect); 887 888 LogRestartDescriptor logRD = new LogRestartDescriptor(readVect[0],0); 889 LogRestartDescriptor logRDEnd = new LogRestartDescriptor(readVect[2],0); 890 891 898 if( logRD.restartValid != restartOffset || 899 logRD.restartDataLength != restartDataLength || 900 !logRD.equals(logRDEnd) ) 901 throw new LogException(null,LogException.LOG_CORRUPTED,7); 902 903 907 return readVect[1]; 908 } 909 910 920 synchronized void closeFile( boolean deleteFile ) throws LogException { 921 926 if( blockValid != this ) 927 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 928 929 932 if( !logControl.logInitialised ) 933 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 934 935 937 blockValid = null; 938 939 941 boolean forced = false; 942 Enumeration extents = extentTable.elements(); 943 while( extents.hasMoreElements() ) { 944 LogExtent logEDP = (LogExtent)extents.nextElement(); 945 946 947 952 if( logEDP.writtenSinceLastForce ) { 953 logEDP.fileHandle.fileSync(); 954 logEDP.writtenSinceLastForce = false; 955 forced = true; 956 } 957 958 961 logEDP.fileHandle.fileClose(); 962 963 if( deleteFile ){ 966 final LogExtent tmplogEDP = logEDP; 968 Boolean isdeleted = (Boolean ) java.security.AccessController.doPrivileged( 969 new java.security.PrivilegedAction () { 970 public Object run(){ 971 return new Boolean (tmplogEDP.file.delete()); 972 } 973 } 974 ); 975 if(!isdeleted.booleanValue()) 976 throw new LogException(null,LogException.LOG_CLOSE_FAILURE,6); 977 978 } 979 984 extentTable.remove(new Integer (logEDP.extentNumber)); 985 logEDP.finalize(); 986 } 987 988 994 if( forced && !logControl.logReadOnly ) 995 writeControlFile(); 996 997 1000 logFileHandle.fileClose(); 1001 logFileHandle.finalize(); 1002 1003 1006 if( deleteFile ) { 1007 1008 Boolean isdeleted = (Boolean ) java.security.AccessController.doPrivileged( 1012 new java.security.PrivilegedAction () { 1013 public Object run(){ 1014 return new Boolean (logControl.controlFile.delete()); 1015 } 1016 } 1017 ); 1018 if( !isdeleted.booleanValue() ) 1019 throw new LogException(null,LogException.LOG_CLOSE_FAILURE,7); 1020 freeCushion(); 1022 1023 java.security.AccessController.doPrivileged( 1027 new java.security.PrivilegedAction () { 1028 public Object run(){ 1029 LogControl.directory(logFileName,logControl.directoryPath).delete(); 1030 return null; 1031 } 1032 } 1033 ); 1034 } 1036 1037 1040 logControl.removeFile(this); 1041 1042 } 1043 1044 1055 synchronized void truncate( LogLSN truncLSN, 1056 int inclusive ) 1057 throws LogException { 1058 1059 1064 if( blockValid != this ) 1065 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 1066 1067 1070 if( !logControl.logInitialised ) 1071 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 1072 1073 1076 if( logControl.logReadOnly ) 1077 throw new LogException(null,LogException.LOG_READ_ONLY_ACCESS,3); 1078 1079 1084 if( logControlDescriptor.headLSN.isNULL() ) { 1085 if( truncLSN.equals(LogLSN.HEAD_LSN) ) { 1086 return; 1087 } else 1088 throw new LogException(null,LogException.LOG_NEW_TAIL_TOO_HIGH,6); 1089 } 1090 1091 1099 LogLSN lsn; 1100 boolean truncateHead = false; 1101 1102 if( truncLSN.equals(LogLSN.HEAD_LSN) || 1103 truncLSN.equals(logControlDescriptor.headLSN) ) { 1104 lsn = new LogLSN(logControlDescriptor.headLSN); 1105 truncateHead = true; 1106 } else if( truncLSN.equals(LogLSN.TAIL_LSN) ) 1107 lsn = new LogLSN(logControlDescriptor.tailLSN); 1108 else 1109 lsn = new LogLSN(truncLSN); 1110 1111 1120 if( lsn.lessThan(logControlDescriptor.tailLSN) ) 1121 throw new LogException(null,LogException.LOG_NEW_TAIL_TOO_LOW,7); 1122 else if( lsn.greaterThan(logControlDescriptor.headLSN) ) 1123 throw new LogException(null,LogException.LOG_NEW_TAIL_TOO_HIGH,8); 1124 1125 1134 LogLSN truncationRecord; 1135 LogLSN newTailRecord; 1136 boolean truncLastExtent = false; 1137 1138 if( truncateHead && 1139 inclusive == TAIL_NOT_INCLUSIVE ) { 1140 truncationRecord = new LogLSN(lsn); 1141 newTailRecord = new LogLSN(logControlDescriptor.nextLSN); 1142 } else { 1143 1144 1150 if( inclusive == TAIL_INCLUSIVE && 1151 lsn.equals(logControlDescriptor.tailLSN) ) { 1152 return; 1153 } 1154 1155 1159 LogExtent logEDP = positionFilePointer(lsn,0,LogExtent.ACCESSTYPE_READ); 1160 1161 1164 byte[] headerBytes = new byte[LogRecordHeader.SIZEOF]; 1165 int bytesRead = 0; 1166 1167 try { 1168 bytesRead = logEDP.fileHandle.fileRead(headerBytes); 1169 } catch( LogException le ) { 1170 logEDP.lastAccess = LogExtent.ACCESSTYPE_UNKNOWN; 1171 throw new LogException(null,LogException.LOG_READ_FAILURE,11); 1172 } 1173 1174 logEDP.cursorPosition += bytesRead; 1175 LogRecordHeader recordHeader = new LogRecordHeader(headerBytes,0); 1176 1177 1182 if( recordHeader.recordType == LINK ) 1183 throw new LogException(null,LogException.LOG_INVALID_TAIL,12); 1184 1185 1188 if( inclusive == TAIL_INCLUSIVE ) { 1189 1193 truncationRecord = new LogLSN(recordHeader.previousLSN); 1194 newTailRecord = new LogLSN(lsn); 1195 1196 1199 if( lsn.offset == 0 ) 1200 truncLastExtent = true; 1201 } else { 1202 1203 1207 truncationRecord = new LogLSN(lsn); 1208 newTailRecord = new LogLSN(recordHeader.nextLSN); 1209 } 1210 } 1211 1212 1217 int firstExtent = logControlDescriptor.tailLSN.extent; 1218 int lastExtent = truncationRecord.extent; 1219 1220 1228 if( truncateHead && 1229 inclusive == TAIL_NOT_INCLUSIVE ) { 1230 logControlDescriptor.tailLSN.copy(newTailRecord); 1231 logControlDescriptor.headLSN.copy(LogLSN.NULL_LSN); 1232 } else 1233 logControlDescriptor.tailLSN.copy(newTailRecord); 1234 1235 1238 writeControlFile(); 1239 1240 1246 if( truncLastExtent ) 1247 lastExtent++; 1248 1249 for( int extent = firstExtent; extent <= lastExtent-1; extent++ ) { 1250 1251 1255 LogExtent logEDP = (LogExtent)extentTable.get(new Integer (extent)); 1256 if( logEDP != null ) 1257 logEDP.fileHandle.fileClose(); 1258 1259 1263 final LogExtent tmplogEDP = logEDP; 1266 Boolean isdeleted = (Boolean ) java.security.AccessController.doPrivileged( 1267 new java.security.PrivilegedAction () { 1268 public Object run(){ 1269 return new Boolean (tmplogEDP.file.delete()); 1270 } 1271 } 1272 ); 1273 if(!isdeleted.booleanValue()) 1274 throw new LogException(null,LogException.LOG_CLOSE_FAILURE,15); 1275 1279 extentTable.remove(new Integer (extent)); 1280 logEDP.finalize(); 1281 } 1282 1283 1290 if( !cushionExists && 1291 firstExtent <= lastExtent - 1 ) 1292 restoreCushion(false); 1293 1294 1298 if( logControlDescriptor.tailLSN.offset > 0 ) 1299 freeFileStorage(logControlDescriptor.tailLSN); 1300 1301 1308 if( logControlDescriptor.headLSN.isNULL() ) 1309 recordsWritten = CONTROL_FORCE_INTERVAL; 1310 1311 } 1312 1313 1323 synchronized void checkLSN( LogLSN chkLSN ) 1324 throws LogException { 1325 1326 1331 if( blockValid != this ) 1332 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 1333 1334 1337 if( !logControl.logInitialised ) 1338 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 1339 1340 1343 if( logControl.logReadOnly ) 1344 throw new LogException(null,LogException.LOG_READ_ONLY_ACCESS,3); 1345 1346 1352 LogLSN lsn; 1353 1354 if( chkLSN.equals(LogLSN.HEAD_LSN) ) 1355 lsn = new LogLSN(logControlDescriptor.headLSN); 1356 else if( chkLSN.equals(LogLSN.TAIL_LSN) ) 1357 lsn = new LogLSN(logControlDescriptor.tailLSN); 1358 else 1359 lsn = new LogLSN(chkLSN); 1360 1361 1364 if( lsn.lessThan(logControlDescriptor.tailLSN) ) { 1365 return; 1366 } 1367 1368 1372 if( logControlDescriptor.headLSN.isNULL() ) { 1373 return; 1374 } 1375 1376 1379 if( lsn.greaterThan(logControlDescriptor.headLSN) ) 1380 lsn.copy(logControlDescriptor.headLSN); 1381 1382 1386 int lastExtent = lsn.extent; 1387 1388 1391 int firstExtent = logControlDescriptor.tailLSN.extent; 1392 1393 1396 for( int extent = firstExtent; extent <= lastExtent; extent++ ) { 1397 1398 1405 LogExtent logEDP = (LogExtent)extentTable.get(new Integer (extent)); 1406 if( logEDP != null && 1407 logEDP.writtenSinceLastForce ) { 1408 logEDP.fileHandle.fileSync(); 1409 logEDP.writtenSinceLastForce = false; 1410 } 1411 } 1412 1413 1424 1428 1429 } 1430 1431 1442 synchronized LogCursor openCursor( LogLSN startLSN, 1443 LogLSN endLSN ) 1444 throws LogException { 1445 1446 1451 if( blockValid != this ) 1452 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 1453 1454 1457 if( !logControl.logInitialised ) 1458 throw new LogException(null,LogException.LOG_NOT_INITIALISED,2); 1459 1460 1464 LogCursor cursor = new LogCursor(logControl,this,startLSN,endLSN); 1465 if( cursor == null ) { 1466 throw new LogException(null,LogException.LOG_INSUFFICIENT_MEMORY,4); 1467 } 1468 1469 1470 1473 cursors.add(cursor); 1474 1475 return cursor; 1476 } 1477 1478 1488 synchronized void closeCursor( LogCursor cursor ) 1489 throws LogException { 1490 1491 1496 if( cursor == null || cursor.blockValid != cursor ) 1497 throw new LogException(null,LogException.LOG_INVALID_CURSOR,1); 1498 1499 1502 if( blockValid != this ) 1503 throw new LogException(null,LogException.LOG_INVALID_CURSOR,2); 1504 1505 1508 if( !logControl.logInitialised ) 1509 throw new LogException(null,LogException.LOG_NOT_INITIALISED,3); 1510 1511 1515 cursors.remove(cursor); 1516 1517 1519 cursor.finalize(); 1520 1521 } 1522 1523 1536 LogExtent positionFilePointer( LogLSN currentLSN, 1537 int extra, 1538 int accessType ) 1539 throws LogException { 1540 1541 boolean extentJustOpened = false; 1543 1545 LogExtent extent = (LogExtent)extentTable.get(new Integer (currentLSN.extent)); 1546 1547 1549 if( extent == null ) { 1550 1551 1553 extent = openExtent(currentLSN.extent); 1554 extentJustOpened = true; 1555 } 1556 1557 1560 if( extent.cursorPosition != currentLSN.offset + extra || 1561 extent.lastAccess != accessType ) { 1562 1563 1570 int seekDist = ((currentLSN.offset + extra) > extent.cursorPosition) ? 1571 (currentLSN.offset + extra - extent.cursorPosition) : 1572 (extent.cursorPosition - currentLSN.offset - extra); 1573 1574 try { 1575 if( extent.lastAccess == LogExtent.ACCESSTYPE_UNKNOWN || 1576 currentLSN.offset + extra < seekDist ) 1577 extent.fileHandle.fileSeek(currentLSN.offset+extra,LogFileHandle.SEEK_ABSOLUTE); 1578 else 1579 extent.fileHandle.fileSeek(currentLSN.offset+extra-extent.cursorPosition,LogFileHandle.SEEK_RELATIVE); 1580 } catch( LogException le ) { 1581 if( extentJustOpened ) { 1582 extentTable.remove(new Integer (currentLSN.extent)); 1583 extent.finalize(); 1584 } 1585 1586 throw new LogException(null,LogException.LOG_READ_FAILURE,3); 1587 } 1588 1589 extent.cursorPosition = currentLSN.offset + extra; 1590 extent.lastAccess = accessType; 1591 } 1592 1593 1595 1596 return extent; 1597 } 1598 1599 1609 private void freeCushion() { 1610 1612 if( cushionExists ) { 1613 1614 java.security.AccessController.doPrivileged( 1618 new java.security.PrivilegedAction () { 1619 public Object run(){ 1620 logControl.cushionFile.delete(); 1621 return null; 1622 } 1623 } 1624 ); 1625 cushionExists = false; 1627 } 1628 1629 } 1630 1631 1643 void restoreCushion( boolean callUpcall ) 1644 throws LogException { 1645 1646 1648 if( CUSHION_SIZE > 0 ) { 1649 1650 1653 if( !logControl.cushionFile.exists() ) { 1654 LogFileHandle cushionFH; int openOptions = LogFileHandle.OPEN_RDWR | 1656 LogFileHandle.OPEN_CREAT | 1657 LogFileHandle.OPEN_SYNC; 1658 1659 1667 try { 1668 cushionFH = new LogFileHandle(logControl.cushionFile,openOptions); 1669 } catch( LogException le ) { 1670 if( callUpcall && !upcallInProgress ) { 1671 upcallInProgress = true; 1672 upcallTarget.upcall(CALLBACK_REASON_SOS); 1673 upcallInProgress = false; 1674 } 1675 throw new LogException(null,LogException.LOG_OPEN_FAILURE,3); 1676 } 1677 1678 1687 try { 1688 cushionFH.allocFileStorage(CUSHION_SIZE); 1689 } catch( LogException le ) { 1690 cushionFH.finalize(); 1691 java.security.AccessController.doPrivileged( 1694 new java.security.PrivilegedAction () { 1695 public Object run(){ 1696 logControl.cushionFile.delete(); 1697 return null; 1698 } 1699 } 1700 ); 1701 1703 if( callUpcall && !upcallInProgress ) { 1704 upcallInProgress = true; 1705 upcallTarget.upcall(CALLBACK_REASON_SOS); 1706 upcallInProgress = false; 1707 } 1708 cushionExists = false; 1709 throw new LogException(null,LogException.LOG_OPEN_FAILURE,4); 1710 } 1711 1712 1714 cushionFH.finalize(); 1715 } 1716 1717 cushionExists = true; 1718 } 1719 1720 } 1721 1722 1733 void writeControlFile() throws LogException { 1734 1735 Enumeration extents = extentTable.elements(); 1747 while (extents.hasMoreElements()) { 1748 LogExtent nextEDP = (LogExtent) extents.nextElement(); 1749 if (nextEDP.writtenSinceLastForce) { 1750 try { 1751 nextEDP.fileHandle.fileSync(); 1752 nextEDP.writtenSinceLastForce = false; 1753 } catch (LogException le) { 1754 throw new LogException(null, 1755 LogException.LOG_ERROR_FORCING_LOG, 1756 14); 1757 } 1758 } 1759 } 1760 1761 1763 logFileHandle.fileSeek(0,LogFileHandle.SEEK_ABSOLUTE); 1764 1765 1767 byte[] controlBytes = new byte[LogControlDescriptor.SIZEOF]; 1768 logControlDescriptor.toBytes(controlBytes,0); 1769 int bytesWritten = logFileHandle.fileWrite(controlBytes); 1770 1771 } 1772 1773 1785 LogExtent openExtent( int extent ) throws LogException { 1786 1787 1789 File extentFile = logControl.extentFile(logFileName,LogExtent.modExtent(extent)); 1790 1791 1795 int openOptions = LogFileHandle.OPEN_RDWR | LogFileHandle.OPEN_CREAT; 1796 if( logControl.logReadOnly ) 1797 openOptions = LogFileHandle.OPEN_RDONLY; 1798 1799 LogFileHandle extentFH = new LogFileHandle(extentFile,openOptions); 1800 1801 1803 LogExtent logEDP = new LogExtent(extent,extentFH,extentFile); 1804 if( logEDP == null ) { 1805 extentFH.finalize(); 1806 throw new LogException(null,LogException.LOG_INSUFFICIENT_MEMORY,2); 1807 } 1808 1809 1812 extentTable.put(new Integer (extent),logEDP); 1813 logEDP.blockValid = logEDP; 1814 1815 return logEDP; 1816 } 1817 1818 1829 void freeFileStorage( LogLSN tailLSN ) 1830 throws LogException { 1831 1832 1839 int bytesToClear = tailLSN.offset; 1840 if( bytesToClear == 0 ) { 1841 return; 1842 } 1843 1844 1847 LogLSN startOfExtent = new LogLSN(tailLSN.extent,0); 1848 LogExtent logEDP = positionFilePointer(startOfExtent,0,LogExtent.ACCESSTYPE_UNKNOWN); 1849 1850 1852 logEDP.fileHandle.fileSync(); 1853 1854 } 1855 1856 1869 static void checkRestart( LogFileHandle fileHandle, 1870 int restartNumber, 1871 int[] restartInfo ) 1872 throws LogException { 1873 1874 1876 restartInfo[0] = 0; restartInfo[1] = 0; 1879 1883 byte[] restartBytes = new byte[LogRestartDescriptor.SIZEOF]; 1884 1885 int offset = restartPosition(restartNumber); 1886 fileHandle.fileSeek(offset,LogFileHandle.SEEK_ABSOLUTE); 1887 int bytesRead = fileHandle.fileRead(restartBytes); 1888 LogRestartDescriptor logRD = new LogRestartDescriptor(restartBytes,0); 1889 1890 1892 if( bytesRead > 0 ) { 1893 1894 1900 if( logRD.restartValid == restartPosition(restartNumber) ) { 1901 fileHandle.fileSeek(logRD.restartDataLength, 1902 LogFileHandle.SEEK_RELATIVE); 1903 bytesRead = fileHandle.fileRead(restartBytes); 1904 LogRestartDescriptor logRDEnd = new LogRestartDescriptor(restartBytes,0); 1905 1906 1907 1912 if( logRD.equals(logRDEnd) ) { 1913 restartInfo[0] = logRD.restartDataLength; 1914 restartInfo[1] = logRD.timeStamp; 1915 } 1916 else 1917 throw new LogException(null,LogException.LOG_CORRUPTED,1); 1918 } 1919 } 1920 1921 } 1922 1923 1933 void dump() throws LogException { 1934 LogExtent logEDP; LogCursor logCuDP; 1937 1942 if( blockValid != this ) 1943 throw new LogException(null,LogException.LOG_INVALID_FILE_DESCRIPTOR,1); 1944 1945 1947 Enumeration extents = extentTable.elements(); 1948 while( extents.hasMoreElements() ) { 1949 logEDP = (LogExtent)extents.nextElement(); 1950 } 1951 1952 java.util.Iterator curs = cursors.iterator(); 1953 while( curs.hasNext() ) { 1954 logCuDP = (LogCursor)curs.next(); 1955 } 1956 1957 } 1958 1959 1968 void cleanUpExtents() { 1969 1970 Enumeration extents = extentTable.elements(); 1971 while( extents.hasMoreElements() ) { 1972 LogExtent logEDP = (LogExtent)extents.nextElement(); 1973 extentTable.remove(new Integer (logEDP.extentNumber)); 1974 logEDP.finalize(); 1975 } 1976 extentTable = null; 1977 1978 } 1979 1980 1988 1989 final static int alternateRestart( int restart) { 1990 return (restart == 1) ? 2 : 1; 1991 } 1992 1993 2001 final static int restartPosition( int restart ) { 2002 return (restart == 1) ? RESTART_OFFSET_1 : RESTART_OFFSET_2; 2003 } 2004 2005 2013 final String logFileName() { 2014 return logFileName; 2015 } 2016} 2017 | Popular Tags |