1 21 22 package org.apache.derby.impl.store.raw.data; 23 24 import org.apache.derby.iapi.reference.Property; 25 26 import org.apache.derby.iapi.reference.Limits; 27 import org.apache.derby.iapi.reference.SQLState; 28 29 import org.apache.derby.impl.store.raw.data.BaseContainer; 30 import org.apache.derby.impl.store.raw.data.BaseContainerHandle; 31 import org.apache.derby.impl.store.raw.data.BasePage; 32 import org.apache.derby.impl.store.raw.data.PageVersion; 33 34 import org.apache.derby.iapi.services.cache.Cacheable; 35 import org.apache.derby.iapi.services.cache.CacheManager; 36 import org.apache.derby.iapi.services.context.ContextService; 37 import org.apache.derby.iapi.services.daemon.DaemonService; 38 import org.apache.derby.iapi.services.daemon.Serviceable; 39 import org.apache.derby.iapi.services.monitor.Monitor; 40 import org.apache.derby.iapi.services.sanity.SanityManager; 41 import org.apache.derby.iapi.services.io.FormatIdUtil; 42 import org.apache.derby.iapi.services.io.FormatIdOutputStream; 43 import org.apache.derby.iapi.services.io.StoredFormatIds; 44 import org.apache.derby.iapi.services.io.TypedFormat; 45 46 import org.apache.derby.iapi.error.StandardException; 47 import org.apache.derby.iapi.store.raw.ContainerHandle; 48 import org.apache.derby.iapi.store.raw.ContainerKey; 49 import org.apache.derby.iapi.store.raw.LockingPolicy; 50 import org.apache.derby.iapi.store.raw.Loggable; 51 import org.apache.derby.iapi.store.raw.Page; 52 import org.apache.derby.iapi.store.raw.PageKey; 53 import org.apache.derby.iapi.store.raw.PageTimeStamp; 54 import org.apache.derby.iapi.store.raw.RecordHandle; 55 import org.apache.derby.iapi.store.raw.RawStoreFactory; 56 import org.apache.derby.iapi.store.raw.Transaction; 57 58 import org.apache.derby.iapi.store.raw.log.LogInstant; 59 import org.apache.derby.iapi.store.raw.xact.RawTransaction; 60 61 import org.apache.derby.iapi.store.access.TransactionController; 62 import org.apache.derby.iapi.store.access.AccessFactory; 63 import org.apache.derby.iapi.store.access.SpaceInfo; 64 65 import org.apache.derby.iapi.services.io.ArrayInputStream; 66 import org.apache.derby.iapi.services.io.ArrayOutputStream; 67 import org.apache.derby.iapi.services.property.PropertyUtil; 68 import org.apache.derby.iapi.util.ByteArray; 69 70 import java.io.IOException ; 71 import java.io.DataInput ; 72 import java.io.DataOutput ; 73 74 import java.util.Properties ; 75 import java.util.zip.CRC32 ; 76 77 78 84 85 abstract class FileContainer 86 extends BaseContainer implements Cacheable, TypedFormat 87 { 88 89 92 93 protected static final int formatIdInteger = 94 StoredFormatIds.RAW_STORE_SINGLE_CONTAINER_FILE; 95 96 98 101 public int getTypeFormatId() 102 { 103 return StoredFormatIds.RAW_STORE_SINGLE_CONTAINER_FILE; 104 } 105 106 109 110 protected final CacheManager pageCache; protected final CacheManager containerCache; protected final BaseDataFileFactory dataFactory; 114 117 118 protected int pageSize; protected int spareSpace; protected int minimumRecordSize; 123 protected short initialPages; 126 protected boolean canUpdate; 128 private int PreAllocThreshold; private int PreAllocSize; private boolean bulkIncreaseContainerSize; private static final int PRE_ALLOC_THRESHOLD = 8; 138 private static final int MIN_PRE_ALLOC_SIZE = 1; 139 private static final int DEFAULT_PRE_ALLOC_SIZE = 8; 140 private static final int MAX_PRE_ALLOC_SIZE = 1000; 141 142 145 146 protected long firstAllocPageNumber; protected long firstAllocPageOffset; protected long containerVersion; protected long estimatedRowCount; protected LogInstant lastLogInstant; 163 private long reusableRecordIdSequenceNumber; 164 165 166 173 private long lastInsertedPage[]; 174 private int lastInsertedPage_index; 175 176 182 private long lastUnfilledPage; 183 184 189 private long lastAllocatedPage; 190 191 195 private long estimatedPageCount; 196 197 198 protected boolean preDirty; 209 protected boolean isDirty; 210 211 246 protected AllocationCache allocCache; 247 248 251 byte[] containerInfo; 252 253 private CRC32 checksum; 255 258 private byte[] encryptionBuffer; 259 260 263 264 265 private static final int CONTAINER_FORMAT_ID_SIZE = 4; 266 267 268 protected static final int CHECKSUM_SIZE = 8; 269 270 289 protected static final int CONTAINER_INFO_SIZE = 290 CONTAINER_FORMAT_ID_SIZE+4+4+4+4+2+2+8+8+8+8+CHECKSUM_SIZE+8+8; 291 292 295 protected static final int STORED_PAGE_ARG_NUM = 5; 296 protected static final int ALLOC_PAGE_ARG_NUM = 6; 297 298 304 public static final long FIRST_ALLOC_PAGE_NUMBER = 0L; 305 public static final long FIRST_ALLOC_PAGE_OFFSET = 0L; 306 307 private static final int FILE_DROPPED = 0x1; 309 private static final int FILE_COMMITTED_DROP = 0x2; 310 311 private static final int FILE_REUSABLE_RECORDID = 0x8; 313 314 protected static final String SPACE_TRACE = 315 (SanityManager.DEBUG ? "SpaceTrace" : null); 316 317 FileContainer(BaseDataFileFactory factory) 318 { 319 dataFactory = factory; 320 pageCache = factory.getPageCache(); 321 containerCache = factory.getContainerCache(); 322 323 initContainerHeader(true); 324 } 325 326 329 public SpaceInfo getSpaceInfo(BaseContainerHandle handle) 330 throws StandardException 331 { 332 SpaceInformation spaceInfo; 333 synchronized(allocCache) 334 { 335 spaceInfo = 336 allocCache.getAllPageCounts(handle,firstAllocPageNumber); 337 } 338 spaceInfo.setPageSize(pageSize); 339 return spaceInfo; 340 } 341 342 347 348 351 352 362 public Cacheable setIdentity(Object key) throws StandardException 363 { 364 return setIdent((ContainerKey) key); 365 } 366 367 379 protected Cacheable setIdent(ContainerKey newIdentity) 380 throws StandardException 381 { 382 boolean ok = openContainer(newIdentity); 383 384 initializeLastInsertedPage(1); 385 lastUnfilledPage = ContainerHandle.INVALID_PAGE_NUMBER; 386 lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; 387 388 estimatedPageCount = -1; 389 390 if (ok) 391 { 392 fillInIdentity(newIdentity); 395 return this; 396 } 397 else 398 { 399 return null; 400 } 401 } 402 403 public Cacheable createIdentity(Object key, Object createParameter) 404 throws StandardException 405 { 406 if (SanityManager.DEBUG) 407 { 408 SanityManager.ASSERT( 409 !(key instanceof PageKey), "PageKey input to create container"); 410 } 411 412 return createIdent((ContainerKey) key, createParameter); 413 } 414 415 416 protected Cacheable createIdent( 419 ContainerKey newIdentity, 420 Object createParameter) 421 throws StandardException 422 { 423 if (createParameter != this) 428 { 429 initContainerHeader(true ); 430 431 if (createParameter != null && 432 (createParameter instanceof ByteArray)) 433 { 434 439 createInfoFromLog((ByteArray)createParameter); 440 } 441 else 442 { 443 if (SanityManager.DEBUG) 444 { 445 if (createParameter != null && 446 !(createParameter instanceof Properties )) 447 { 448 SanityManager.THROWASSERT( 449 "Expecting a non-null createParameter to a " + 450 "Properties instead of " + 451 createParameter.getClass().getName()); 452 } 453 } 454 455 createInfoFromProp((Properties )createParameter); 456 } 457 } 458 else 459 { 460 initContainerHeader(false); 463 } 464 465 if (initialPages > 1) 466 { 467 PreAllocThreshold = 0; 468 PreAllocSize = initialPages; 469 bulkIncreaseContainerSize = true; 470 } 471 else 472 { 473 PreAllocThreshold = PRE_ALLOC_THRESHOLD; 474 } 475 476 createContainer(newIdentity); 477 478 setDirty(true); 479 480 fillInIdentity(newIdentity); 483 484 return this; 485 } 486 487 public void clearIdentity() 488 { 489 490 closeContainer(); 491 492 initializeLastInsertedPage(1); 493 lastUnfilledPage = ContainerHandle.INVALID_PAGE_NUMBER; 494 lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; 495 496 canUpdate = false; 497 super.clearIdentity(); 498 } 499 500 504 public boolean isDirty() 505 { 506 synchronized (this) 507 { 508 return isDirty; 509 } 510 } 511 512 public void preDirty(boolean preDirtyOn) 513 { 514 synchronized (this) 515 { 516 if (preDirtyOn) 517 { 518 preDirty = true; 522 } 523 else 524 { 525 preDirty = false; 526 notifyAll(); 528 } 529 } 530 } 531 532 protected void setDirty(boolean dirty) 533 { 534 synchronized(this) 535 { 536 preDirty = false; 537 isDirty = dirty; 538 539 notifyAll(); 541 } 542 } 543 544 547 548 557 abstract void createContainer(ContainerKey newIdentity) 558 throws StandardException; 559 560 561 575 abstract boolean openContainer(ContainerKey newIdentity) 576 throws StandardException; 577 578 abstract void closeContainer(); 579 580 587 protected void dropContainer( 588 LogInstant instant, 589 boolean isDropped) 590 { 591 synchronized(this) 592 { 593 setDroppedState(isDropped); 594 setDirty(true); 595 bumpContainerVersion(instant); 596 } 597 } 598 599 600 606 protected final void bumpContainerVersion(LogInstant instant) 607 { 608 lastLogInstant = instant; 609 ++containerVersion; 610 } 611 612 protected long getContainerVersion() 613 { 614 synchronized(this) 619 { 620 return containerVersion; 621 } 622 } 623 624 654 public void getContainerProperties(Properties prop) 655 throws StandardException 656 { 657 if (prop.getProperty(Property.PAGE_SIZE_PARAMETER) != null) 659 { 660 prop.put( 661 Property.PAGE_SIZE_PARAMETER, 662 Integer.toString(pageSize)); 663 } 664 665 if (prop.getProperty(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER) != 667 null) 668 { 669 prop.put( 670 RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, 671 Integer.toString(minimumRecordSize)); 672 } 673 674 if (prop.getProperty(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER) != 676 null) 677 { 678 prop.put( 679 RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, 680 Integer.toString(spareSpace)); 681 } 682 683 if (prop.getProperty(RawStoreFactory.PAGE_REUSABLE_RECORD_ID) != null) 685 { 686 Boolean bool = new Boolean (isReusableRecordId()); 687 prop.put(RawStoreFactory.PAGE_REUSABLE_RECORD_ID, 688 bool.toString()); 689 } 690 691 if (prop.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES) != null) 693 { 694 prop.put(RawStoreFactory.CONTAINER_INITIAL_PAGES, 695 Integer.toString(initialPages)); 696 } 697 698 } 699 700 712 protected void readHeader(DataInput fileData) 713 throws IOException , StandardException 714 { 715 725 byte[] epage = getEmbryonicPage(fileData); 726 727 AllocPage.ReadContainerInfo(containerInfo, epage); 729 730 readHeaderFromArray(containerInfo); 732 733 epage = null; 734 } 735 736 private void initContainerHeader(boolean changeContainer) 739 { 740 if (containerInfo == null) 741 containerInfo = new byte[CONTAINER_INFO_SIZE]; 742 743 if (checksum == null) 744 checksum = new CRC32 (); 745 else 746 checksum.reset(); 747 748 if (allocCache == null) 749 allocCache = new AllocationCache(); 750 else 751 allocCache.reset(); 752 753 if (changeContainer) 754 { 755 pageSize = 0; 756 spareSpace = 0; 757 minimumRecordSize = 0; 758 } 759 760 initialPages = 1; 761 firstAllocPageNumber = ContainerHandle.INVALID_PAGE_NUMBER; 762 firstAllocPageOffset = -1; 763 containerVersion = 0; 764 estimatedRowCount = 0; 765 reusableRecordIdSequenceNumber = 0; 766 767 setDroppedState(false); 768 setCommittedDropState(false); 769 setReusableRecordIdState(false); 770 771 lastLogInstant = null; 773 774 initializeLastInsertedPage(1); 775 lastUnfilledPage = ContainerHandle.INVALID_PAGE_NUMBER; 776 lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; 777 estimatedPageCount = -1; 778 779 PreAllocThreshold = PRE_ALLOC_THRESHOLD; 780 PreAllocSize = DEFAULT_PRE_ALLOC_SIZE; 781 bulkIncreaseContainerSize = false; 782 } 783 784 785 793 private void readHeaderFromArray(byte[] a) 794 throws StandardException, IOException 795 { 796 ArrayInputStream inStream = new ArrayInputStream(a); 797 798 inStream.setLimit(0, CONTAINER_INFO_SIZE); 799 int fid = inStream.readInt(); 800 if (fid != formatIdInteger) 801 { 802 throw StandardException.newException( 803 SQLState.DATA_UNKNOWN_CONTAINER_FORMAT, getIdentity(), 804 new Long (fid)); 805 } 806 807 int status = inStream.readInt(); 808 pageSize = inStream.readInt(); 809 spareSpace = inStream.readInt(); 810 minimumRecordSize = inStream.readInt(); 811 initialPages = inStream.readShort(); 812 PreAllocSize = inStream.readShort(); 813 firstAllocPageNumber = inStream.readLong(); 814 firstAllocPageOffset = inStream.readLong(); 815 containerVersion = inStream.readLong(); 816 estimatedRowCount = inStream.readLong(); 817 reusableRecordIdSequenceNumber = inStream.readLong(); 818 lastLogInstant = null; 819 820 if (PreAllocSize == 0) PreAllocSize = DEFAULT_PRE_ALLOC_SIZE; 822 823 long spare3 = inStream.readLong(); 825 if (initialPages == 0) 829 initialPages = 1; 830 831 PreAllocThreshold = PRE_ALLOC_THRESHOLD; 833 834 long onDiskChecksum = inStream.readLong(); 836 checksum.reset(); 837 checksum.update(a, 0, CONTAINER_INFO_SIZE - CHECKSUM_SIZE); 838 839 if (onDiskChecksum != checksum.getValue()) 840 { 841 PageKey pk = new PageKey(identity, FIRST_ALLOC_PAGE_NUMBER); 842 843 throw dataFactory.markCorrupt 844 (StandardException.newException( 845 SQLState.FILE_BAD_CHECKSUM, 846 pk, 847 new Long (checksum.getValue()), 848 new Long (onDiskChecksum), 849 org.apache.derby.iapi.util.StringUtil.hexDump(a))); 850 } 851 852 allocCache.reset(); 853 854 setDroppedState((status & FILE_DROPPED) != 0); 856 setCommittedDropState((status & FILE_COMMITTED_DROP) != 0); 857 setReusableRecordIdState((status & FILE_REUSABLE_RECORDID) != 0); 858 } 859 860 861 867 protected void writeHeader(byte[] pageData) 868 throws StandardException, IOException 869 { 870 writeHeaderToArray(containerInfo); 873 874 AllocPage.WriteContainerInfo(containerInfo, pageData, false); 875 } 876 877 889 protected void writeHeader(DataOutput fileData, boolean create, byte[] epage) 890 throws IOException , StandardException 891 { 892 writeHeaderToArray(containerInfo); 895 896 900 AllocPage.WriteContainerInfo(containerInfo, epage, create); 901 903 dataFactory.flush(lastLogInstant); 905 if (lastLogInstant != null) 906 lastLogInstant = null; 907 908 dataFactory.writeInProgress(); 910 try 911 { 912 fileData.write(epage); 913 } 914 finally 915 { 916 dataFactory.writeFinished(); 917 } 918 } 919 920 932 protected byte[] getEmbryonicPage(DataInput fileData) throws IOException 933 { 934 byte[] epage = new byte[AllocPage.MAX_BORROWED_SPACE]; 935 936 if (fileData != null) 937 { 938 fileData.readFully(epage); 939 } 940 return epage; 941 } 942 943 949 private void writeHeaderToArray(byte[] a) throws IOException 950 { 951 if (SanityManager.DEBUG) 952 SanityManager.ASSERT(a.length >= CONTAINER_INFO_SIZE, 953 "header won't fit in array"); 954 955 ArrayOutputStream a_out = new ArrayOutputStream(a); 956 FormatIdOutputStream outStream = new FormatIdOutputStream(a_out); 957 958 int status = 0; 959 if (getDroppedState()) status |= FILE_DROPPED; 960 if (getCommittedDropState()) status |= FILE_COMMITTED_DROP; 961 if (isReusableRecordId()) status |= FILE_REUSABLE_RECORDID; 962 963 a_out.setPosition(0); 964 a_out.setLimit(CONTAINER_INFO_SIZE); 965 outStream.writeInt(formatIdInteger); 966 outStream.writeInt(status); 967 outStream.writeInt(pageSize); 968 outStream.writeInt(spareSpace); 969 outStream.writeInt(minimumRecordSize); 970 outStream.writeShort(initialPages); 971 outStream.writeShort(PreAllocSize); outStream.writeLong(firstAllocPageNumber); 973 outStream.writeLong(firstAllocPageOffset); 974 outStream.writeLong(containerVersion); 975 outStream.writeLong(estimatedRowCount); 976 outStream.writeLong(reusableRecordIdSequenceNumber); 977 outStream.writeLong(0); 979 checksum.reset(); 980 checksum.update(a, 0, CONTAINER_INFO_SIZE - CHECKSUM_SIZE); 981 982 outStream.writeLong(checksum.getValue()); 984 985 a_out.clearLimit(); 986 } 987 988 994 protected ByteArray logCreateContainerInfo() 995 throws StandardException 996 { 997 byte[] array = new byte[CONTAINER_INFO_SIZE]; 999 if (array == null || array.length != CONTAINER_INFO_SIZE) 1000 { 1001 throw StandardException.newException( 1002 SQLState.DATA_OBJECT_ALLOCATION_FAILED, "byte[]"); 1003 } 1004 1005 try 1006 { 1007 writeHeaderToArray(array); 1008 } 1009 catch (IOException ioe) 1010 { 1011 throw StandardException.newException( 1012 SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); 1013 } 1014 1015 return new ByteArray(array); 1016 } 1017 1018 1032 private void createInfoFromLog(ByteArray byteArray) 1033 throws StandardException 1034 { 1035 if (SanityManager.DEBUG) 1036 { 1037 SanityManager.ASSERT(byteArray != null, 1038 "setCreateContainerInfoFromLog: ByteArray is null"); 1039 SanityManager.ASSERT(byteArray.getLength() == 1040 CONTAINER_INFO_SIZE, 1041 "setCreateContainerInfoFromLog: ByteArrays.length() != CONTAINER_INFO_SIZE"); 1042 } 1043 1044 byte[] array = byteArray.getArray(); 1045 1046 ArrayInputStream inStream = new ArrayInputStream(array); 1049 1050 int status = 0; 1051 1052 try 1053 { 1054 inStream.setLimit(0, CONTAINER_INFO_SIZE); 1055 1056 int fid = inStream.readInt(); 1057 if (fid != formatIdInteger) 1058 { 1059 throw StandardException.newException( 1061 SQLState.DATA_UNKNOWN_CONTAINER_FORMAT, 1062 getIdentity(), new Long (fid)); 1063 } 1064 1065 status = inStream.readInt(); 1066 pageSize = inStream.readInt(); 1067 spareSpace = inStream.readInt(); 1068 minimumRecordSize = inStream.readInt(); 1069 initialPages = inStream.readShort(); 1070 1071 } 1072 catch (IOException ioe) 1073 { 1074 throw StandardException.newException( 1075 SQLState.DATA_UNEXPECTED_EXCEPTION, ioe); 1076 } 1077 1078 setReusableRecordIdState((status & FILE_REUSABLE_RECORDID) != 0); 1080 1081 if (SanityManager.DEBUG) 1084 { 1085 SanityManager.ASSERT((status & FILE_DROPPED) == 0 && 1086 (status & FILE_COMMITTED_DROP) == 0, 1087 "cannot load a dropped container"); 1088 } 1089 } 1090 1091 1105 private void createInfoFromProp(Properties createArgs) 1106 throws StandardException 1107 { 1108 AccessFactory af = (AccessFactory) 1110 Monitor.getServiceModule(dataFactory, AccessFactory.MODULE); 1111 1112 TransactionController tc = 1114 (af == null) ? 1115 null : 1116 af.getTransaction( 1117 ContextService.getFactory().getCurrentContextManager()); 1118 1119 pageSize = 1120 PropertyUtil.getServiceInt(tc, createArgs, 1121 Property.PAGE_SIZE_PARAMETER, 1122 Limits.DB2_MIN_PAGE_SIZE, 1123 Limits.DB2_MAX_PAGE_SIZE, 1124 RawStoreFactory.PAGE_SIZE_DEFAULT); 1125 1126 if ((pageSize != 4096) && 1129 (pageSize != 8192) && 1130 (pageSize != 16384) && 1131 (pageSize != 32768)) 1132 { 1133 pageSize= RawStoreFactory.PAGE_SIZE_DEFAULT; 1134 } 1135 1136 spareSpace = 1137 PropertyUtil.getServiceInt(tc, createArgs, 1138 RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, 1139 0, 100, 20); 1140 1141 PreAllocSize = 1142 PropertyUtil.getServiceInt(tc, createArgs, 1143 RawStoreFactory.PRE_ALLOCATE_PAGE, 1144 MIN_PRE_ALLOC_SIZE, 1145 MAX_PRE_ALLOC_SIZE, 1146 DEFAULT_PRE_ALLOC_SIZE ); 1147 1148 if (createArgs == null) { 1151 minimumRecordSize = 1157 PropertyUtil.getServiceInt(tc, 1158 RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, 1159 RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT, (pageSize * (1 - spareSpace/100) - 100), 1162 RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT); 1163 } else { 1164 minimumRecordSize = 1168 PropertyUtil.getServiceInt(tc, createArgs, 1169 RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, 1170 RawStoreFactory.MINIMUM_RECORD_SIZE_MINIMUM, (pageSize * (1 - spareSpace/100) - 100), 1173 RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT); 1174 } 1175 1176 if (createArgs != null) 1182 { 1183 String reusableRecordIdParameter = 1184 createArgs.getProperty(RawStoreFactory.PAGE_REUSABLE_RECORD_ID); 1185 if (reusableRecordIdParameter != null) 1186 { 1187 Boolean reusableRecordId = new Boolean (reusableRecordIdParameter); 1188 setReusableRecordIdState(reusableRecordId.booleanValue()); 1189 } 1190 1191 String containerInitialPageParameter = 1192 createArgs.getProperty(RawStoreFactory.CONTAINER_INITIAL_PAGES); 1193 if (containerInitialPageParameter != null) 1194 { 1195 initialPages = 1196 Short.parseShort(containerInitialPageParameter); 1197 if (initialPages > 1) 1198 { 1199 if (initialPages > RawStoreFactory.MAX_CONTAINER_INITIAL_PAGES) 1200 initialPages = RawStoreFactory.MAX_CONTAINER_INITIAL_PAGES; 1201 } 1202 } 1203 } 1204 } 1205 1206 1208 protected boolean canUpdate() { 1209 return canUpdate; 1210 } 1211 1212 1221 protected void deallocatePage(BaseContainerHandle handle, BasePage page) 1222 throws StandardException 1223 { 1224 if (SanityManager.DEBUG) { 1225 SanityManager.ASSERT(page.isLatched(), "page is not latched"); 1226 SanityManager.ASSERT(page.getPageNumber() != FIRST_ALLOC_PAGE_NUMBER, 1227 "cannot deallocate an alloc page"); 1228 } 1229 1230 long pnum = page.getPageNumber(); 1231 1232 deallocatePagenum(handle, pnum); 1234 1235 page.deallocatePage(); 1240 1241 } 1242 1243 1244 private void deallocatePagenum(BaseContainerHandle handle, long pnum) 1245 throws StandardException 1246 { 1247 synchronized(allocCache) 1248 { 1249 long allocPageNum = allocCache.getAllocPageNumber(handle, pnum, firstAllocPageNumber); 1250 1251 if (SanityManager.DEBUG) 1252 { 1253 if (allocPageNum == ContainerHandle.INVALID_PAGE_NUMBER) 1254 allocCache.dumpAllocationCache(); 1255 1256 if (allocPageNum == ContainerHandle.INVALID_PAGE_NUMBER) 1257 SanityManager.THROWASSERT( 1258 "can't find alloc page for page number " + 1259 pnum); 1260 } 1261 AllocPage allocPage = (AllocPage)handle.getAllocPage(allocPageNum); 1263 if (allocPage == null) 1264 { 1265 PageKey pkey = new PageKey(identity, allocPageNum); 1266 1267 throw StandardException.newException( 1268 SQLState.FILE_NO_ALLOC_PAGE, pkey); 1269 } 1270 1271 try 1272 { 1273 allocCache.invalidate(allocPage, allocPageNum); 1274 1275 allocPage.deallocatePage(handle, pnum); 1278 } 1279 finally 1280 { 1281 allocPage.unlatch(); 1282 } 1283 } 1284 if (pnum <= lastAllocatedPage) 1286 { 1287 lastAllocatedPage = pnum - 1; 1288 } 1289 1290 } 1291 1292 1348 protected void compressContainer( 1349 RawTransaction ntt, 1350 BaseContainerHandle allocHandle) 1351 throws StandardException 1352 { 1353 AllocPage alloc_page = null; 1354 AllocPage prev_alloc_page = null; 1355 1356 if (firstAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER) 1357 { 1358 return; 1360 } 1361 1362 1363 dataFactory.getRawStoreFactory().checkpoint(); 1368 1369 ntt.blockBackup(true); 1374 1375 try 1376 { 1377 synchronized(allocCache) 1378 { 1379 alloc_page = (AllocPage) 1381 allocHandle.getAllocPage(firstAllocPageNumber); 1382 1383 while (!alloc_page.isLast()) 1384 { 1385 if (prev_alloc_page != null) 1386 { 1387 prev_alloc_page.unlatch(); 1390 } 1391 prev_alloc_page = alloc_page; 1392 alloc_page = null; 1393 1394 long nextAllocPageNumber = 1395 prev_alloc_page.getNextAllocPageNumber(); 1396 long nextAllocPageOffset = 1397 prev_alloc_page.getNextAllocPageOffset(); 1398 1399 alloc_page = (AllocPage) 1400 allocHandle.getAllocPage(nextAllocPageNumber); 1401 } 1402 1403 allocCache.invalidate(); 1408 1409 lastUnfilledPage = ContainerHandle.INVALID_PAGE_NUMBER; 1411 lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; 1412 1413 1414 alloc_page.compress(ntt, this); 1415 } 1416 1417 } 1418 finally 1419 { 1420 if (alloc_page != null) 1421 { 1422 alloc_page.unlatch(); 1423 alloc_page = null; 1424 } 1425 if (prev_alloc_page != null) 1426 { 1427 prev_alloc_page.unlatch(); 1428 prev_alloc_page = null; 1429 } 1430 1431 flushAll(); 1433 1434 pageCache.discard(identity); 1441 } 1442 } 1443 1444 1449 public final long getReusableRecordIdSequenceNumber() { 1450 synchronized(this) { 1451 return reusableRecordIdSequenceNumber; 1452 } 1453 } 1454 1455 1458 protected final void incrementReusableRecordIdSequenceNumber() 1459 { 1460 final boolean readOnly = dataFactory.isReadOnly(); 1461 1462 synchronized (this) { 1463 reusableRecordIdSequenceNumber++; 1464 if (!readOnly) 1465 { 1466 isDirty = true; 1467 } 1468 } 1469 } 1470 1471 1517 protected BasePage newPage(BaseContainerHandle userHandle, 1518 RawTransaction ntt, 1519 BaseContainerHandle allocHandle, 1520 boolean isOverflow) 1521 throws StandardException 1522 { 1523 1525 boolean useNTT = (ntt != null); 1526 1527 if (!useNTT) 1529 ntt = userHandle.getTransaction(); 1530 1531 long lastPage; long lastPreallocPage; long pageNumber; PageKey pkey; boolean reuse; 1537 1539 boolean retry; 1540 int numtries = 0; 1541 long startSearch = lastAllocatedPage; 1542 1543 AllocPage allocPage = null; BasePage page = null; 1546 try 1547 { 1548 do 1549 { 1550 retry = false; 1552 synchronized(allocCache) 1553 { 1554 if (SanityManager.DEBUG) 1555 { 1556 SanityManager.ASSERT( 1557 ntt.getId().equals( 1558 allocHandle.getTransaction().getId())); 1559 1560 if (useNTT) 1561 SanityManager.ASSERT( 1562 !ntt.getId().equals( 1563 userHandle.getTransaction().getId())); 1564 } 1565 1566 1606 allocPage = 1607 findAllocPageForAdd(allocHandle, ntt, startSearch); 1608 1609 allocCache.invalidate(allocPage, allocPage.getPageNumber()); 1610 } 1611 1612 if (SanityManager.DEBUG) 1613 { 1614 if (allocPage == null) 1615 allocCache.dumpAllocationCache(); 1616 1617 SanityManager.ASSERT(allocPage != null, 1618 "findAllocPageForAdd returned a null alloc page"); 1619 } 1620 1621 pageNumber = allocPage.nextFreePageNumber(startSearch); 1628 1629 lastPage = allocPage.getLastPagenum(); 1640 lastPreallocPage = allocPage.getLastPreallocPagenum(); 1641 1642 reuse = pageNumber <= lastPage; 1643 1644 pkey = new PageKey(identity, pageNumber); 1646 1647 1648 if (reuse) 1649 { 1650 1656 RecordHandle deallocLock = BasePage.MakeRecordHandle(pkey, 1657 RecordHandle.DEALLOCATE_PROTECTION_HANDLE); 1658 1659 if (!getDeallocLock(allocHandle, deallocLock, 1660 false , 1661 true )) 1662 { 1663 1664 if (numtries == 0) 1671 { 1672 startSearch = ContainerHandle.INVALID_PAGE_NUMBER; 1673 lastAllocatedPage = pageNumber; 1674 } 1675 else startSearch = pageNumber; 1677 1678 numtries++; 1679 1680 allocPage.unlatch(); 1684 allocPage = null; 1685 1686 retry = true; 1687 } 1688 else 1689 { 1690 lastAllocatedPage = pageNumber; 1692 } 1693 } 1694 else 1695 { 1696 if (numtries > 0) 1700 lastAllocatedPage = ContainerHandle.INVALID_PAGE_NUMBER; 1701 else 1702 lastAllocatedPage = pageNumber; 1703 } 1704 1705 if (retry) 1707 continue; 1708 1709 if (SanityManager.DEBUG) 1711 { 1712 SanityManager.ASSERT(retry == false); 1713 } 1714 1715 1720 if (SanityManager.DEBUG) 1721 { 1722 if (lastPage > lastPreallocPage) 1724 { 1725 SanityManager.THROWASSERT("last page " + 1726 lastPage + " > lastPreallocPage " + 1727 lastPreallocPage); 1728 } 1729 } 1730 1731 boolean noIO = 1741 (allocHandle.getMode() & ContainerHandle.MODE_UNLOGGED) == 1742 ContainerHandle.MODE_UNLOGGED; 1743 1744 if (!noIO && 1754 (bulkIncreaseContainerSize || 1755 (pageNumber > lastPreallocPage && 1756 pageNumber > PreAllocThreshold))) 1757 { 1758 allocPage.preAllocatePage( 1759 this, PreAllocThreshold, PreAllocSize); 1760 } 1761 1762 lastPreallocPage = allocPage.getLastPreallocPagenum(); 1766 boolean prealloced = pageNumber <= lastPreallocPage; 1767 1768 1776 int[] createPageArgs = new int[STORED_PAGE_ARG_NUM]; 1777 createPageArgs[0] = StoredPage.FORMAT_NUMBER; 1778 createPageArgs[1] = prealloced ? 1779 0 : (noIO ? 0 : CachedPage.WRITE_SYNC); 1780 createPageArgs[2] = pageSize; 1781 createPageArgs[3] = spareSpace; 1782 createPageArgs[4] = minimumRecordSize; 1783 1784 long pageOffset = pageNumber * pageSize; 1787 1788 1794 try 1795 { 1796 page = initPage(allocHandle, pkey, createPageArgs, pageOffset, 1797 reuse, isOverflow); 1798 } 1799 catch (StandardException se) 1800 { 1801 if (SanityManager.DEBUG) { 1802 SanityManager.DEBUG_PRINT("FileContainer", 1803 "got exception from initPage:" + 1804 "\nreuse = " + reuse + 1805 "\ncreatePageArgs[1] = " + createPageArgs[1] + 1806 "\nallocPage = " + allocPage 1807 ); 1808 } 1809 allocCache.dumpAllocationCache(); 1810 1811 throw se; 1812 } 1813 1814 if (SanityManager.DEBUG) 1815 { 1816 SanityManager.ASSERT( 1817 page != null, "initPage returns null page"); 1818 SanityManager.ASSERT( 1819 page.isLatched(), "initPage returns unlatched page"); 1820 } 1821 1822 allocPage.addPage(this, pageNumber, ntt, userHandle); 1824 1825 if (useNTT) 1826 { 1827 1857 page.unlatch(); 1858 page = null; 1859 1860 page = (BasePage)pageCache.find(pkey); 1863 page = latchPage( 1864 userHandle, page, 1865 false ); 1866 1867 if (page == null || 1868 page.recordCount() != 0 || 1871 page.getPageStatus() != BasePage.VALID_PAGE) 1872 { 1873 retry = true; 1874 if (page != null) 1875 { 1876 page.unlatch(); 1877 page = null; 1878 } 1879 allocPage.unlatch(); 1880 allocPage = null; 1881 } 1882 1883 } 1884 } 1888 while (retry == true); 1889 1890 if (SanityManager.DEBUG) 1892 SanityManager.ASSERT(page.isLatched()); 1893 } 1894 catch (StandardException se) 1895 { 1896 if (page != null) 1897 page.unlatch(); 1898 page = null; 1899 1900 throw se; } 1902 finally 1903 { 1904 if (!useNTT && allocPage != null) 1905 { 1906 allocPage.unlatch(); 1907 allocPage = null; 1908 } 1909 1910 } 1912 1913 if (SanityManager.DEBUG) 1914 SanityManager.ASSERT(page.isLatched()); 1915 1916 1917 if (bulkIncreaseContainerSize) 1923 { 1924 bulkIncreaseContainerSize = false; 1925 PreAllocSize = DEFAULT_PRE_ALLOC_SIZE; 1926 } 1927 1928 if (!isOverflow && page != null) 1929 setLastInsertedPage(pageNumber); 1930 1931 1932 if (estimatedPageCount >= 0) 1935 estimatedPageCount++; 1936 1937 if (!this.identity.equals(page.getPageId().getContainerId())) { 1938 1939 if (SanityManager.DEBUG) { 1940 SanityManager.THROWASSERT( 1941 "just created a new page from a different container" 1942 + "\n this.identity = " + this.identity 1943 + "\n page.getPageId().getContainerId() = " + 1944 page.getPageId().getContainerId() 1945 + "\n userHandle is: " + userHandle 1946 + "\n allocHandle is: " + allocHandle 1947 + "\n this container is: " + this); 1948 } 1949 1950 throw StandardException.newException( 1951 SQLState.DATA_DIFFERENT_CONTAINER, 1952 this.identity, page.getPageId().getContainerId()); 1953 } 1954 1955 return page; } 1957 1958 protected void clearPreallocThreshold() 1959 { 1960 PreAllocThreshold = 0; 1962 } 1963 1964 protected void prepareForBulkLoad(BaseContainerHandle handle, int numPage) 1965 { 1966 clearPreallocThreshold(); 1967 RawTransaction tran = handle.getTransaction(); 1968 1969 AllocPage allocPage = findLastAllocPage(handle, tran); 1973 1974 if (allocPage != null) 1978 { 1979 allocPage.preAllocatePage(this, 0, numPage); 1980 allocPage.unlatch(); 1981 } 1982 } 1983 1984 private boolean pageValid(BaseContainerHandle handle, long pagenum) 1985 throws StandardException 1986 { 1987 boolean retval = false; 1988 1989 synchronized(allocCache) 1990 { 1991 if (pagenum <= allocCache.getLastPageNumber(handle, firstAllocPageNumber) && 1992 allocCache.getPageStatus(handle, pagenum, firstAllocPageNumber) == AllocExtent.ALLOCATED_PAGE) 1993 retval = true; 1994 } 1995 1996 return retval; 1997 } 1998 1999 protected long getLastPageNumber(BaseContainerHandle handle) 2000 throws StandardException 2001 { 2002 long retval; 2003 synchronized(allocCache) 2004 { 2005 2013 if (firstAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER) 2014 { 2015 retval = ContainerHandle.INVALID_PAGE_NUMBER; 2016 } 2017 else 2018 { 2019 retval = 2020 allocCache.getLastPageNumber(handle, firstAllocPageNumber); 2021 } 2022 } 2023 return retval; 2024 } 2025 2026 2032 private AllocPage findAllocPageForAdd(BaseContainerHandle allocHandle, 2033 RawTransaction ntt, long lastAllocatedPage) 2034 throws StandardException 2035 { 2036 AllocPage allocPage = null; 2037 AllocPage oldAllocPage = null; boolean success = false; 2040 try 2041 { 2042 if (firstAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER) 2043 { 2044 allocPage = makeAllocPage(ntt, allocHandle, FIRST_ALLOC_PAGE_NUMBER, 2046 FIRST_ALLOC_PAGE_OFFSET, CONTAINER_INFO_SIZE); 2047 2048 if (SanityManager.DEBUG) 2049 { 2050 SanityManager.ASSERT(firstAllocPageNumber == FIRST_ALLOC_PAGE_NUMBER, 2051 "first Alloc Page number is still not set"); 2052 SanityManager.ASSERT(firstAllocPageOffset == FIRST_ALLOC_PAGE_OFFSET, 2053 "first Alloc Page offset is still not set"); 2054 } 2055 } 2056 else 2057 { 2058 allocPage = (AllocPage)allocHandle.getAllocPage(firstAllocPageNumber); 2060 } 2061 2062 2063 2064 if (!allocPage.canAddFreePage(lastAllocatedPage)) 2065 { 2066 2070 boolean found = false; 2073 while(allocPage.isLast() != true) 2074 { 2075 long nextAllocPageNumber = allocPage.getNextAllocPageNumber(); 2076 long nextAllocPageOffset = allocPage.getNextAllocPageOffset(); 2077 2078 2081 allocPage.unlatch(); 2082 allocPage = null; 2083 2084 allocPage = (AllocPage)allocHandle.getAllocPage(nextAllocPageNumber); 2088 2089 if (allocPage.canAddFreePage(lastAllocatedPage)) 2090 { 2091 found = true; 2092 break; 2093 } 2094 } 2095 2096 if (!found) 2097 { 2098 oldAllocPage = allocPage; 2100 allocPage = null; 2101 2102 if (SanityManager.DEBUG) 2103 SanityManager.ASSERT(oldAllocPage.getLastPagenum() == 2104 oldAllocPage.getMaxPagenum(), 2105 "expect allocpage to be full but last pagenum != maxpagenum"); 2106 2107 long newAllocPageNum = oldAllocPage.getMaxPagenum() + 1; 2108 long newAllocPageOffset = newAllocPageNum; 2110 allocPage = makeAllocPage(ntt, allocHandle, 2111 newAllocPageNum, 2112 newAllocPageOffset, 2113 0 ); 2114 2115 2118 oldAllocPage.chainNewAllocPage(allocHandle, newAllocPageNum, newAllocPageOffset); 2121 oldAllocPage.unlatch(); 2122 oldAllocPage = null; 2123 } 2124 } 2125 2126 2127 success = true; 2128 } 2129 finally { 2131 if (!success) 2132 { 2133 if (oldAllocPage != null) 2134 oldAllocPage.unlatch(); 2135 2136 if (allocPage != null) 2137 allocPage.unlatch(); 2138 2139 allocPage = null; 2140 } 2141 2142 } 2144 2145 return allocPage; 2146 } 2147 2148 2151 private AllocPage findLastAllocPage(BaseContainerHandle handle, 2152 RawTransaction tran) 2153 { 2154 AllocPage allocPage = null; 2155 AllocPage oldAllocPage = null; 2156 2157 if (firstAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER) 2158 return null; 2159 2160 try 2161 { 2162 allocPage = (AllocPage)handle.getAllocPage(firstAllocPageNumber); 2163 while(!allocPage.isLast()) 2164 { 2165 long nextAllocPageNumber = allocPage.getNextAllocPageNumber(); 2166 long nextAllocPageOffset = allocPage.getNextAllocPageOffset(); 2167 2168 allocPage.unlatch(); 2169 allocPage = null; 2170 2171 allocPage = (AllocPage)handle.getAllocPage(nextAllocPageNumber); 2172 } 2173 } 2174 catch (StandardException se) 2175 { 2176 if (allocPage != null) 2177 allocPage.unlatch(); 2178 allocPage = null; 2179 } 2180 2181 return allocPage; 2182 2183 } 2184 2185 2186 2189 private AllocPage makeAllocPage(RawTransaction ntt, 2190 BaseContainerHandle handle, 2191 long pageNumber, 2192 long pageOffset, 2193 int containerInfoSize) 2194 throws StandardException 2195 { 2196 if (SanityManager.DEBUG) 2197 { 2198 if (containerInfoSize != 0 && 2199 containerInfoSize != CONTAINER_INFO_SIZE) 2200 SanityManager.THROWASSERT( 2201 "expect 0 or " + CONTAINER_INFO_SIZE + 2202 ", got " + containerInfoSize); 2203 2204 if (pageNumber != FIRST_ALLOC_PAGE_NUMBER && 2205 containerInfoSize != 0) 2206 SanityManager.THROWASSERT( 2207 "Not first alloc page but container info size " 2208 + containerInfoSize); 2209 } 2210 2211 2220 2228 boolean noIO = (handle.getMode() & ContainerHandle.MODE_UNLOGGED) == 2229 ContainerHandle.MODE_UNLOGGED; 2230 2231 int[] createAllocPageArgs = new int[ALLOC_PAGE_ARG_NUM]; 2232 createAllocPageArgs[0] = AllocPage.FORMAT_NUMBER; 2233 createAllocPageArgs[1] = noIO ? 0 : CachedPage.WRITE_SYNC; 2234 createAllocPageArgs[2] = pageSize; 2235 createAllocPageArgs[3] = 0; createAllocPageArgs[4] = containerInfoSize; 2237 createAllocPageArgs[5] = minimumRecordSize; 2238 2239 if (SanityManager.DEBUG) 2240 { 2241 if (SanityManager.DEBUG_ON(SPACE_TRACE)) 2242 { 2243 SanityManager.DEBUG( 2244 SPACE_TRACE, "making new allocation page at " + pageNumber); 2245 } 2246 } 2247 2248 if (pageNumber == FIRST_ALLOC_PAGE_NUMBER) 2249 { 2250 firstAllocPageNumber = pageNumber; 2259 firstAllocPageOffset = pageOffset; 2260 2261 } 2262 2263 PageKey pkey = new PageKey(identity, pageNumber); 2264 2265 return (AllocPage)initPage(handle, pkey, createAllocPageArgs, 2267 pageOffset, 2268 false, 2269 false ); 2270 } 2271 2272 2285 protected BasePage initPage(BaseContainerHandle allochandle, 2286 PageKey pkey, 2287 int[] createArgs, 2288 long pageOffset, 2289 boolean reuse, 2290 boolean overflow) throws StandardException 2291 { 2292 BasePage page = null; 2293 2294 boolean releasePage = true; 2295 2296 try 2297 { 2298 if (reuse) { 2300 2304 if (SanityManager.DEBUG) 2305 { 2306 if (SanityManager.DEBUG_ON(SPACE_TRACE)) 2307 { 2308 SanityManager.DEBUG( 2309 SPACE_TRACE, "reusing page " + pkey); 2310 } 2311 } 2312 2313 page = (BasePage)pageCache.find(pkey); 2314 if (page == null) { 2316 throw StandardException.newException( 2317 SQLState.FILE_REUSE_PAGE_NOT_FOUND, pkey); 2318 } 2319 } 2320 else 2321 { 2322 if (SanityManager.DEBUG) 2323 { 2324 if (SanityManager.DEBUG_ON(SPACE_TRACE)) 2325 { 2326 SanityManager.DEBUG( 2327 SPACE_TRACE, "allocation new page " + pkey); 2328 } 2329 } 2330 2331 page = (BasePage) pageCache.create(pkey, createArgs); 2333 2334 if (SanityManager.DEBUG) 2335 SanityManager.ASSERT(page != null, "page Cache create return a null page"); 2336 } 2337 releasePage = false; 2338 page = latchPage(allochandle, page, true ); 2339 2340 if (page == null) 2341 { 2342 throw StandardException.newException( 2343 SQLState.FILE_NEW_PAGE_NOT_LATCHED, pkey); 2344 } 2345 2346 int initPageFlag = 0; 2349 if (reuse) initPageFlag |= BasePage.INIT_PAGE_REUSE; 2350 if (overflow) initPageFlag |= BasePage.INIT_PAGE_OVERFLOW; 2351 if (reuse && isReusableRecordId()) 2352 initPageFlag |= BasePage.INIT_PAGE_REUSE_RECORDID; 2353 2354 page.initPage(initPageFlag, pageOffset); 2355 page.setContainerRowCount(estimatedRowCount); 2356 2357 } 2358 finally 2359 { 2360 if (releasePage && page != null) 2361 { 2362 pageCache.release((Cacheable)page); 2365 page = null; 2366 } 2367 } 2368 2369 return page; 2370 } 2371 2372 2373 2393 private BasePage getUserPage(BaseContainerHandle handle, long pageNumber, 2394 boolean overflowOK, boolean wait) 2395 throws StandardException 2396 { 2397 2398 if (SanityManager.DEBUG) 2399 { 2400 SanityManager.ASSERT( 2401 pageNumber != FIRST_ALLOC_PAGE_NUMBER, 2402 "getUserPage trying to get an alloc page, pageNumber = " + 2403 pageNumber); 2404 2405 if (pageNumber < ContainerHandle.FIRST_PAGE_NUMBER) 2406 SanityManager.THROWASSERT("pageNumber = " + pageNumber); 2407 } 2408 2409 if (pageNumber < ContainerHandle.FIRST_PAGE_NUMBER) 2410 return null; 2411 2412 if (getCommittedDropState()) return null; 2414 2415 if (!pageValid(handle, pageNumber)) 2416 { 2417 return null; 2418 } 2419 2420 2422 PageKey pageSearch = new PageKey(identity, pageNumber); 2423 BasePage page = (BasePage)pageCache.find(pageSearch); 2424 2425 if (page == null) 2426 { 2427 return page; 2428 } 2429 2430 if (latchPage(handle,page,wait) == null) 2432 { 2433 return null; 2435 } 2436 2437 if ((page.isOverflowPage() && !overflowOK) || 2445 (page.getPageStatus() != BasePage.VALID_PAGE)) 2446 { 2447 page.unlatch(); 2449 page = null; 2450 } 2451 2452 return page; 2453 } 2454 2455 protected void trackUnfilledPage(long pagenumber, boolean unfilled) 2456 { 2457 if (!dataFactory.isReadOnly()) 2458 allocCache.trackUnfilledPage(pagenumber, unfilled); 2459 } 2460 2461 2469 protected BasePage getPage(BaseContainerHandle handle, long pageNumber, 2470 boolean wait) 2471 throws StandardException 2472 { 2473 return getUserPage(handle, pageNumber, true , 2474 wait); 2475 } 2476 2477 2478 2483 protected BasePage getAnyPage(BaseContainerHandle handle, long pageNumber) throws StandardException 2484 { 2485 2488 if (getCommittedDropState()) return null; 2490 2491 synchronized(allocCache) 2493 { 2494 allocCache.invalidate(); 2495 } 2496 2497 PageKey pageSearch = new PageKey(identity, pageNumber); 2498 BasePage page = (BasePage) pageCache.find(pageSearch); 2499 2500 return page; 2501 } 2502 2503 2534 protected BasePage reCreatePageForRedoRecovery( 2535 BaseContainerHandle handle, 2536 int pageFormat, 2537 long pageNumber, 2538 long pageOffset) 2539 throws StandardException 2540 { 2541 2545 boolean rollForwardRecovery = 2547 ((RawTransaction)handle.getTransaction()).inRollForwardRecovery(); 2548 2549 if (!rollForwardRecovery && !(PropertyUtil.getSystemBoolean( 2550 RawStoreFactory.PATCH_INITPAGE_RECOVER_ERROR))) 2551 { 2552 return null; 2553 } 2554 2555 2558 PageKey pkey = new PageKey(identity, pageNumber); 2560 2561 int[] reCreatePageArgs = null; 2562 2563 if (pageFormat == StoredPage.FORMAT_NUMBER) 2564 { 2565 reCreatePageArgs = new int[STORED_PAGE_ARG_NUM]; 2566 reCreatePageArgs[0] = pageFormat; 2567 reCreatePageArgs[1] = CachedPage.WRITE_SYNC; 2568 reCreatePageArgs[2] = pageSize; 2569 reCreatePageArgs[3] = spareSpace; 2570 reCreatePageArgs[4] = minimumRecordSize; 2571 } 2572 else if (pageFormat == AllocPage.FORMAT_NUMBER) 2573 { 2574 reCreatePageArgs = new int[ALLOC_PAGE_ARG_NUM]; 2575 2576 2579 int containerInfoSize = 0; 2580 if (pageNumber == FIRST_ALLOC_PAGE_NUMBER) 2581 { 2582 containerInfoSize = CONTAINER_INFO_SIZE; 2583 firstAllocPageNumber = pageNumber; 2584 firstAllocPageOffset = pageOffset; 2585 } 2586 2587 2588 reCreatePageArgs[0] = pageFormat; 2589 reCreatePageArgs[1] = CachedPage.WRITE_SYNC; 2590 reCreatePageArgs[2] = pageSize; 2591 reCreatePageArgs[3] = 0; reCreatePageArgs[4] = containerInfoSize; 2593 reCreatePageArgs[5] = minimumRecordSize; 2594 } 2595 else 2596 { 2597 throw StandardException.newException( 2598 SQLState.DATA_UNKNOWN_PAGE_FORMAT, pkey); 2599 } 2600 2601 if (SanityManager.DEBUG) 2602 { 2603 if (SanityManager.DEBUG_ON("LoadTran")) 2604 SanityManager.DEBUG_PRINT( 2605 "Trace", "recreating page " + pkey + " for load tran"); 2606 } 2607 2608 BasePage page = null; 2612 boolean releasePage = true; 2613 2614 try 2615 { 2616 try 2617 { 2618 page = (BasePage) pageCache.create(pkey, reCreatePageArgs); 2620 } 2621 catch (StandardException se) 2622 { 2623 throw StandardException.newException( 2624 SQLState.FILE_NEW_PAGE_DURING_RECOVERY, se, pkey); 2625 } 2626 2627 if (page != null) 2628 { 2629 releasePage = false; 2630 page = latchPage(handle, page, false ); 2631 2632 if (page == null) 2633 { 2634 throw StandardException.newException( 2635 SQLState.FILE_NEW_PAGE_NOT_LATCHED, pkey); 2636 } 2637 } 2638 else 2639 { 2640 throw StandardException.newException( 2641 SQLState.FILE_NEW_PAGE_DURING_RECOVERY, pkey); 2642 } 2643 2644 } 2645 finally 2646 { 2647 if (releasePage && page != null) 2648 { 2649 pageCache.release((Cacheable)page); 2653 page = null; 2654 } 2655 } 2656 2657 return page; 2658 2659 } 2660 2661 2662 2668 protected BasePage getAllocPage(long pageNumber) throws StandardException 2669 { 2670 if (getCommittedDropState()) return null; 2672 2673 PageKey pageSearch = new PageKey(identity, pageNumber); 2674 BasePage page = (BasePage) pageCache.find(pageSearch); 2675 2676 if (SanityManager.DEBUG) 2677 { 2678 if (page == null) 2679 SanityManager.THROWASSERT( 2680 "getting a null alloc page page " + 2681 getIdentity() + pageNumber); 2682 2683 if ( ! (page instanceof AllocPage)) 2684 SanityManager.THROWASSERT( 2685 "trying to get a user page as an alloc page " + 2686 getIdentity() + pageNumber); 2687 } 2688 2689 return page; 2691 } 2692 2693 2699 protected BasePage getHeadPage(BaseContainerHandle handle, long pageNumber, 2700 boolean wait) 2701 throws StandardException 2702 { 2703 return getUserPage(handle, pageNumber, false , 2704 wait); 2705 } 2706 2707 2712 protected BasePage getFirstHeadPage(BaseContainerHandle handle, boolean wait) 2713 throws StandardException 2714 { 2715 return getNextHeadPage(handle, ContainerHandle.FIRST_PAGE_NUMBER-1, wait); 2716 } 2717 2718 2722 protected BasePage getNextHeadPage(BaseContainerHandle handle, 2723 long pageNumber, boolean wait) 2724 throws StandardException 2725 { 2726 long nextNumber; 2727 2728 while(true) 2729 { 2730 synchronized(allocCache) 2731 { 2732 nextNumber = allocCache.getNextValidPage(handle, pageNumber, firstAllocPageNumber); 2734 } 2735 2736 if (nextNumber == ContainerHandle.INVALID_PAGE_NUMBER) 2737 return null; 2738 2739 BasePage p = getUserPage(handle, nextNumber, 2741 false , wait); 2742 if (p != null) 2743 return p; 2744 2745 pageNumber = nextNumber; 2746 } 2747 } 2748 2749 2750 private BasePage getInsertablePage(BaseContainerHandle handle, 2751 long pageNumber, 2752 boolean wait, 2753 boolean overflowOK) 2754 throws StandardException 2755 { 2756 if (pageNumber == ContainerHandle.INVALID_PAGE_NUMBER) 2757 return null; 2758 2759 BasePage p = getUserPage(handle, pageNumber, overflowOK, wait); 2760 if (p != null) 2761 { 2762 if (!p.allowInsert()) 2764 { 2765 p.unlatch(); 2766 p = null; 2767 2768 allocCache.trackUnfilledPage(pageNumber, false); 2771 } 2772 } 2773 2791 return p; 2792 } 2793 2794 2807 protected BasePage getPageForCompress( 2808 BaseContainerHandle handle, 2809 int flag, 2810 long pageno) 2811 throws StandardException 2812 { 2813 BasePage p = null; 2814 boolean getLastInserted = 2815 (flag & ContainerHandle.GET_PAGE_UNFILLED) == 0; 2816 2817 if (getLastInserted) 2818 { 2819 long localLastInsertedPage = getLastInsertedPage(); 2822 2823 if ((localLastInsertedPage < pageno) && 2824 (localLastInsertedPage != ContainerHandle.INVALID_PAGE_NUMBER)) 2825 { 2826 2828 p = getInsertablePage( 2829 handle, 2830 localLastInsertedPage, 2831 true, 2832 false ); 2833 2834 if (p == null) 2837 { 2838 2844 if (localLastInsertedPage == getLastUnfilledPage()) 2845 setLastUnfilledPage( 2846 ContainerHandle.INVALID_PAGE_NUMBER); 2847 2848 if (localLastInsertedPage == getLastInsertedPage()) 2849 setLastInsertedPage( 2850 ContainerHandle.INVALID_PAGE_NUMBER); 2851 } 2852 } 2853 } 2854 else 2855 { 2856 2858 long localLastUnfilledPage = getLastUnfilledPage(); 2859 2860 if (localLastUnfilledPage == ContainerHandle.INVALID_PAGE_NUMBER || 2861 localLastUnfilledPage >= pageno || 2862 localLastUnfilledPage == getLastInsertedPage()) 2863 { 2864 localLastUnfilledPage = 2866 getUnfilledPageNumber(handle, 0); 2867 } 2868 2869 if ((localLastUnfilledPage != 2870 ContainerHandle.INVALID_PAGE_NUMBER) && 2871 (localLastUnfilledPage < pageno)) 2872 { 2873 p = getInsertablePage( 2874 handle, localLastUnfilledPage, true, false); 2875 } 2876 2877 if (p != null) 2879 { 2880 setLastUnfilledPage(localLastUnfilledPage); 2881 setLastInsertedPage(localLastUnfilledPage); 2882 } 2883 } 2884 2885 return p; 2886 } 2887 2888 2892 protected BasePage getPageForInsert(BaseContainerHandle handle, 2893 int flag) 2894 throws StandardException 2895 { 2896 BasePage p = null; 2897 boolean getLastInserted = (flag & ContainerHandle.GET_PAGE_UNFILLED) == 0; 2898 2899 if (getLastInserted) 2900 { 2901 long localLastInsertedPage = getLastInsertedPage(); 2904 2905 if (localLastInsertedPage != ContainerHandle.INVALID_PAGE_NUMBER) 2906 { 2907 2909 p = getInsertablePage(handle, localLastInsertedPage, 2910 false, 2911 false ); 2912 2913 if (p == null) 2914 { 2915 2919 2920 localLastInsertedPage = getLastInsertedPage(); 2921 2922 p = getInsertablePage(handle, localLastInsertedPage, 2923 true, 2924 false ); 2925 } 2926 } 2927 2928 if (p == null) 2931 { 2932 2938 if (localLastInsertedPage == getLastUnfilledPage()) 2939 setLastUnfilledPage(ContainerHandle.INVALID_PAGE_NUMBER); 2940 2941 if (localLastInsertedPage == getLastInsertedPage()) 2942 setLastInsertedPage(ContainerHandle.INVALID_PAGE_NUMBER); 2943 } 2944 } 2945 else { long localLastUnfilledPage = getLastUnfilledPage(); 2948 2949 if (localLastUnfilledPage == ContainerHandle.INVALID_PAGE_NUMBER || 2950 localLastUnfilledPage == getLastInsertedPage()) 2951 localLastUnfilledPage = getUnfilledPageNumber(handle, localLastUnfilledPage); 2952 2953 if (localLastUnfilledPage != ContainerHandle.INVALID_PAGE_NUMBER) 2954 { 2955 p = getInsertablePage(handle, localLastUnfilledPage, true, false); 2960 2961 if (p == null) 2963 { 2964 localLastUnfilledPage = getUnfilledPageNumber(handle, localLastUnfilledPage); 2965 if (localLastUnfilledPage != ContainerHandle.INVALID_PAGE_NUMBER) 2966 { 2967 p = getInsertablePage(handle, localLastUnfilledPage, true, 2968 false); 2969 } 2970 } 2971 } 2972 2973 if (p != null) 2975 { 2976 setLastUnfilledPage(localLastUnfilledPage); 2977 setLastInsertedPage(localLastUnfilledPage); 2978 } 2979 } 2980 2981 return p; 2982 2983 } 2984 2985 2986 2998 protected BasePage getLatchedPage(BaseContainerHandle handle, 2999 long pageNumber) 3000 throws StandardException 3001 { 3002 PageKey pageKey = new PageKey(identity, pageNumber); 3003 BasePage page = (BasePage) pageCache.find(pageKey); 3004 3005 if (SanityManager.DEBUG){ 3006 SanityManager.ASSERT(page != null, "page is not found :" + pageKey); 3007 } 3008 3009 page = latchPage(handle, page, true); 3011 3012 if (SanityManager.DEBUG){ 3013 SanityManager.ASSERT(page.isLatched(), "page is not latched:" + pageKey); 3014 } 3015 3016 return page; 3017 } 3018 3019 3020 3021 private long getUnfilledPageNumber(BaseContainerHandle handle, long pagenum) 3022 throws StandardException 3023 { 3024 synchronized(allocCache) 3025 { 3026 return allocCache. 3027 getUnfilledPageNumber(handle, firstAllocPageNumber, pagenum); 3028 } 3029 } 3030 3031 3034 3040 public long getEstimatedRowCount(int flag) 3041 { 3042 return estimatedRowCount; 3043 } 3044 3045 3048 public void setEstimatedRowCount(long count, int flag) 3049 { 3050 boolean readOnly = dataFactory.isReadOnly(); 3051 3052 synchronized(this) 3053 { 3054 estimatedRowCount = count; 3055 3056 if (!readOnly) 3057 isDirty = true; 3058 } 3059 } 3060 3061 3065 protected void updateEstimatedRowCount(int delta) 3066 { 3067 boolean readOnly = dataFactory.isReadOnly(); 3068 3069 synchronized(this) 3070 { 3071 estimatedRowCount += delta; 3072 if (estimatedRowCount < 0) 3073 estimatedRowCount = 0; 3074 3075 if (!readOnly) 3078 isDirty = true; 3079 } 3080 } 3081 3082 3083 3087 public long getEstimatedPageCount(BaseContainerHandle handle, int flag) 3088 throws StandardException 3089 { 3090 3092 if (estimatedPageCount < 0) 3093 { 3094 synchronized(allocCache) 3095 { 3096 estimatedPageCount = 3097 allocCache.getEstimatedPageCount(handle, firstAllocPageNumber); 3098 } 3099 } 3100 3101 if (SanityManager.DEBUG) 3102 SanityManager.ASSERT(estimatedPageCount >= 0, 3103 "AllocCache returns negatie estimatedPageCount"); 3104 3105 return estimatedPageCount; 3106 } 3107 3108 3111 3112 3119 protected abstract void readPage(long pageNumber, byte[] pageData) 3120 throws IOException , StandardException; 3121 3122 3123 3130 protected abstract void writePage(long pageNumber, byte[] pageData, boolean syncPage) 3131 throws IOException , StandardException; 3132 3133 3136 3143 protected void decryptPage(byte[] pageData, int pageSize) 3144 throws StandardException 3145 { 3146 synchronized(this) 3150 { 3151 if (encryptionBuffer == null || encryptionBuffer.length < pageSize) 3152 encryptionBuffer = new byte[pageSize]; 3153 3154 int len = dataFactory.decrypt(pageData, 0, pageSize, 3155 encryptionBuffer, 0); 3156 3157 if (SanityManager.DEBUG) 3158 SanityManager.ASSERT(len == pageSize, 3159 "Encrypted page length != page length"); 3160 3161 System.arraycopy(encryptionBuffer, 8, pageData, 0, pageSize-8); 3163 System.arraycopy(encryptionBuffer, 0, pageData, pageSize-8, 8); 3164 } 3165 } 3166 3167 3175 protected byte[] encryptPage(byte[] pageData, 3176 int pageSize, 3177 byte[] encryptionBuffer, 3178 boolean newEngine) 3179 throws StandardException 3180 { 3181 3185 System.arraycopy(pageData, pageSize-8, encryptionBuffer, 0, 8); 3186 System.arraycopy(pageData, 0, encryptionBuffer, 8, pageSize-8); 3187 3188 int len = dataFactory.encrypt(encryptionBuffer, 0, pageSize, 3189 encryptionBuffer, 0, newEngine); 3190 3191 if (SanityManager.DEBUG) 3192 SanityManager.ASSERT(len == pageSize, 3193 "Encrypted page length != page length"); 3194 3195 return encryptionBuffer; 3196 } 3197 3198 3199 3205 protected byte[] getEncryptionBuffer() { 3206 3207 if (encryptionBuffer == null || encryptionBuffer.length < pageSize) 3208 encryptionBuffer = new byte[pageSize]; 3209 return encryptionBuffer; 3210 } 3211 3212 3213 3214 3217 3218 3246 protected abstract int preAllocate(long lastPreallocPagenum, int preAllocSize); 3247 3248 3251 protected int doPreAllocatePages(long lastPreallocPagenum, 3252 int preAllocSize) 3253 { 3254 if (SanityManager.DEBUG) 3255 SanityManager.ASSERT(!dataFactory.isReadOnly(), 3256 "how can we be Preallocating pages in a read only database?"); 3257 3258 int[] createArgs = new int[5]; 3260 createArgs[0] = StoredPage.FORMAT_NUMBER; createArgs[1] = CachedPage.WRITE_NO_SYNC; createArgs[2] = pageSize; 3263 createArgs[3] = spareSpace; 3264 createArgs[4] = minimumRecordSize; 3265 3266 StoredPage page = new StoredPage(); 3267 page.setFactory(dataFactory); 3268 3269 boolean error = false; 3270 int count = 0; 3271 3272 while(count < preAllocSize) 3273 { 3274 PageKey pkey = new PageKey(identity, 3275 lastPreallocPagenum+count+1); 3276 try 3277 { 3278 page.createIdentity(pkey, createArgs); 3280 3281 if (SanityManager.DEBUG) 3283 SanityManager.ASSERT(!page.isDirty(), 3284 "create identity failed to do a write page"); 3285 3286 page.clearIdentity(); 3288 } 3289 catch (StandardException se) 3290 { 3291 error = true; 3294 } 3295 3296 if (error) 3297 break; 3298 3299 count++; 3300 } 3301 3302 return count; 3303 } 3304 3305 protected int getPageSize() { 3306 return pageSize; 3307 } 3308 protected int getSpareSpace() { 3309 return spareSpace; 3310 } 3311 protected int getMinimumRecordSize() { 3312 return minimumRecordSize; 3313 } 3314 3315 private synchronized void switchToMultiInsertPageMode( 3316 BaseContainerHandle handle) 3317 throws StandardException 3318 { 3319 if (lastInsertedPage.length == 1) 3320 { 3321 long last = lastInsertedPage[0]; 3322 3323 lastInsertedPage = new long[4]; 3324 lastInsertedPage[0] = last; 3325 3326 for (int i = 3; i > 0; i--) 3327 { 3328 Page page = addPage(handle, false); 3329 lastInsertedPage[i] = page.getPageNumber(); 3330 page.unlatch(); 3331 } 3332 } 3333 } 3334 3335 3339 private synchronized long getLastInsertedPage() 3340 { 3341 if (lastInsertedPage.length == 1) 3342 { 3343 if (SanityManager.DEBUG) 3344 SanityManager.ASSERT(lastInsertedPage_index == 0); 3345 3346 return(lastInsertedPage[0]); 3349 } 3350 else 3351 { 3352 long ret = lastInsertedPage[lastInsertedPage_index++]; 3353 3354 if (lastInsertedPage_index > (lastInsertedPage.length - 1)) 3355 { 3356 lastInsertedPage_index = 0; 3357 } 3358 3359 return(ret); 3360 } 3361 } 3362 3363 private synchronized long getLastUnfilledPage() 3364 { 3365 return lastUnfilledPage; 3366 } 3367 3368 private synchronized void initializeLastInsertedPage(int size) 3369 { 3370 lastInsertedPage = new long[size]; 3371 3372 for (int i = lastInsertedPage.length - 1; i >= 0; i--) 3373 lastInsertedPage[i] = ContainerHandle.INVALID_PAGE_NUMBER; 3374 3375 lastInsertedPage_index = 0; 3376 } 3377 3378 private synchronized void setLastInsertedPage(long val) 3379 { 3380 lastInsertedPage[lastInsertedPage_index] = val; 3381 } 3382 3383 private synchronized void setLastUnfilledPage(long val) 3384 { 3385 lastUnfilledPage = val; 3386 } 3387 3388 3389 3390 3394 3395 3398 protected void letGo(BaseContainerHandle handle) { 3399 super.letGo(handle); 3400 3401 containerCache.release(this); 3402 } 3403 3404 protected BasePage latchPage(BaseContainerHandle handle, BasePage foundPage, boolean wait) 3405 throws StandardException { 3406 3407 if (foundPage == null) 3408 return null; 3409 3410 BasePage ret = super.latchPage(handle, foundPage, wait); 3411 if (ret == null) { 3412 pageCache.release((Cacheable) foundPage); 3414 } 3415 return ret; 3416 } 3417 3418 3419 3420 3427 protected abstract void backupContainer(BaseContainerHandle handle, 3428 String backupLocation) 3429 throws StandardException; 3430} 3431 | Popular Tags |