Source Code Cross Referenced for AllocExtent.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) 


001:        /*
002:
003:           Derby - Class org.apache.derby.impl.store.raw.data.AllocExtent
004:
005:           Licensed to the Apache Software Foundation (ASF) under one or more
006:           contributor license agreements.  See the NOTICE file distributed with
007:           this work for additional information regarding copyright ownership.
008:           The ASF licenses this file to you under the Apache License, Version 2.0
009:           (the "License"); you may not use this file except in compliance with
010:           the License.  You may obtain a copy of the License at
011:
012:              http://www.apache.org/licenses/LICENSE-2.0
013:
014:           Unless required by applicable law or agreed to in writing, software
015:           distributed under the License is distributed on an "AS IS" BASIS,
016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017:           See the License for the specific language governing permissions and
018:           limitations under the License.
019:
020:         */
021:
022:        package org.apache.derby.impl.store.raw.data;
023:
024:        import org.apache.derby.iapi.services.sanity.SanityManager;
025:        import org.apache.derby.iapi.error.StandardException;
026:        import org.apache.derby.iapi.store.raw.ContainerHandle;
027:        import org.apache.derby.iapi.store.raw.xact.RawTransaction;
028:
029:        import org.apache.derby.iapi.services.io.FormatableBitSet;
030:
031:        import java.io.Externalizable;
032:        import java.io.IOException;
033:
034:        import java.io.ObjectOutput;
035:        import java.io.ObjectInput;
036:
037:        /**
038:
039:         An allocation extent row manages the page status of page in the extent.
040:         AllocExtent is externalizable and is written to the AllocPage directly,
041:         without being converted to a row first.
042:         <P>
043:         <PRE>
044:         @format_id	none, format implied by AllocPage's format
045:         @purpose	manage page status of page in extent
046:         @upgrade
047:         @disk_layout
048:         extentOffset(long) the begin physical byte offset of the first page of this extent
049:         extentStart(long) the first logical page mananged by this extent.
050:         extentEnd(long) the last page this extent can ever hope to manage 
051:         extentLength(int) the number of pages allocated in this extent
052:         extentStatus(int) status bits for the whole extent.
053:         HAS_DEALLOCATED - most likely, this extent has a deallocated 
054:         page somewhere
055:         If !HAD_DEALLOCATED, the extent has no deallocated page
056:         HAS_FREE - most likely, this extent has a free page somewhere
057:         If !HAS_FREE, there is no free page in the extent
058:         ALL_FREE - most likely, this extent only has free pages, good 
059:         candidate for shrinking the file.
060:         If !ALL_FREE, the extent is not all free
061:         HAS_UNFILLED_PAGES - most likely, this extent has unfilled pages.
062:         if !HAS_UNFILLED_PAGES, all pages are filled
063:         KEEP_UNFILLED_PAGES - this extent keeps track of unfilled pages
064:         (post v1.3).  If not set, this extent has no notion of
065:         unfilled page and has no unFilledPage bitmap.
066:         NO_DEALLOC_PAGE_MAP - this extents do not have a dealloc and a
067:         free page bit maps.  Prior to 2.0, there are 2 bit
068:         maps, a deallocate page bit map and a free page bit
069:         map.  Cloudscape 2.0 and later merged the dealloc page
070:         bit map into the free page bit map.
071:         RETIRED - this extent contains only 'retired' pages, never use 
072:         any page from this extent.  The pages don't actually 
073:         exist, i.e., it maps to nothing (physicalOffset is 
074:         garbage).  The purpose of this extent is to blot out a 
075:         range of logical page numbers that no longer exists 
076:         for this container.  Use this to reuse a physical page
077:         when a logical page has exhausted all recordId or for
078:         logical pages that has been shrunk out.
079:         preAllocLength(int)  the number of pages that have been preallocated
080:         reserved1(int)
081:         reserved2(long)	reserved for future use
082:         reserved3(long)	reserved for future use
083:         FreePages(bit)	bitmap of free pages
084:         Bit[i] is ON iff page i is free for immediate (re)use.
085:         [
086:         on disk version before 2.0
087:         deAllocPages(bit) bitmap of deallocated pages
088:         Bit[i] is ON iff page i has been deallocated.
089:         ]
090:         unFilledPages(bit)	bitmap of pages that has free space
091:         Bit[i] is ON if page i is likely to be < 1/2 full
092:
093:         org.apache.derby.iapi.services.io.FormatableBitSet is used to store the bit map.  
094:         FormatableBitSet is an externalizable class.
095:
096:         @end_format
097:
098:         <PRE>
099:         A page can have the following logical state:
100:         <BR>Free - a page that is free to be used
101:         <BR>Valid - a page that is currently in use
102:         <P>
103:         There is another type of transitional pages which pages that have been
104:         allocated on disk but has not yet been used.  These pages are Free.
105:         <P>
106:         Bit[K] freePages
107:         Bit[i] is ON iff page i maybe free for reuse.  User must get the
108:         dealloc page lock on the free page to make sure the transaction.
109:         <P>
110:         K is the size of the bit array, it must be >= length.
111:
112:         @see AllocPage
113:         */
114:
115:        public class AllocExtent implements  Externalizable {
116:            private long extentOffset; // begin physical offset
117:            private long extentStart; // first logical page number
118:            private long extentEnd; // last logical page number
119:            // page[extentStart] to page[extentEnd] are the pages in the range of this
120:            // alloc extent.
121:            // page[exentStart] to page[extentStart+extentLength-1] are actually
122:            // allocated in this extent
123:            // when the extent is completely allocated,
124:            // extentEnd == extentStart+extentLength -1
125:
126:            private int extentLength; // number of pages allocated in the extent
127:
128:            int extentStatus;
129:
130:            private int preAllocLength;
131:
132:            private int reserved1;
133:            private long reserved2;
134:            private long reserved3;
135:
136:            // extent Status bits
137:            private static final int HAS_DEALLOCATED = 0x1;
138:            private static final int HAS_FREE = 0x2;
139:            private static final int ALL_FREE = 0x4;
140:            private static final int HAS_UNFILLED_PAGES = 0x10;
141:            private static final int KEEP_UNFILLED_PAGES = 0x10000000;
142:            private static final int NO_DEALLOC_PAGE_MAP = 0x20000000;
143:            private static final int RETIRED = 0x8;
144:
145:            /**
146:            	public Per Page status
147:             */
148:            protected static final int ALLOCATED_PAGE = 0;
149:            protected static final int DEALLOCATED_PAGE = 1;
150:            protected static final int FREE_PAGE = 2;
151:
152:            // a page which is not a freePage is a regular old
153:            // allocated page.  Only an allocated page can be unFilled.
154:            FormatableBitSet freePages;
155:            FormatableBitSet unFilledPages;
156:
157:            /**
158:            	Statically calculates how many pages this extent can manage given the
159:            	availspace number of bytes to store this extent in
160:
161:            	if read/writeExternal changes, this must change too
162:             */
163:            protected static int MAX_RANGE(int availspace) {
164:                /* extent Offset, Start, End, Length, Status, preAllocLength, reserved1,2,3 */
165:                int bookkeeping = 8 /* offset */+ 8 /* start */+ 8 /* end */
166:                        + 4 /* length */+ 4 /* status */+ 4 /* preAllocLength */
167:                        + 4 /* reserved1 */+ 8 /* reserved2 */+ 8 /* reserved3 */;
168:                availspace -= bookkeeping;
169:
170:                // each bit array is allowed to the 1/3 the remaining space
171:                availspace /= 3;
172:
173:                if (availspace <= 0)
174:                    return 0;
175:
176:                // ask bit array how many bits it can store in this amount of space
177:                return FormatableBitSet.maxBitsForSpace(availspace);
178:            }
179:
180:            /*
181:             * methods
182:             */
183:
184:            /*
185:             * ctors
186:             */
187:            protected AllocExtent(long offset, // physical offset
188:                    long start, // starting logical page number
189:                    int length, // how many pages are in this extent
190:                    int pagesize, // size of all the pages in the extent
191:                    int maxlength) // initial size of the bit map arrays
192:            {
193:                if (SanityManager.DEBUG) {
194:                    if (length > maxlength)
195:                        SanityManager.THROWASSERT("length " + length
196:                                + " > maxlength " + maxlength);
197:                }
198:
199:                this .extentOffset = offset;
200:                this .extentStart = start;
201:                this .extentEnd = start + maxlength - 1;
202:
203:                this .extentLength = length;
204:                preAllocLength = extentLength;
205:
206:                if (length > 0)
207:                    extentStatus = HAS_FREE | ALL_FREE;
208:                else
209:                    extentStatus = 0;
210:
211:                extentStatus |= KEEP_UNFILLED_PAGES; // v1.3 or beyond
212:                extentStatus |= NO_DEALLOC_PAGE_MAP; // v2.0 or beyond
213:
214:                int numbits = (1 + (length / 8)) * 8;
215:                if (numbits > maxlength)
216:                    numbits = maxlength;
217:
218:                freePages = new FormatableBitSet(numbits);
219:                unFilledPages = new FormatableBitSet(numbits);
220:
221:                // by definition, all pages are free to begin with, no pages are
222:                // deallocated and no page is unfilled
223:                for (int i = 0; i < length; i++)
224:                    freePages.set(i);
225:            }
226:
227:            /*
228:              Copy constructor
229:             */
230:            protected AllocExtent(AllocExtent original) {
231:                extentOffset = original.extentOffset;
232:                extentStart = original.extentStart;
233:                extentEnd = original.extentEnd;
234:                extentLength = original.extentLength;
235:                extentStatus = original.extentStatus;
236:                preAllocLength = original.preAllocLength;
237:
238:                freePages = new FormatableBitSet(original.freePages);
239:                unFilledPages = new FormatableBitSet(original.unFilledPages);
240:            }
241:
242:            /*
243:             * Methods of Externalizable
244:             */
245:            public AllocExtent() {
246:            }
247:
248:            public void writeExternal(ObjectOutput out) throws IOException {
249:
250:                // any change to this routine must change maxRange
251:                out.writeLong(extentOffset);
252:                out.writeLong(extentStart);
253:                out.writeLong(extentEnd);
254:                out.writeInt(extentLength);
255:                out.writeInt(extentStatus);
256:                out.writeInt(preAllocLength);
257:                out.writeInt(0); // reserved1
258:                out.writeLong(0); // reserved2
259:                out.writeLong(0); // reserved3
260:
261:                freePages.writeExternal(out);
262:                unFilledPages.writeExternal(out);
263:            }
264:
265:            public void readExternal(ObjectInput in) throws IOException,
266:                    ClassNotFoundException {
267:                // any change to this routine must change maxRange
268:                extentOffset = in.readLong();
269:                extentStart = in.readLong();
270:                extentEnd = in.readLong();
271:                extentLength = in.readInt();
272:                extentStatus = in.readInt();
273:                preAllocLength = in.readInt();
274:                reserved1 = in.readInt();
275:                reserved2 = in.readLong();
276:                reserved3 = in.readLong();
277:
278:                freePages = new FormatableBitSet(); // don't know how to point to it
279:                freePages.readExternal(in);
280:
281:                // this extent is created before 2.0
282:                if ((extentStatus & NO_DEALLOC_PAGE_MAP) == 0) {
283:                    FormatableBitSet deAllocPages = new FormatableBitSet();
284:                    deAllocPages.readExternal(in);
285:                    // fold this into free page bit map
286:                    freePages.or(deAllocPages);
287:                    extentStatus |= NO_DEALLOC_PAGE_MAP; // dealloc page map has been merged
288:                }
289:
290:                if ((extentStatus & KEEP_UNFILLED_PAGES) == KEEP_UNFILLED_PAGES) {
291:                    unFilledPages = new FormatableBitSet();
292:                    unFilledPages.readExternal(in);
293:                } else // before we keep track of unfilled pages pre 1.3
294:                {
295:                    // make sure there are enough space
296:                    unFilledPages = new FormatableBitSet(freePages.getLength());
297:                    extentStatus |= KEEP_UNFILLED_PAGES; // now we keep track of them
298:                }
299:
300:            }
301:
302:            /*
303:             * methods specific to allocExtent
304:             */
305:
306:            /*
307:             * write operation that is called underneath the log
308:             *
309:             * page goes thru the following transition:
310:             * ALLOCATED_PAGE <-> deallocated page -> free page <-> ALLOCATED_PAGE
311:             *
312:             */
313:
314:            /**
315:            	Allocate this page - this is called underneath the log record
316:
317:            	@exception StandardException Standard Cloudscape error policy
318:             */
319:            protected void allocPage(long pagenum) throws StandardException {
320:                if (SanityManager.DEBUG) {
321:                    if (pagenum > getLastPagenum()) {
322:                        // adding a brand new page, it should be at most one off from the last page
323:                        if (pagenum > extentEnd)
324:                            SanityManager.THROWASSERT("pagenum " + pagenum
325:                                    + " is out of beyond my range ("
326:                                    + extentStart + "," + extentEnd + ")");
327:                        if (pagenum != getLastPagenum() + 1)
328:                            SanityManager
329:                                    .THROWASSERT("skipping pages, lastPageNumber = "
330:                                            + getLastPagenum()
331:                                            + " pageNumber = " + pagenum + "\n");
332:                    } else {
333:                        // reuseing a page, make sure it is in range and is not already in use
334:                        checkInRange(pagenum);
335:
336:                        int bitnum = (int) (pagenum - extentStart);
337:
338:                        // either the pagenum is now free (do) or deallocated (undo)
339:                        if (!freePages.isSet(bitnum)) {
340:                            SanityManager
341:                                    .THROWASSERT("trying to re-allocate a page ( "
342:                                            + pagenum
343:                                            + " ) that is already allocated ");
344:                        }
345:                    }
346:                }
347:
348:                // don't know if we are redoing (from free -> valid)
349:                // or undoing (from dealloc -> valid), reset them both
350:                int bitnum = (int) (pagenum - extentStart);
351:
352:                if (bitnum >= freePages.getLength()) // expand the bit map
353:                {
354:                    int numbits = (1 + (bitnum / 8)) * 8;
355:                    if (numbits > (int) (extentEnd - extentStart + 1))
356:                        numbits = (int) (extentEnd - extentStart + 1);
357:
358:                    freePages.grow(numbits);
359:                    unFilledPages.grow(numbits);
360:                }
361:
362:                // the first page to be allocated has pagenum == extentStart.
363:                int numPageAlloced = (int) (pagenum - extentStart + 1);
364:
365:                if (numPageAlloced > extentLength) {
366:                    extentLength = numPageAlloced;
367:                }
368:
369:                freePages.clear(bitnum);
370:
371:                // do not set the unfilled bit on a newly allocated page because
372:                // we only keep track of unfilled HEAD page, not unfilled overflow
373:                // page. 
374:            }
375:
376:            /**
377:                Deallocate logical page pagenum - this is called underneath the log record.
378:            	pagenum must be a page managed by this extent and it must be valid
379:
380:            	@exception StandardException Standard Cloudscape error policy
381:             */
382:            protected void deallocPage(long pagenum) throws StandardException {
383:                int bitnum = (int) (pagenum - extentStart);
384:
385:                // the pagenum must now be either valid (do) or free (undo)
386:                if (SanityManager.DEBUG) {
387:                    if (freePages.isSet(bitnum))
388:                        SanityManager
389:                                .THROWASSERT("trying to deallocate a deallocated page "
390:                                        + pagenum);
391:                }
392:
393:                freePages.set(bitnum);
394:                unFilledPages.clear(bitnum); // deallocated page is never unfilled
395:
396:                setExtentFreePageStatus(true);
397:            }
398:
399:            /**
400:             * Compress free pages at end of this extent.
401:             * <p>
402:             * Search backward from end of extent and prepare data structures
403:             * to return pages at end of extent to the OS. Returns the lowest
404:             * page that can be returned to the OS.
405:             * <p>
406:             *
407:             * @return Return bit of page where all pages that follow can
408:             *         be returned to the OS.
409:             **/
410:            protected int compress(BaseContainerHandle owner,
411:                    RawTransaction ntt, AllocPage alloc_page)
412:                    throws StandardException {
413:                int compress_bitnum = -1;
414:                int num_pages_compressed = 0;
415:
416:                for (int i = (extentLength - 1); i >= 0; i--) {
417:                    if (freePages.isSet(i)) {
418:                        compress_bitnum = i;
419:                        num_pages_compressed++;
420:                    } else {
421:                        break;
422:                    }
423:                }
424:
425:                // new_highest_page is the last page to remain in the file after 
426:                // the truncate, the above loop set compress_bitnum to lowest 
427:                // free page in the set of contiguous free pages at end of extent.
428:                int new_highest_page = compress_bitnum - 1;
429:
430:                if (num_pages_compressed > 0) {
431:                    if (SanityManager.DEBUG) {
432:                        for (int i = new_highest_page + 1; i < extentLength; i++) {
433:                            if (!freePages.isSet(i)) {
434:
435:                                SanityManager
436:                                        .THROWASSERT("compressPages with nonfree pg to truncate,"
437:                                                + "new_highest_page = "
438:                                                + new_highest_page
439:                                                + "num_pages_truncated = "
440:                                                + num_pages_compressed
441:                                                + ";extentLength = "
442:                                                + extentLength
443:                                                + ";extentStart = "
444:                                                + extentStart
445:                                                + ";freePages.isSet("
446:                                                + i
447:                                                + ") = "
448:                                                + freePages.isSet(i)
449:                                                + "\nextent:\n"
450:                                                + toDebugString());
451:                            }
452:                        }
453:
454:                        SanityManager.ASSERT((new_highest_page
455:                                + num_pages_compressed + 1) == extentLength,
456:                                "truncate page count did not match: "
457:                                        + ";new_highest_page = "
458:                                        + new_highest_page
459:                                        + ";num_pages_truncated = "
460:                                        + num_pages_compressed
461:                                        + ";extentLength = " + extentLength);
462:
463:                        // the following assert could be made invalid by a new type of
464:                        // access method, but currently page 1 of btree and heap contain
465:                        // control rows, so will never become free and thus should never
466:                        // be compressed.
467:                        if (extentStart == 1) {
468:                            SanityManager.ASSERT(new_highest_page >= 0);
469:
470:                            if (num_pages_compressed >= extentLength) {
471:                                SanityManager.THROWASSERT("new_highest_page = "
472:                                        + new_highest_page
473:                                        + "num_pages_compressed = "
474:                                        + num_pages_compressed
475:                                        + "; extentLength = " + extentLength
476:                                        + "extent:\n" + toDebugString());
477:                            }
478:                        }
479:                    }
480:
481:                    /*
482:                    SanityManager.DEBUG_PRINT("AllocExtent", 
483:                        "calling actionCompressSpaceOperation:" +
484:                        ";new_highest_page = " + new_highest_page +
485:                        ";num_pages_compressed = " +  num_pages_compressed +
486:                        ";extentLength = " +  extentLength +
487:                        ";extent: \n" + toDebugString());
488:                     */
489:
490:                    owner.getAllocationActionSet()
491:                            .actionCompressSpaceOperation(ntt, alloc_page,
492:                                    new_highest_page, num_pages_compressed);
493:                    return (compress_bitnum);
494:                } else {
495:                    return (-1);
496:                }
497:
498:            }
499:
500:            protected void compressPages(int new_highest_page,
501:                    int num_pages_truncated) {
502:                if (SanityManager.DEBUG) {
503:                    if (new_highest_page >= 0) {
504:                        for (int i = new_highest_page + 1; i < extentLength; i++) {
505:                            if (!freePages.isSet(i)) {
506:                                SanityManager
507:                                        .THROWASSERT("compressPages with non free page to truncate,"
508:                                                + "new_highest_page = "
509:                                                + new_highest_page
510:                                                + "num_pages_truncated = "
511:                                                + num_pages_truncated
512:                                                + ";extentLength = "
513:                                                + extentLength
514:                                                + ";extentStart = "
515:                                                + extentStart
516:                                                + ";freePages.isSet("
517:                                                + i
518:                                                + ") = "
519:                                                + freePages.isSet(i)
520:                                                + "\nextent:\n"
521:                                                + toDebugString());
522:                            }
523:                        }
524:                    }
525:
526:                    SanityManager.ASSERT((new_highest_page
527:                            + num_pages_truncated + 1) == extentLength,
528:                            "truncate page count did not match: "
529:                                    + ";new_highest_page = " + new_highest_page
530:                                    + ";num_pages_truncated = "
531:                                    + num_pages_truncated + ";extentLength = "
532:                                    + extentLength);
533:
534:                    // the following assert could be made invalid by a new type of
535:                    // access method, but currently page 1 of btree and heap contain
536:                    // control rows, so will never become free and thus should never
537:                    // be compressed.
538:                    if (extentStart == 1) {
539:                        SanityManager.ASSERT(new_highest_page >= 0);
540:                        SanityManager
541:                                .ASSERT(num_pages_truncated < extentLength);
542:                    }
543:                }
544:
545:                if (new_highest_page >= 0) {
546:                    freePages.shrink(new_highest_page + 1);
547:                    unFilledPages.shrink(new_highest_page + 1);
548:
549:                    // This routine assumes the caller
550:                    // will be doing the truncate, and just updates the data structures.
551:                    preAllocLength = extentLength = (new_highest_page + 1);
552:                }
553:
554:                return;
555:            }
556:
557:            /**
558:             * Undo the compress space operation.
559:             * <p>
560:             * Undo of this operation doesn't really "undo" the operation, it just
561:             * makes sure the data structures are ok after the undo.  We are 
562:             * guaranteed at the point of the transaction doing the 
563:             * Undo of the compress space operation fixes up the bit maps to
564:             * only point at pages within the new_highest_page range.
565:             * <p>
566:             * Prior to logging the compress space operation all pages greater 
567:             * than 
568:             * There are only 2 possibilities at this point:
569:             * 1) the truncate of pages greater than new_highest_page happened before
570:             *    the abort took place.  W
571:             * 2) 
572:             *
573:             * @exception  StandardException  Standard exception policy.
574:             **/
575:            protected void undoCompressPages(int new_highest_page,
576:                    int num_pages_truncated) {
577:                if (new_highest_page >= 0) {
578:                    freePages.shrink(new_highest_page + 1);
579:                    unFilledPages.shrink(new_highest_page + 1);
580:                    preAllocLength = extentLength = (new_highest_page + 1);
581:                }
582:
583:                return;
584:            }
585:
586:            protected long getExtentEnd() {
587:                return extentEnd;
588:            }
589:
590:            /*
591:             * read operation that is called above the log
592:             */
593:
594:            /**
595:            	Get a page number that is free
596:             */
597:            protected long getFreePageNumber(long pnum) {
598:                // if we can reuse page, do so, otherwise add a brand new page
599:                if (mayHaveFreePage()) {
600:                    // The last allocated page may be from a previous alloc extent, but
601:                    // if that extent is full and we are the first extent that can
602:                    // accomodate a new page, we may be picked.  In that case, pnum may
603:                    // be before the start of this extent.
604:                    int i = (pnum < extentStart) ? freePages.anySetBit()
605:                            : freePages.anySetBit((int) (pnum - extentStart));
606:
607:                    if (i != -1) {
608:                        if (SanityManager.DEBUG) {
609:                            if (i >= extentLength)
610:                                SanityManager.THROWASSERT("returned bit = " + i
611:                                        + " extent length = " + extentLength);
612:                        }
613:
614:                        return i + extentStart;
615:                    }
616:
617:                    // the hint is wrong, no free page in the extent
618:                    // do this unlogged, it is just a hint, don't care if it is lost
619:                    if (pnum < extentStart)
620:                        setExtentFreePageStatus(false);
621:                }
622:
623:                // maximally, we can have up to extendEnd page
624:                if (SanityManager.DEBUG)
625:                    SanityManager
626:                            .ASSERT(extentStart + extentLength <= extentEnd);
627:
628:                // need to add a brand new page, current end of extent is at page
629:                // extentStart+extentLength-1;
630:                return extentStart + extentLength;
631:            }
632:
633:            /**
634:            	Get the physical offset of pagenum.
635:            	If deallocOK is true, then even if pagenum is deallocated, it is OK.
636:            	If deallocOK is false, then an exception is thrown if pagenum is
637:            	deallocated.
638:
639:            	An exception is always thrown if pagenum is a free page
640:
641:            	@exception StandardException Standard Cloudscape error policy
642:             */
643:            protected long getPageOffset(long pagenum, int pagesize,
644:                    boolean deallocOK) throws StandardException {
645:                return pagenum * pagesize;
646:            }
647:
648:            /**
649:            	Return the status of this extent
650:             */
651:            protected boolean isRetired() {
652:                return ((extentStatus & RETIRED) != 0);
653:            }
654:
655:            private boolean mayHaveFreePage() {
656:                return ((extentStatus & HAS_FREE) != 0);
657:            }
658:
659:            private void setExtentFreePageStatus(boolean hasFree) {
660:                if (hasFree)
661:                    extentStatus |= HAS_FREE;
662:                else
663:                    extentStatus &= ~HAS_FREE;
664:            }
665:
666:            protected boolean canAddFreePage(long lastAllocatedPage) {
667:                // the last page to be allocated == extentEnd
668:                if (extentStart + extentLength <= extentEnd)
669:                    return true;
670:
671:                // else, check to see if this may have any free page
672:                if (!mayHaveFreePage())
673:                    return false;
674:
675:                // we may have a free page, but that is not certain, double check
676:                if (lastAllocatedPage < extentStart)
677:                    return (freePages.anySetBit() != -1);
678:                else
679:                    return ((freePages
680:                            .anySetBit((int) (lastAllocatedPage - extentStart))) != -1);
681:            }
682:
683:            /**
684:            	Return the status of a particular page
685:             */
686:            protected int getPageStatus(long pagenum) {
687:                if (SanityManager.DEBUG)
688:                    checkInRange(pagenum);
689:
690:                int status = 0;
691:                int bitnum = (int) (pagenum - extentStart);
692:
693:                if (freePages.isSet(bitnum))
694:                    status = FREE_PAGE;
695:                else
696:                    status = ALLOCATED_PAGE;
697:
698:                return status;
699:            }
700:
701:            /**
702:            	Get the first logical page number managed by this extent.
703:             */
704:            protected long getFirstPagenum() {
705:                return extentStart;
706:            }
707:
708:            /**
709:            	Get the last logical page number managed by this extent.
710:             */
711:            protected long getLastPagenum() {
712:                return extentStart + extentLength - 1;
713:            }
714:
715:            /**
716:             * translate bit position in map to page number.
717:             * <p>
718:             *
719:             * @return The page number of this "bit" in the extent map.
720:             *
721:             * @exception  StandardException  Standard exception policy.
722:             **/
723:            protected long getPagenum(int bit_pos) {
724:                return (extentStart + bit_pos);
725:            }
726:
727:            /*
728:             * page preallocation 
729:             */
730:
731:            /**
732:             * get the last preallocated pagenumber managed by this alloc page
733:             */
734:            protected long getLastPreallocPagenum() {
735:                if (extentLength > preAllocLength)
736:                    preAllocLength = extentLength;
737:
738:                return extentStart + preAllocLength - 1;
739:            }
740:
741:            /**
742:            	preallocated N pages, passed in the last preallocated page number.
743:             */
744:            protected void setLastPreallocPagenum(long preAllocPagenum) {
745:                if (SanityManager.DEBUG)
746:                    SanityManager
747:                            .ASSERT(
748:                                    preAllocPagenum >= getLastPreallocPagenum(),
749:                                    "setLastPreallocPagenum set to small prealloc length than before");
750:
751:                // cannot prealloc more than this extent can handle
752:                if (preAllocPagenum > extentEnd)
753:                    preAllocPagenum = extentEnd;
754:
755:                preAllocLength = (int) (preAllocPagenum - extentStart + 1);
756:            }
757:
758:            /*
759:              Get the logical page number that is bigger than prevPageNumber
760:              and is a valid page.  If no such page in this extent, return
761:              ContainerHandle.INVALID_PAGE_HANDLE
762:             */
763:            protected long getNextValidPageNumber(long prevPageNumber) {
764:                long pageNum;
765:                long lastpage = getLastPagenum();
766:
767:                if (prevPageNumber < extentStart)
768:                    pageNum = extentStart;
769:                else
770:                    pageNum = prevPageNumber + 1;
771:
772:                while (pageNum <= lastpage) {
773:                    int status = getPageStatus(pageNum);
774:                    if (status == ALLOCATED_PAGE)
775:                        break;
776:                    pageNum++;
777:                }
778:
779:                if (pageNum > lastpage)
780:                    pageNum = ContainerHandle.INVALID_PAGE_NUMBER;
781:                return pageNum;
782:            }
783:
784:            protected long getLastValidPageNumber() {
785:                long pageNum = getLastPagenum();
786:                while (pageNum >= extentStart) {
787:                    int status = getPageStatus(pageNum);
788:                    if (status == ALLOCATED_PAGE)
789:                        break;
790:                    pageNum--;
791:                }
792:                if (pageNum < extentStart)
793:                    pageNum = ContainerHandle.INVALID_PAGE_NUMBER;
794:                return pageNum;
795:            }
796:
797:            private void checkInRange(long pagenum) {
798:                if (SanityManager.DEBUG)
799:                    if (pagenum < extentStart
800:                            || pagenum >= extentStart + extentLength)
801:                        SanityManager.THROWASSERT("pagenum " + pagenum
802:                                + " out of range");
803:            }
804:
805:            protected void updateUnfilledPageInfo(AllocExtent inputExtent) {
806:                if (SanityManager.DEBUG) {
807:                    if (inputExtent.unFilledPages.getLength() != unFilledPages
808:                            .getLength()) {
809:                        SanityManager
810:                                .THROWASSERT("inputExtent's unfilled page length "
811:                                        + inputExtent.unFilledPages.getLength()
812:                                        + " != extent's unfilled page length "
813:                                        + unFilledPages.getLength());
814:                    }
815:                }
816:
817:                // just use the passed in inputExtent, we know (wink wink) that the
818:                // unfilled page info is being updated just when the allocation cache
819:                // is being invalidated.  Nobody is going to have a reference to the
820:                // inputExtent after this so is it save to share the FormatableBitSet.
821:
822:                // if we cannot guarentee that the inputExtent will be unchanged by the
823:                // caller, we need to copy it 		
824:                //		unFilledPages = new FormatableBitSet(inputExtent.unFilledPages);
825:                // Right now, just reference it directly
826:                unFilledPages = inputExtent.unFilledPages;
827:
828:                if (unFilledPages.anySetBit() >= 0)
829:                    extentStatus |= HAS_UNFILLED_PAGES;
830:                else
831:                    extentStatus &= ~HAS_UNFILLED_PAGES;
832:            }
833:
834:            /*
835:            	Keep track of unfilled pages, if the extent changed, returns true.
836:             */
837:            protected boolean trackUnfilledPage(long pagenumber,
838:                    boolean unfilled) {
839:                checkInRange(pagenumber);
840:
841:                int bitnum = (int) (pagenumber - extentStart);
842:
843:                boolean bitSet = unFilledPages.isSet(bitnum);
844:                if (unfilled != bitSet) {
845:                    if (unfilled) {
846:                        unFilledPages.set(bitnum);
847:                        extentStatus |= HAS_UNFILLED_PAGES;
848:                    } else
849:                        unFilledPages.clear(bitnum);
850:                    return true;
851:                }
852:
853:                return false;
854:            }
855:
856:            /**
857:            	Get a page number that is unfilled, pagenum is the last page that was
858:            	rejected.
859:             */
860:            protected long getUnfilledPageNumber(long pagenum) {
861:                if ((extentStatus & HAS_UNFILLED_PAGES) == 0)
862:                    return ContainerHandle.INVALID_PAGE_NUMBER;
863:
864:                int i = unFilledPages.anySetBit();
865:
866:                if (i != -1) {
867:                    if (i + extentStart != pagenum)
868:                        return i + extentStart;
869:                    else {
870:                        // unfortunately, we found the same page number that
871:                        // was rejected.  It would be unwise to unset bit
872:                        // pagenum because just because it was rejected does not mean
873:                        // the page is full, the row we are trying to insert may just
874:                        // be too big.  If we unset it, we will never find that page
875:                        // again even though it may be a perfectly good page for any
876:                        // other row.  Just get the next set bit.
877:                        i = unFilledPages.anySetBit(i);
878:                        if (i != -1)
879:                            return i + extentStart;
880:                    }
881:                }
882:
883:                return ContainerHandle.INVALID_PAGE_NUMBER;
884:
885:            }
886:
887:            /**
888:            	Get the number of used page in this extent
889:             */
890:            protected int getAllocatedPageCount() {
891:                // allocated page is one which is not free or deallocated.
892:                int allocatedPageCount = extentLength;
893:
894:                if (!mayHaveFreePage())
895:                    return allocatedPageCount;
896:
897:                byte[] free = freePages.getByteArray();
898:                int numBytes = free.length;
899:
900:                for (int i = 0; i < numBytes; i++) {
901:                    if (free[i] != 0) {
902:                        for (int j = 0; j < 8; j++) {
903:                            if (((1 << j) & free[i]) != 0) {
904:                                allocatedPageCount--;
905:                            }
906:                        }
907:                    }
908:                }
909:
910:                if (SanityManager.DEBUG) {
911:                    if (allocatedPageCount < 0) {
912:                        SanityManager
913:                                .THROWASSERT("number of allocated page < 0, val ="
914:                                        + allocatedPageCount
915:                                        + "\nextent = "
916:                                        + toDebugString());
917:                    }
918:                }
919:
920:                return allocatedPageCount;
921:            }
922:
923:            /**
924:            	Get the number of unfilled pages in this extent
925:             */
926:            protected int getUnfilledPageCount() {
927:                int unfilledPageCount = 0;
928:                int freePagesSize = freePages.size();
929:
930:                for (int i = 0; i < unFilledPages.size(); i++) {
931:                    if (unFilledPages.isSet(i)
932:                            && (i >= freePagesSize || !freePages.isSet(i)))
933:                        unfilledPageCount++;
934:                }
935:
936:                if (SanityManager.DEBUG)
937:                    SanityManager.ASSERT(unfilledPageCount >= 0,
938:                            "number of unfilled pages < 0");
939:
940:                return unfilledPageCount;
941:            }
942:
943:            /**
944:            	Get the total number of pages in this extent
945:             */
946:            protected int getTotalPageCount() {
947:                return extentLength;
948:            }
949:
950:            protected String toDebugString() {
951:                if (SanityManager.DEBUG) {
952:                    String str = "------------------------------------------------------------------------------\n"
953:                            + "Extent map of from page "
954:                            + extentStart
955:                            + " to page " + extentEnd + "\n";
956:
957:                    for (long i = extentStart; i < extentStart + extentLength; i++) {
958:                        str += "\tpage " + i + ": ";
959:                        switch (getPageStatus(i)) {
960:                        case FREE_PAGE:
961:                            str += "free page\n";
962:                            break;
963:                        case ALLOCATED_PAGE:
964:                            str += "valid, in use page\n";
965:                            break;
966:                        }
967:
968:                        // int bitnum = (int)(i-extentStart);
969:                        // if (unFilledPages.isSet(bitnum))
970:                        //    str += "          page is estimated to be unfilled\n";
971:                    }
972:
973:                    if (getLastPagenum() < extentEnd)
974:                        str += "\tFrom " + getLastPagenum() + " to "
975:                                + extentEnd + " are un-allocated pages\n";
976:
977:                    str += "------------------------------------------------------------------------------\n";
978:
979:                    return str;
980:                } else
981:                    return null;
982:            }
983:
984:        }
w__w___w.__j_a__va_2__s__._c_om__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.