001    /**
002     * JDBM LICENSE v1.00
003     *
004     * Redistribution and use of this software and associated documentation
005     * ("Software"), with or without modification, are permitted provided
006     * that the following conditions are met:
007     *
008     * 1. Redistributions of source code must retain copyright
009     *    statements and notices.  Redistributions must also contain a
010     *    copy of this document.
011     *
012     * 2. Redistributions in binary form must reproduce the
013     *    above copyright notice, this list of conditions and the
014     *    following disclaimer in the documentation and/or other
015     *    materials provided with the distribution.
016     *
017     * 3. The name "JDBM" must not be used to endorse or promote
018     *    products derived from this Software without prior written
019     *    permission of Cees de Groot.  For written permission,
020     *    please contact cg@cdegroot.com.
021     *
022     * 4. Products derived from this Software may not be called "JDBM"
023     *    nor may "JDBM" appear in their names without prior written
024     *    permission of Cees de Groot. 
025     *
026     * 5. Due credit should be given to the JDBM Project
027     *    (http://jdbm.sourceforge.net/).
028     *
029     * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS
030     * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
031     * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
032     * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
033     * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
034     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
035     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
036     * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
037     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
038     * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
039     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
040     * OF THE POSSIBILITY OF SUCH DAMAGE.
041     *
042     * Copyright 2000 (C) Cees de Groot. All Rights Reserved.
043     * Contributions are Copyright (C) 2000 by their associated contributors.
044     *
045     * $Id: PageHeader.java,v 1.2 2003/09/21 15:47:01 boisvert Exp $
046     */
047    
048    package jdbm.recman;
049    
050    /**
051     *  This class represents a page header. It is the common superclass for
052     *  all different page views.
053     */
054    public class PageHeader implements BlockView {
055        // offsets
056        private static final short O_MAGIC = 0; // short magic
057        private static final short O_NEXT = Magic.SZ_SHORT;  // long next
058        private static final short O_PREV = O_NEXT + Magic.SZ_LONG; // long prev
059        protected static final short SIZE = O_PREV + Magic.SZ_LONG;
060    
061        // my block
062        protected BlockIo block;
063    
064        /**
065         *  Constructs a PageHeader object from a block
066         *
067         *  @param block The block that contains the file header
068         *  @throws IOException if the block is too short to keep the file
069         *          header.
070         */
071        protected PageHeader(BlockIo block) {
072            initialize(block);
073            if (!magicOk())
074                throw new Error("CRITICAL: page header magic for block "
075                                + block.getBlockId() + " not OK "
076                                + getMagic());
077        }
078        
079        /**
080         *  Constructs a new PageHeader of the indicated type. Used for newly
081         *  created pages.
082         */
083        PageHeader(BlockIo block, short type) {
084            initialize(block);
085            setType(type);
086        }
087        
088        /**
089         *  Factory method to create or return a page header for the
090         *  indicated block.
091         */
092        static PageHeader getView(BlockIo block) {
093            BlockView view = block.getView();
094            if (view != null && view instanceof PageHeader)
095                return (PageHeader) view;
096            else
097                return new PageHeader(block);
098        }
099        
100        private void initialize(BlockIo block) {
101            this.block = block;
102            block.setView(this);
103        }
104        
105        /**
106         *  Returns true if the magic corresponds with the fileHeader magic.
107         */
108        private boolean magicOk() {
109            int magic = getMagic();
110            return magic >= Magic.BLOCK
111                && magic <= (Magic.BLOCK + Magic.FREEPHYSIDS_PAGE);
112        }
113        
114        /**
115         *  For paranoia mode
116         */
117        protected void paranoiaMagicOk() {
118            if (!magicOk())
119                throw new Error("CRITICAL: page header magic not OK "
120                                + getMagic());
121        }
122        
123        /** Returns the magic code */
124        short getMagic() {
125            return block.readShort(O_MAGIC);
126        }
127    
128        /** Returns the next block. */
129        long getNext() {
130            paranoiaMagicOk();
131            return block.readLong(O_NEXT);
132        }
133        
134        /** Sets the next block. */
135        void setNext(long next) {
136            paranoiaMagicOk();
137            block.writeLong(O_NEXT, next);
138        }
139        
140        /** Returns the previous block. */
141        long getPrev() {
142            paranoiaMagicOk();
143            return block.readLong(O_PREV);
144        }
145        
146        /** Sets the previous block. */
147        void setPrev(long prev) {
148            paranoiaMagicOk();
149            block.writeLong(O_PREV, prev);
150        }
151        
152        /** Sets the type of the page header */
153        void setType(short type) {
154            block.writeShort(O_MAGIC, (short) (Magic.BLOCK + type));
155        }
156    }