Source Code Cross Referenced for AllocPage.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » store » raw » data » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.store.raw.data 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.store.raw.data.AllocPage
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.store.raw.data;
0023:
0024:        import org.apache.derby.iapi.services.sanity.SanityManager;
0025:
0026:        import org.apache.derby.iapi.reference.SQLState;
0027:
0028:        import org.apache.derby.iapi.services.io.TypedFormat;
0029:        import org.apache.derby.iapi.services.io.FormatIdUtil;
0030:        import org.apache.derby.iapi.services.io.StoredFormatIds;
0031:
0032:        import org.apache.derby.iapi.error.StandardException;
0033:
0034:        import org.apache.derby.iapi.store.raw.ContainerHandle;
0035:        import org.apache.derby.iapi.store.raw.Loggable;
0036:        import org.apache.derby.iapi.store.raw.PageKey;
0037:        import org.apache.derby.iapi.store.raw.PageTimeStamp;
0038:        import org.apache.derby.iapi.store.raw.RawStoreFactory;
0039:
0040:        import org.apache.derby.iapi.store.raw.log.LogInstant;
0041:        import org.apache.derby.iapi.store.raw.xact.RawTransaction;
0042:
0043:        import org.apache.derby.impl.store.raw.data.BaseContainerHandle;
0044:        import org.apache.derby.impl.store.raw.data.BasePage;
0045:        import org.apache.derby.impl.store.raw.data.PageVersion;
0046:
0047:        import java.io.IOException;
0048:
0049:        import java.io.ObjectOutput;
0050:        import java.io.ObjectInput;
0051:
0052:        import org.apache.derby.iapi.services.io.ArrayInputStream;
0053:
0054:        /**
0055:         An allocation page of the file container.
0056:         <P>
0057:         This class extends a normal Stored page, with the exception that a hunk of
0058:         space may be 'borrowed' by the file container to store the file header.
0059:         <P>
0060:         The borrowed space is not visible to the alloc page even though it is
0061:         present in the page data array.  It is accessed directly by the
0062:         FileContainer.  Any change made to the borrowed space is not managed or
0063:         seen by the allocation page.
0064:         <P
0065:         The reason for having this borrowed space is so that the container header
0066:         does not need to have a page of its own.
0067:
0068:         <P><B>Page Format</B><BR>
0069:         An allocation page extends a stored page, the on disk format is different
0070:         from a stored page in that N bytes are 'borrowed' by the container and the
0071:         page header of an allocation page will be slightly bigger than a normal
0072:         stored page.  This N bytes are stored between the page header and the 
0073:         record space.
0074:         <P>
0075:         The reason why this N bytes can't simply be a row is because it needs to be
0076:         statically accessible by the container object to avoid a chicken and egg
0077:         problem of the container object needing to instantiate an alloc page object
0078:         before it can be objectified, and an alloc page object needing to
0079:         instantiate a container object before it can be objectified.  So this N
0080:         bytes must be stored outside of the normal record interface yet it must be
0081:         settable because only the first alloc page has this borrowed space.  Other
0082:         (non-first) alloc page have N == 0.
0083:
0084:         <PRE>
0085:         <-- borrowed ->
0086:         +----------+-------------+---+---------+-------------------+-------------+--------+
0087:         | FormatId | page header | N | N bytes | alloc extend rows | slot offset |checksum|
0088:         +----------+-------------+---+---------+-------------------+-------------+--------+
0089:         </PRE>
0090:
0091:         N is a byte that indicates the size of the borrowed space.  Once an alloc
0092:         page is initialized, the value of N cannot change.
0093:         <P>
0094:         The maximum space that can be borrowed by the container is 256 bytes.
0095:         <P>
0096:         The allocation page are of the same page size as any other pages in the
0097:         container. The first allocation page of the FileContainer starts at the
0098:         first physical byte of the container.  Subsequent allocation pages are
0099:         chained via the nextAllocPageOffset.  Each allocation page is expected to
0100:         manage at least 1000 user pages (for 1K page size) so this chaining may not
0101:         be a severe performance hit.  The logical -> physical mapping of an
0102:         allocation page is stored in the previous allocation page.  The container
0103:         object will need to maintain this mapping.
0104:         <P>
0105:         The following fields are stored in the page header
0106:         <PRE>
0107:         @format_id	RAW_STORE_ALLOC_PAGE
0108:         @purpose	manage page allocation
0109:         @upgrade
0110:         @disk_layout
0111:         FormatId(int)
0112:         StoredPageHeader	see StoredPage
0113:         nextAllocPageNubmer(long)	the next allocation page's number
0114:         nextAllocPageOffset(long)	the file offset of the next allocation page
0115:         reserved1(long)				reserved for future usage
0116:         reserved2(long)				reserved for future usage
0117:         reserved3(long)				reserved for future usage
0118:         reserved4(long)				reserved for future usage
0119:         N(byte)						the size of the borrowed container info
0120:         containerInfo(byte[N])		the content of the borrowed container info
0121:         AllocExtent					the one and only extent on this alloc page
0122:
0123:         @end_format
0124:         </PRE>
0125:
0126:         <P>
0127:         The allocation page contains allocation extent rows.  In this first cut
0128:         implementation, there is only 1 allocation extent row per allocation page.
0129:         <P>
0130:         The allocation extent row is an externalizable object and is directly
0131:         written on to the page by the alloc page.  In other words, it will not be
0132:         converted in to a storeableRow.  This is to cut down overhead, enhance
0133:         performance and gives more control of the size and layout of the allocation
0134:         extent row to the alloc page.
0135:         <P>
0136:         <HR WIDTH="100%">
0137:         <BR> DETAIL implmentation notes <BR>
0138:         <HR WIDTH="100%">
0139:         <P>
0140:         Create Container - an embryonic allocation page is formatted on disk by a
0141:         spcial static function to avoid instantiating a full AllocPage object.
0142:         This embryonic allocation has enough information that it can find the
0143:         file header and not much else.  Then the allocation page is perperly
0144:         initiated by creating the first extent.
0145:         <P>
0146:         Open Container - A static AllocPage method will be used to read off the
0147:         container information directly from disk.  Even if
0148:         the first alloc page (page 0) is already in the page cache, it will not be
0149:         used because cleaning the alloc page will introduce a deadlock if the
0150:         container is not in the container cache.  Long term, the first alloc page
0151:         should probably live in the container cache rather than in the page cache.
0152:         <P>
0153:         Get Page - The first alloc page (page 0) will be read into the page cache.
0154:         Continue to follow the alloc page chain until the alloc page that manages
0155:         the specified page is found.  From the alloc page, the physical offset of
0156:         the specified page is located.
0157:         <P>
0158:         Cleaning alloc page - the alloc page is written out the same way any page
0159:         is written out.  The container object will provide a call back to the alloc
0160:         page to write the current version of the container object back into the
0161:         borrowed space before the alloc page itself is written out.
0162:         <P>
0163:         Cleaning the container object - get the the first alloc page, dirty it and
0164:         clean it (which will cause it to call the container object to write itself
0165:         out into the borrowed space).  The versioning of the container is
0166:         independent of the versioning of the alloc page.  The container version is
0167:         stored inside the borrowed space and is opaque to the alloc page.
0168:         <P>
0169:         For the fields in an allocation extent row
0170:
0171:         @see AllocExtent
0172:         */
0173:
0174:        public class AllocPage extends StoredPage {
0175:            /*
0176:             * typed format
0177:             */
0178:            public static final int FORMAT_NUMBER = StoredFormatIds.RAW_STORE_ALLOC_PAGE;
0179:
0180:            // format Id must fit in 4 bytes
0181:
0182:            /**
0183:            	Return my format identifier.
0184:             */
0185:            public int getTypeFormatId() {
0186:                return StoredFormatIds.RAW_STORE_ALLOC_PAGE;
0187:            }
0188:
0189:            /*****************************************************************
0190:             * alloc page header
0191:             *****************************************************************/
0192:            private long nextAllocPageNumber; // if isLast, nextAllocPageNumber == INVALID_PAGE_NUMBER
0193:            private long nextAllocPageOffset;
0194:            private long reserved1;
0195:            private long reserved2;
0196:            private long reserved3;
0197:            private long reserved4;
0198:
0199:            private AllocExtent extent;
0200:
0201:            private int borrowedSpace;
0202:
0203:            /*****************************************************************
0204:             * constants
0205:             *****************************************************************/
0206:
0207:            /*
0208:             * allocation page header
0209:             * 8 bytes	long	next alloc page number
0210:             * 8 bytes	long	next alloc page physical offset
0211:             * 8 bytes  long	reserved1
0212:             * 8 bytes  long	reserved2
0213:             * 8 bytes  long	reserved3
0214:             * 8 bytes  long	reserved4
0215:             */
0216:            protected static final int ALLOC_PAGE_HEADER_OFFSET = StoredPage.PAGE_HEADER_OFFSET
0217:                    + StoredPage.PAGE_HEADER_SIZE;
0218:
0219:            protected static final int ALLOC_PAGE_HEADER_SIZE = 8 + 8 + (4 * 8);
0220:
0221:            /* borrowed_SPACE_OFFSET is where the borrowed space len is kept */
0222:            protected static final int BORROWED_SPACE_OFFSET = ALLOC_PAGE_HEADER_OFFSET
0223:                    + ALLOC_PAGE_HEADER_SIZE;
0224:
0225:            /* size of the borrowed space length */
0226:            protected static final int BORROWED_SPACE_LEN = 1; // 1 byte to store the containerInfo length
0227:
0228:            /*
0229:             * BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN is the beginning offset of
0230:             * the borrowed space
0231:             */
0232:
0233:            /*
0234:             * the entire borrowed space must live within MAX_BORROWED_SPACE of the
0235:             * alloc page
0236:             */
0237:            protected static final int MAX_BORROWED_SPACE = RawStoreFactory.PAGE_SIZE_MINIMUM / 5; // cannot take more then 1/5 of the page
0238:
0239:            public AllocPage() {
0240:                super ();
0241:            }
0242:
0243:            /*
0244:             * overwriting StoredPage methods
0245:             */
0246:
0247:            protected int getMaxFreeSpace() {
0248:
0249:                // the maximum free space is reduced by the allocation page header the
0250:                // size of the borrowed space.  In all allocation page except the first
0251:                // one, there is no borrowed space and this is indeed the max free
0252:                // space.  In the first allocation page, need to further subtract
0253:                // the borrowed space
0254:
0255:                return super .getMaxFreeSpace() - ALLOC_PAGE_HEADER_SIZE
0256:                        - BORROWED_SPACE_LEN - borrowedSpace;
0257:            }
0258:
0259:            /*
0260:             * Methods of cachedPage - create, read and write up a page
0261:             * Overwriting StoredPage's CachedPage methods
0262:             */
0263:
0264:            /**
0265:             * Create a new alloc page.
0266:             *
0267:             * @exception  StandardException  Standard exception policy.
0268:             **/
0269:            protected void createPage(PageKey newIdentity, int[] args)
0270:                    throws StandardException {
0271:
0272:                super .createPage(newIdentity, args);
0273:
0274:                // args[0] is the format id
0275:                // args[1] is whether to sync the page to disk or not
0276:                // args[2] is the pagesize (used by StoredPage)
0277:                // args[3] is the spareSize (used by StoredPage)
0278:                // args[4] is the number of bytes to reserve for container header
0279:                // args[5] is the minimumRecordSize
0280:                // NOTE: the arg list here must match the one in FileContainer
0281:                int pageSize = args[2];
0282:                int minimumRecordSize = args[5];
0283:                borrowedSpace = args[4];
0284:
0285:                if (SanityManager.DEBUG) {
0286:                    // MAX_BORROWED_SPACE can't be bigger than what can be represented in 1 byte space
0287:                    SanityManager.ASSERT(MAX_BORROWED_SPACE <= 255);
0288:
0289:                    if (!(borrowedSpace + BORROWED_SPACE_LEN
0290:                            + BORROWED_SPACE_OFFSET < MAX_BORROWED_SPACE)) {
0291:                        SanityManager.THROWASSERT("borrowedSpace too big = "
0292:                                + borrowedSpace);
0293:                    }
0294:                    SanityManager.ASSERT(pageData != null);
0295:                }
0296:                pageData[BORROWED_SPACE_OFFSET] = (byte) borrowedSpace;
0297:
0298:                // remember that the borrowed space have been wiped out now, it
0299:                // needs to be put back when the page is written out.
0300:                // blot out borrowed space before checksum is verified
0301:                if (borrowedSpace > 0) {
0302:                    clearSection(BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN,
0303:                            borrowedSpace);
0304:                }
0305:
0306:                // init the rest of the header and the allocation extent
0307:                nextAllocPageNumber = ContainerHandle.INVALID_PAGE_NUMBER;
0308:                nextAllocPageOffset = 0;
0309:                reserved1 = reserved2 = reserved3 = reserved4 = 0;
0310:
0311:                // calculate how much space we have left for the extent map
0312:                int maxSpace = getMaxFreeSpace();
0313:
0314:                // the pages this extent is going to manage starts from pageNum+1
0315:                // starting physical offset is pageSize*(pageNum+1) since we have
0316:                // no logical to physical mapping yet...
0317:                extent = createExtent(newIdentity.getPageNumber() + 1,
0318:                        pageSize, 0 /* pagesAlloced */, maxSpace);
0319:            }
0320:
0321:            private AllocExtent createExtent(long pageNum, int pageSize,
0322:                    int pagesAlloced, int availspace) {
0323:                int maxPages = AllocExtent.MAX_RANGE(availspace);
0324:
0325:                if (SanityManager.DEBUG)
0326:                    SanityManager.ASSERT(maxPages > 8,
0327:                            "cannot manage > 8 pages");
0328:
0329:                if (SanityManager.DEBUG) {
0330:                    if (SanityManager.DEBUG_ON(TEST_MULTIPLE_ALLOC_PAGE)) {
0331:                        maxPages = 2; // 2 pages per alloc page
0332:                    }
0333:                }
0334:
0335:                return new AllocExtent(pageNum * pageSize, // starting offset
0336:                        pageNum, // extent start page number
0337:                        pagesAlloced, // #pages already allocated
0338:                        pageSize, // page size
0339:                        maxPages); // max #pages to manage
0340:            }
0341:
0342:            /**
0343:            	Initialize in memory structure using the buffer in pageData
0344:
0345:            	@exception StandardException If the page cannot be read correctly, or is inconsistent.
0346:             */
0347:            protected void initFromData(FileContainer myContainer,
0348:                    PageKey newIdentity) throws StandardException {
0349:                if (pageData.length < BORROWED_SPACE_OFFSET
0350:                        + BORROWED_SPACE_LEN) {
0351:                    throw dataFactory.markCorrupt(StandardException
0352:                            .newException(SQLState.DATA_CORRUPT_PAGE,
0353:                                    newIdentity));
0354:                }
0355:
0356:                byte n = pageData[BORROWED_SPACE_OFFSET];
0357:                borrowedSpace = (int) n;
0358:
0359:                if (pageData.length < BORROWED_SPACE_OFFSET
0360:                        + BORROWED_SPACE_LEN + n) {
0361:                    throw dataFactory.markCorrupt(StandardException
0362:                            .newException(SQLState.DATA_CORRUPT_PAGE,
0363:                                    newIdentity));
0364:                }
0365:
0366:                // blot out borrowed space before checksum is verified
0367:                if (borrowedSpace > 0) {
0368:                    clearSection(BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN,
0369:                            borrowedSpace);
0370:                }
0371:
0372:                super .initFromData(myContainer, newIdentity);
0373:
0374:                try {
0375:                    // now init alloc page header fields
0376:                    readAllocPageHeader();
0377:
0378:                    // now init the allocation extent - read it from offset
0379:                    int offset = BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN
0380:                            + borrowedSpace;
0381:                    extent = readExtent(offset);
0382:                } catch (IOException ioe) {
0383:                    throw dataFactory.markCorrupt(StandardException
0384:                            .newException(SQLState.DATA_CORRUPT_PAGE, ioe,
0385:                                    newIdentity));
0386:                } catch (ClassNotFoundException cnfe) {
0387:                    throw dataFactory.markCorrupt(StandardException
0388:                            .newException(SQLState.DATA_CORRUPT_PAGE, cnfe,
0389:                                    newIdentity));
0390:                }
0391:            }
0392:
0393:            /**
0394:            	Write the page out
0395:
0396:            	@exception StandardException If the page cannot be written
0397:             */
0398:            protected void writePage(PageKey identity) throws StandardException {
0399:                try {
0400:                    updateAllocPageHeader(); // write out the next alloc page chain
0401:
0402:                    // blot out borrowed space before checksum is calculated - even
0403:                    // though the page is first read in with borrowed space blotted
0404:                    // out, whenever this page got cleaned the container will overlay
0405:                    // the container info in the borrowed space.
0406:                    int n = (int) pageData[BORROWED_SPACE_OFFSET];
0407:                    if (SanityManager.DEBUG) {
0408:                        if (n != borrowedSpace)
0409:                            SanityManager
0410:                                    .THROWASSERT("different borrowed space "
0411:                                            + n + ", " + borrowedSpace);
0412:                    }
0413:                    if (n > 0) {
0414:                        clearSection(
0415:                                BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN, n);
0416:                    }
0417:
0418:                    int offset = BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN + n;
0419:                    writeExtent(offset);
0420:                } catch (IOException ioe) {
0421:                    // i/o methods on the byte array have thrown an IOException
0422:                    throw dataFactory.markCorrupt(StandardException
0423:                            .newException(SQLState.DATA_CORRUPT_PAGE, ioe,
0424:                                    identity));
0425:                }
0426:
0427:                // let store page write out the rest and do the checksum
0428:                super .writePage(identity);
0429:            }
0430:
0431:            private void readAllocPageHeader() throws IOException {
0432:                ArrayInputStream lrdi = rawDataIn;
0433:                lrdi.setPosition(ALLOC_PAGE_HEADER_OFFSET);
0434:
0435:                nextAllocPageNumber = lrdi.readLong();
0436:                nextAllocPageOffset = lrdi.readLong();
0437:                reserved1 = lrdi.readLong();
0438:                reserved2 = lrdi.readLong();
0439:                reserved3 = lrdi.readLong();
0440:                reserved4 = lrdi.readLong();
0441:            }
0442:
0443:            private void updateAllocPageHeader() throws IOException {
0444:                // rawDataOut and logicalDataOut are defined by StoredPage
0445:                rawDataOut.setPosition(ALLOC_PAGE_HEADER_OFFSET);
0446:                logicalDataOut.writeLong(nextAllocPageNumber);
0447:                logicalDataOut.writeLong(nextAllocPageOffset);
0448:                logicalDataOut.writeLong(0); // reserved1
0449:                logicalDataOut.writeLong(0); // reserved2
0450:                logicalDataOut.writeLong(0); // reserved3
0451:                logicalDataOut.writeLong(0); // reserved4
0452:            }
0453:
0454:            private AllocExtent readExtent(int offset) throws IOException,
0455:                    ClassNotFoundException {
0456:                ArrayInputStream lrdi = rawDataIn;
0457:                rawDataIn.setPosition(offset);
0458:                AllocExtent newExtent = new AllocExtent();
0459:                newExtent.readExternal(lrdi);
0460:
0461:                // in 1.3 or later, make sure the upgrade from before 1.3 is legal.
0462:                if (SanityManager.DEBUG) {
0463:                    int max_range = newExtent.MAX_RANGE(getMaxFreeSpace());
0464:                    long extent_start = newExtent.getFirstPagenum();
0465:                    long extent_end = newExtent.getExtentEnd();
0466:
0467:                    // extent_start + max_range - 1 is the absolute last page this
0468:                    // extent can hope to manage.  See if it did the calculation
0469:                    // correctly after upgrade.
0470:
0471:                    if ((extent_start + max_range - 1) < extent_end) {
0472:                        SanityManager
0473:                                .THROWASSERT("extent range exceed what extent's space can handle ");
0474:                    }
0475:                }
0476:
0477:                return newExtent;
0478:            }
0479:
0480:            private void writeExtent(int offset) throws IOException {
0481:                // rawDataOut and logicalDataOut are defined by StoredPage
0482:                rawDataOut.setPosition(offset);
0483:                extent.writeExternal(logicalDataOut);
0484:            }
0485:
0486:            /*
0487:             * borrowed space management
0488:             */
0489:
0490:            /**
0491:            	Write the container information into the container information area.
0492:
0493:            	@param containerInfo the container information
0494:
0495:            	@param epage the allocation page data which may not be fully formed,
0496:            	but is guarenteed to be big enough to cover the area inhibited by the
0497:            	container info
0498:
0499:            	@param create if create, write out the length of the container info
0500:            	also. Else check to make sure epage's original container info is of the
0501:            	same length
0502:
0503:            	@exception StandardException Cloudscape standard error policy
0504:             */
0505:            public static void WriteContainerInfo(byte[] containerInfo,
0506:                    byte[] epage, boolean create) throws StandardException {
0507:                int N = (containerInfo == null) ? 0 : containerInfo.length;
0508:
0509:                if (SanityManager.DEBUG) {
0510:                    if (create)
0511:                        SanityManager.ASSERT(containerInfo != null,
0512:                                "containerInfo is null");
0513:
0514:                    SanityManager.ASSERT(epage != null, "page array is null");
0515:
0516:                    if (!((containerInfo == null) || ((containerInfo.length
0517:                            + BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN) < epage.length))) {
0518:                        SanityManager
0519:                                .THROWASSERT("containerInfo too big for page array: "
0520:                                        + containerInfo.length);
0521:                    }
0522:
0523:                    if (BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN + N >= MAX_BORROWED_SPACE)
0524:                        SanityManager
0525:                                .THROWASSERT("exceed max borrowable space: "
0526:                                        + N);
0527:                }
0528:
0529:                if ((N + BORROWED_SPACE_LEN + BORROWED_SPACE_OFFSET) > epage.length) {
0530:                    if (SanityManager.DEBUG)
0531:                        SanityManager
0532:                                .THROWASSERT("exceed max borrowable space on page: "
0533:                                        + N);
0534:                }
0535:
0536:                if (create) {
0537:                    epage[BORROWED_SPACE_OFFSET] = (byte) N;
0538:                } else {
0539:                    int oldN = (int) epage[BORROWED_SPACE_OFFSET];
0540:                    if (oldN != N) {
0541:                        throw StandardException.newException(
0542:                                SQLState.DATA_CHANGING_CONTAINER_INFO,
0543:                                new Long(oldN), new Long(N));
0544:                    }
0545:                }
0546:
0547:                if (N != 0)
0548:                    System.arraycopy(containerInfo, 0, epage,
0549:                            BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN, N);
0550:            }
0551:
0552:            /**
0553:            	Extract the container information from epage.
0554:
0555:            	@param containerInfo where to put the extracted information
0556:
0557:            	@param epage the allocation page which has the container information.
0558:            	Epage may not be fully formed, but is guarenteed to be big enough to
0559:            	cover the area inhibited by the container info
0560:             */
0561:            public static void ReadContainerInfo(byte[] containerInfo,
0562:                    byte[] epage) {
0563:                int N = (int) epage[BORROWED_SPACE_OFFSET];
0564:
0565:                if (SanityManager.DEBUG) {
0566:                    if (N != containerInfo.length)
0567:                        SanityManager.THROWASSERT("N not what is expected : "
0568:                                + N);
0569:
0570:                    if (BORROWED_SPACE_OFFSET + BORROWED_SPACE_LEN + N >= MAX_BORROWED_SPACE) {
0571:                        SanityManager
0572:                                .THROWASSERT("exceed max borrowable space: "
0573:                                        + N);
0574:                    }
0575:                }
0576:
0577:                if (N != 0)
0578:                    System.arraycopy(epage, BORROWED_SPACE_OFFSET
0579:                            + BORROWED_SPACE_LEN, containerInfo, 0, N);
0580:            }
0581:
0582:            /*
0583:             * specific methods to AllocPage
0584:             */
0585:
0586:            /**
0587:            	Return the next free page number after given page number 
0588:             */
0589:            public long nextFreePageNumber(long pnum) {
0590:                return extent.getFreePageNumber(pnum);
0591:            }
0592:
0593:            /**
0594:            	Add a page which is managed by this alloc page.
0595:            	Return the page number of the newly added page.
0596:
0597:            	<BR> MT - thread aware (latched)
0598:
0599:            	@param mycontainer (future) allows the alloc page to call back to the
0600:            		container to grow the container by creating and syncing multiple
0601:            		pages at once
0602:            	@param ntt the nested top action that is the allocation transaction.
0603:            		NTT will comit before the user transaction
0604:            	@param userHandle the container handle that is opened by the user
0605:            		transaction.  Use the userHandle to latch the new page so that
0606:            		it may remain latched after NTT is committed so the user
0607:            		transaction can guarentee to have an empty page
0608:
0609:            	@exception StandardException If the page cannot be added
0610:             */
0611:            public void addPage(FileContainer mycontainer, long newPageNumber,
0612:                    RawTransaction ntt, BaseContainerHandle userHandle)
0613:                    throws StandardException {
0614:                // RESOLVED:
0615:                // 
0616:                // to prevent allocating a free page before the freeing transaction has
0617:                // commit, need to grab the DEALLOCATE_PROTECTION_HANDLE
0618:                // the lock probably should be gotten in FileContainer 
0619:                // and not here
0620:
0621:                // page allocation is logged under the nested top action
0622:                owner.getAllocationActionSet().actionAllocatePage(ntt, this ,
0623:                        newPageNumber, AllocExtent.ALLOCATED_PAGE,
0624:                        AllocExtent.FREE_PAGE);
0625:            }
0626:
0627:            /*
0628:            	Deallocate page
0629:             */
0630:            public void deallocatePage(BaseContainerHandle userHandle,
0631:                    long pageNumber) throws StandardException {
0632:                if (SanityManager.DEBUG) {
0633:                    SanityManager.ASSERT(isLatched());
0634:                }
0635:
0636:                // RESOLVED:
0637:                //
0638:                // to prevent this page from being freed before this transaction commits,
0639:                // need to grab the DEALLOCATE_PROTECTION_HANDLE lock on the
0640:                // deallocated page
0641:                // the lock probably should be gotten in FileContainer 
0642:                // and not here
0643:
0644:                owner.getAllocationActionSet().actionAllocatePage(
0645:                        userHandle.getTransaction(), this , pageNumber,
0646:                        AllocExtent.DEALLOCATED_PAGE,
0647:                        AllocExtent.ALLOCATED_PAGE);
0648:            }
0649:
0650:            /*
0651:             * update unfilled page information
0652:             * We will be using inputExtent's unfilledPage bitmap as the new bitmap, so
0653:             * caller of this routine need to not touch the bitmap after this call (in
0654:             * other words, call this ONLY in allocationCache invalidate and throw away
0655:             * the reference to the bitImpl)
0656:             */
0657:            protected void updateUnfilledPageInfo(AllocExtent inputExtent) {
0658:                if (SanityManager.DEBUG) {
0659:                    SanityManager.ASSERT(isLatched());
0660:                }
0661:
0662:                // update the unfilled page bit map unlogged - it is just a hint, not
0663:                // worth logging it - don't dirty the page either, since we didn't log
0664:                // it.  It will be dirtied soon enough by addPage or deallocPage,
0665:                // that is the only reasons why we are invalidataing the
0666:                // allocation cache and updating the unfilled page info. 
0667:                // If we dirty the page, the BI will be copied to the side log
0668:                extent.updateUnfilledPageInfo(inputExtent);
0669:
0670:            }
0671:
0672:            public boolean canAddFreePage(long lastAllocatedPage) {
0673:                if (SanityManager.DEBUG)
0674:                    SanityManager.ASSERT(isLatched());
0675:
0676:                if (extent.isRetired())
0677:                    return false;
0678:
0679:                // if we want to try allocating not from the beginning of the bit map
0680:                // and this alloc page is before that point and this is not the last
0681:                // alloc page, then skip over this alloc page
0682:                if (lastAllocatedPage != ContainerHandle.INVALID_PAGE_NUMBER
0683:                        && extent.getLastPagenum() <= lastAllocatedPage
0684:                        && !isLast())
0685:                    return false;
0686:
0687:                // Else we either want to start examining from this alloc page, or this
0688:                // is the last page, see if we can add a page.
0689:                return extent.canAddFreePage(lastAllocatedPage);
0690:            }
0691:
0692:            public long getNextAllocPageOffset() {
0693:                if (SanityManager.DEBUG) {
0694:                    SanityManager.ASSERT(!isLast(),
0695:                            "next alloc page not present for last alloc page");
0696:
0697:                    SanityManager.ASSERT(isLatched());
0698:                }
0699:
0700:                return nextAllocPageOffset;
0701:            }
0702:
0703:            public void chainNewAllocPage(BaseContainerHandle allocHandle,
0704:                    long newAllocPageNum, long newAllocPageOffset)
0705:                    throws StandardException {
0706:                if (SanityManager.DEBUG) {
0707:                    SanityManager.ASSERT(isLatched());
0708:                    if (SanityManager.DEBUG_ON(FileContainer.SPACE_TRACE))
0709:                        SanityManager.DEBUG(FileContainer.SPACE_TRACE,
0710:                                "chaining new alloc page " + newAllocPageNum
0711:                                        + " to " + getPageNumber());
0712:                }
0713:
0714:                owner.getAllocationActionSet().actionChainAllocPage(
0715:                        allocHandle.getTransaction(), this , newAllocPageNum,
0716:                        newAllocPageOffset);
0717:            }
0718:
0719:            public long getNextAllocPageNumber() {
0720:                if (SanityManager.DEBUG) {
0721:                    SanityManager.ASSERT(isLatched());
0722:                    SanityManager.ASSERT(!isLast(),
0723:                            "next alloc page not present for last alloc page");
0724:                }
0725:                return nextAllocPageNumber;
0726:            }
0727:
0728:            public boolean isLast() {
0729:                if (SanityManager.DEBUG)
0730:                    SanityManager.ASSERT(isLatched());
0731:                return nextAllocPageNumber == ContainerHandle.INVALID_PAGE_NUMBER;
0732:            }
0733:
0734:            /*
0735:             * get the last pagenumber currently managed by this alloc page
0736:             */
0737:            public long getLastPagenum() {
0738:                if (SanityManager.DEBUG)
0739:                    SanityManager.ASSERT(isLatched());
0740:
0741:                return extent.getLastPagenum();
0742:            }
0743:
0744:            /*
0745:             * get the largest page number this alloc page can manage. 
0746:             * This is the different from the last pagenumber currently managed by this
0747:             * alloc page unless the alloc page is full and all the pages have been
0748:             * allocated 
0749:             */
0750:            public long getMaxPagenum() {
0751:                return extent.getExtentEnd();
0752:            }
0753:
0754:            /*
0755:             * get the last preallocated pagenumber managed by this alloc page
0756:             */
0757:            protected long getLastPreallocPagenum() {
0758:                if (SanityManager.DEBUG)
0759:                    SanityManager.ASSERT(isLatched());
0760:
0761:                return extent.getLastPreallocPagenum();
0762:            }
0763:
0764:            protected int getPageStatus(long pageNumber) {
0765:                if (SanityManager.DEBUG)
0766:                    SanityManager.ASSERT(isLatched());
0767:
0768:                return extent.getPageStatus(pageNumber);
0769:            }
0770:
0771:            /**
0772:            	Do the actual page allocation/deallocation/ree underneath a log operation.
0773:            	Change the page status to new status
0774:
0775:            	@exception StandardException If the page cannot be allocated
0776:             */
0777:            protected void setPageStatus(LogInstant instant, long pageNumber,
0778:                    int newStatus) throws StandardException {
0779:                if (SanityManager.DEBUG) {
0780:                    SanityManager.ASSERT(isLatched(), "page is not latched");
0781:                    SanityManager.ASSERT(extent != null, "extent is null");
0782:                }
0783:
0784:                logAction(instant);
0785:
0786:                switch (newStatus) {
0787:                case AllocExtent.ALLOCATED_PAGE:
0788:                    extent.allocPage(pageNumber);
0789:                    break;
0790:                case AllocExtent.DEALLOCATED_PAGE:
0791:                    extent.deallocPage(pageNumber);
0792:                    break;
0793:                case AllocExtent.FREE_PAGE:
0794:                    extent.deallocPage(pageNumber);
0795:                    break;
0796:                }
0797:            }
0798:
0799:            /**
0800:            	Chain the next page number and offset underneath a log record
0801:
0802:            	@exception StandardException Standard Cloudscape error policy
0803:             */
0804:            protected void chainNextAllocPage(LogInstant instant,
0805:                    long newAllocPageNum, long newAllocPageOffset)
0806:                    throws StandardException {
0807:                if (SanityManager.DEBUG)
0808:                    SanityManager.ASSERT(isLatched(), "page is not latched");
0809:
0810:                logAction(instant);
0811:
0812:                nextAllocPageNumber = newAllocPageNum;
0813:                nextAllocPageOffset = newAllocPageOffset;
0814:            }
0815:
0816:            /**
0817:             * Compress free pages.
0818:             * <p>
0819:             * Compress the free pages at the end of the range maintained by
0820:             * this allocation page.  All pages being compressed should be FREE.
0821:             * Only pages in the last allocation page can be compressed.
0822:             * <p>
0823:             *
0824:             * @param instant               log address for this operation.
0825:             * @param new_highest_page      The new highest page on this allocation 
0826:             *                              page.  The number is the offset of the page
0827:             *                              in the array of pages maintained by this 
0828:             *                              allocation page, for instance a value of 0 
0829:             *                              indicates all page except the first one are
0830:             *                              to be truncated.  If all pages are 
0831:             *                              truncated then the offset is set to -1.
0832:             * @param num_pages_truncated   The number of allocated pages in this 
0833:             *                              allocation page prior to the truncate.  
0834:             *                              Note that all pages from NewHighestPage+1 
0835:             *                              through newHighestPage+num_pages_truncated 
0836:             *                              should be FREE.
0837:             *
0838:             * @exception  StandardException  Standard exception policy.
0839:             **/
0840:            protected void compressSpace(LogInstant instant,
0841:                    int new_highest_page, int num_pages_truncated)
0842:                    throws StandardException {
0843:                if (SanityManager.DEBUG) {
0844:                    SanityManager.ASSERT(isLatched(), "page is not latched");
0845:                    SanityManager.ASSERT(isLast(),
0846:                            "compress on non last alloc page.");
0847:                    SanityManager.ASSERT(new_highest_page >= 0,
0848:                            "negative new high page.");
0849:                }
0850:
0851:                logAction(instant);
0852:
0853:                extent.compressPages(new_highest_page, num_pages_truncated);
0854:            }
0855:
0856:            /**
0857:             * Handle undo of compress space operation.
0858:             **/
0859:            protected void undoCompressSpace(LogInstant instant,
0860:                    int new_highest_page, int num_pages_truncated)
0861:                    throws StandardException {
0862:                logAction(instant);
0863:
0864:                extent.undoCompressPages(new_highest_page, num_pages_truncated);
0865:
0866:            }
0867:
0868:            public String toString() {
0869:                if (SanityManager.DEBUG) {
0870:                    String str = "*** Alloc page ***\n"
0871:                            + "nextAllocPageNumber = " + nextAllocPageNumber
0872:                            + "\nnextAllocPageOffset = " + nextAllocPageOffset
0873:                            + "\nreserved1 = " + reserved1 + "\nreserved2 = "
0874:                            + reserved2 + "\nreserved3 = " + reserved3
0875:                            + "\nreserved4 = " + reserved4
0876:                            + "\nborrowedSpace = " + borrowedSpace
0877:                            + "\nextent = " + extent.toDebugString() + "\n"
0878:                            + super .toString();
0879:                    return str;
0880:                } else {
0881:                    return null;
0882:                }
0883:            }
0884:
0885:            /**
0886:            	Return a copy of the allocExtent to be cached by the container.
0887:            	the container must take care to maintain its coherency by
0888:            	invalidating the cache before any update.
0889:             */
0890:            protected AllocExtent getAllocExtent() {
0891:                return extent;
0892:
0893:                // return new AllocExtent(extent);
0894:            }
0895:
0896:            /**
0897:            	Preallocate user page if needed.
0898:
0899:            	@param myContainer the container object
0900:            	@param preAllocThreshold start preallocating after this threshold
0901:            	@param preAllocSize preallocate this number of pages 
0902:             */
0903:            protected void preAllocatePage(FileContainer myContainer,
0904:                    int preAllocThreshold, int preAllocSize) {
0905:                if (SanityManager.DEBUG)
0906:                    SanityManager.ASSERT(isLatched(), "page is not latched");
0907:
0908:                long lastPreallocatedPagenum = extent.getLastPreallocPagenum();
0909:
0910:                if (lastPreallocatedPagenum < preAllocThreshold)
0911:                    return;
0912:
0913:                // don't pre-allocate more than we the extent can handle - this is
0914:                // because if I preallocate the next alloc page as a stored page,
0915:                // that's going to be problem when we try to get it as an alloc page
0916:                // later.  We don't handle changing from a store page type to an alloc
0917:                // page type on disk very well.
0918:                if (extent.getExtentEnd() < (lastPreallocatedPagenum + preAllocSize))
0919:                    preAllocSize = (int) (extent.getExtentEnd() - lastPreallocatedPagenum);
0920:
0921:                if (preAllocSize <= 0)
0922:                    return;
0923:
0924:                // pre-allocate - only a container knows how to write pages
0925:                // preAllocSize may exceed what this allocation page can really
0926:                // handle, but no harm done.  The next allocation page will benefit
0927:                // from the work we have done...
0928:                int n = myContainer.preAllocate(lastPreallocatedPagenum,
0929:                        preAllocSize);
0930:
0931:                if (n > 0) // successfully preallocated some pages
0932:                {
0933:                    // this is purely a performance issue during runtime.  During
0934:                    // recovery, any page that is actually initialized will have its
0935:                    // own initPage log record.  Update extent's preAllocpageNumber
0936:                    // unlogged.
0937:                    //
0938:                    // We could have logged a redo-only log record, but we are counting
0939:                    // on myContainer.preAllocate to do the right thing if we recovered
0940:                    // and have out of date preallocate information.  A reason why
0941:                    // logging this is undesirable is that the alloc page may think the
0942:                    // preallocation happened, but the container may actually choose to
0943:                    // lie about it - if it thinks there is no advantage in actually
0944:                    // doing the I/O now.  So best to leave it alone.
0945:                    extent.setLastPreallocPagenum(lastPreallocatedPagenum + n);
0946:
0947:                    // don't dirty the page - the new preAlloc page number is only set
0948:                    // in memory.  A page should only get 'dirtied' by a log operation,
0949:                    // we are cheating here.  Same with updating the extentStatus bit
0950:                    // without logging.
0951:                }
0952:
0953:            }
0954:
0955:            /**
0956:             * compress out empty pages at end of container.
0957:             * <p>
0958:             * Call the extent to update the data structure make the bit map look
0959:             * like contiguous free pages at the end of the extent no longer exist.
0960:             * Similar to preallocate do the operation unlogged, need to force the
0961:             * change to the extent before actually removing the space from the
0962:             * file.
0963:             * <p>
0964:             * The sequence is:
0965:             *     1) update extent data structure
0966:             *     2) force extent changes to disk
0967:             *     3) truncate pages
0968:             *
0969:             * If the system crashes between 1 and 2 then no changes are on disk.
0970:             * If the system crashes between 2 and 3 then there are extra pages in
0971:             *     the file that extent does not know about, this is the same case
0972:             *     as preallocation which the code already handes.  It will handle
0973:             *     any set of pages from 0 to all of the intended pages being 
0974:             *     truncated.  The next allocate looks at actual size of file as
0975:             *     does the right thing.
0976:             *
0977:             * <p)
0978:             * MT - expect Container level X lock
0979:             *
0980:             * @exception  StandardException  Standard exception policy.
0981:             **/
0982:            protected boolean compress(RawTransaction ntt,
0983:                    FileContainer myContainer) throws StandardException {
0984:                boolean all_pages_compressed = false;
0985:
0986:                if (SanityManager.DEBUG) {
0987:                    SanityManager.ASSERT(isLatched(), "page is not latched");
0988:                }
0989:
0990:                int last_valid_page = extent.compress(owner, ntt, this );
0991:
0992:                if (last_valid_page >= 0) {
0993:                    // a non-negative return means that pages can be returned to
0994:                    // the operating system.
0995:                    myContainer.truncatePages(extent
0996:                            .getPagenum(last_valid_page));
0997:
0998:                    if (last_valid_page == this .getPageNumber()) {
0999:                        // all pages of the extent have been returned to OS.
1000:                        all_pages_compressed = true;
1001:                    }
1002:                }
1003:
1004:                return (all_pages_compressed);
1005:            }
1006:
1007:            /*********************************************************************
1008:             * Extent Testing
1009:             *
1010:             * Use these strings to simulate error conditions for
1011:             * testing purposes.
1012:             *
1013:             *********************************************************************/
1014:            public static final String TEST_MULTIPLE_ALLOC_PAGE = SanityManager.DEBUG ? "TEST_MULTI_ALLOC_PAGE"
1015:                    : null;
1016:        }
w_w___w_.__ja__v__a_2__s___._com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.