Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / store / raw / data / StoredRecordHeader.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/raw/data/StoredRecordHeader.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/raw/data/StoredRecordHeader.java
new file mode 100644 (file)
index 0000000..10c0605
--- /dev/null
@@ -0,0 +1,784 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.raw.data.StoredRecordHeader\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+package org.apache.derby.impl.store.raw.data;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.store.raw.PageKey;\r
+import org.apache.derby.iapi.store.raw.RecordHandle;\r
+\r
+import java.io.IOException;\r
+import java.io.EOFException;\r
+\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+\r
+import org.apache.derby.iapi.services.io.CompressedNumber;\r
+\r
+/**\r
+       A class StoredPage uses to cache record headers by passing instances\r
+       to BasePage, and to write stored versions of record headers.\r
+\r
+       Format\r
+\r
+       <PRE>\r
+\r
+       1 byte          - status\r
+       compressed int  - record identifier\r
+\r
+       compressed long - overflow page } only if hasOverflow() is true\r
+       compressed int  - overflow id   }     "        "           "\r
+\r
+       compressed int  - first field   } only if hasFirstField set - otherwise 0\r
+\r
+       compressed int  - number of fields in this portion - only if hasOverflow()\r
+                                                               is false OR hasFirstField is true - otherwise 0\r
+       </PRE>\r
+\r
+*/\r
+\r
+public final class StoredRecordHeader\r
+{\r
+\r
+    /**************************************************************************\r
+     * Constants of the class\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Status bits for the record header:\r
+     *\r
+     * RECORD_INITIAL                  - used when record header is first initialized\r
+     * RECORD_DELETED                  - used to indicate the record has been deleted\r
+     * RECORD_OVERFLOW                 - used to indicate the record has been \r
+     *                            overflowed, it will point to the overflow \r
+     *                            page and ID\r
+     * RECORD_HAS_FIRST_FIELD  - used to indicate that firstField is stored. \r
+     *                            When RECORD_OVERFLOW and \r
+     *                            RECORD_HAS_FIRST_FIELD both are set, part of \r
+     *                            record is on the page, the record header \r
+     *                            also stores the overflow point to the next \r
+     *                            part of the record.\r
+     * RECORD_VALID_MASK        - A mask of valid bits that can be set \r
+     *                            currently, such that the following assert can\r
+     *                            be made: \r
+     *                              ASSERT((status & ~RECORD_VALID_MASK) == 0))\r
+     **/\r
+       public static final int RECORD_INITIAL =                        0x00;\r
+       public static final int RECORD_DELETED =                        0x01;\r
+       public static final int RECORD_OVERFLOW =                       0x02;\r
+       public static final int RECORD_HAS_FIRST_FIELD =        0x04; \r
+    public static final int RECORD_VALID_MASK  =        0x0f;\r
+\r
+\r
+    /**************************************************************************\r
+     * Fields of the class\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Actual identifier of the record\r
+     *\r
+     * <BR> MT - Mutable\r
+     **/\r
+       protected int   id;\r
+\r
+    /**\r
+     * Status of the record.\r
+     *\r
+     * See above for description of fields:\r
+     *     RECORD_INITIAL\r
+     *     RECORD_DELETED\r
+     *     RECORD_OVERFLOW\r
+     *     RECORD_HAS_FIRST_FIELD\r
+     *     RECORD_VALID_MASK\r
+     *\r
+     * <BR> MT - Mutable - single thread required.\r
+     **/\r
+       protected int status;\r
+\r
+    /**\r
+     * number of fields in the row.\r
+     **/\r
+       protected int numberFields;\r
+\r
+    /**\r
+     * A record handle that can represent the record, may be null.\r
+     **/\r
+       protected RecordHandle  handle;\r
+\r
+\r
+    /**\r
+     * If (hasOverflow()) then this is the id of the row on page overflowPage\r
+     * where the next portion of the row can be found.  In this case there\r
+     * are no "real" fields on this page.  This situation comes about if a\r
+     * row has been updated such that the real first field no longer fits on\r
+     * the head page.\r
+     **/\r
+       protected int   overflowId;\r
+\r
+\r
+    /**\r
+     * If (hasOverflow()) then this is the page where where the next portion of\r
+     * the row can be found.  In this case there are no "real" fields on this \r
+     * page.\r
+     **/\r
+       protected long  overflowPage;\r
+\r
+    /**\r
+     * if (hasFirstField()) then this field is the number of the column in\r
+     * the orginal row which is now stored as the first field in this row.  This\r
+     * row is 2nd through N'th portion of a long row. \r
+     *\r
+     * For example if a row has its first 3 fields on page 0 and its next 3\r
+     * fields on page 1, then the record header of the row portion on page 1\r
+     * will have hasFirstField() set to true, and the value would be 4, \r
+     * indicating that the 4th field of the row is stored as the 1st field of\r
+     * the partial row portion stored on page 1.\r
+     **/\r
+       protected int   firstField;\r
+\r
+\r
+    /**************************************************************************\r
+     * Constructors for This class:\r
+     **************************************************************************\r
+     */\r
+       public StoredRecordHeader() \r
+    {\r
+       }\r
+\r
+       public StoredRecordHeader(int id, int numberFields) \r
+    {\r
+               setId(id);\r
+               setNumberFields(numberFields);\r
+       }\r
+\r
+       public StoredRecordHeader(\r
+    byte    data[],\r
+    int     offset)\r
+    {\r
+        read(data, offset);\r
+       }\r
+\r
+       public StoredRecordHeader(StoredRecordHeader loadTargetFrom) \r
+    {\r
+               this.status         = loadTargetFrom.status;\r
+               this.id             = loadTargetFrom.id;\r
+               this.numberFields   = loadTargetFrom.numberFields;\r
+               handle              = null;\r
+\r
+               overflowId          = loadTargetFrom.overflowId;\r
+               overflowPage        = loadTargetFrom.overflowPage;\r
+               firstField          = loadTargetFrom.firstField;\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public Accessor "Get" Methods of This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Get a record handle for the record.\r
+     * <p>\r
+     *\r
+     * <BR> MT - single thread required\r
+     **/\r
+       protected RecordHandle getHandle(\r
+    PageKey pageId, \r
+    int current_slot) \r
+    {\r
+               if (handle == null)\r
+                       handle = new RecordId(pageId, id, current_slot);\r
+\r
+               return handle;\r
+       }\r
+\r
+    /**\r
+     * Get the record identifier\r
+     *\r
+     * <BR> MT - thread safe\r
+     **/\r
+       public final int getId() \r
+    {\r
+               return id;\r
+       }\r
+\r
+       public int getNumberFields() \r
+    {\r
+               return numberFields;\r
+       }\r
+\r
+       public long getOverflowPage() \r
+    {\r
+               return overflowPage;\r
+       }\r
+\r
+       public int getOverflowId() \r
+    {\r
+               return overflowId;\r
+       }\r
+\r
+       public int getFirstField() \r
+    {\r
+               return firstField;\r
+       }\r
+\r
+       public final boolean hasOverflow() \r
+    {\r
+               return ((status & RECORD_OVERFLOW) == RECORD_OVERFLOW);\r
+       }\r
+\r
+       protected final boolean hasFirstField() \r
+    {\r
+               return ((status & RECORD_HAS_FIRST_FIELD) == RECORD_HAS_FIRST_FIELD);\r
+       }\r
+\r
+    /**\r
+     * Get the deleted state of the record.\r
+     * <p>\r
+     *\r
+     * <BR> MT - single thread required\r
+     **/\r
+       public final boolean isDeleted() \r
+    {\r
+               return ((status & RECORD_DELETED) == RECORD_DELETED);\r
+       }\r
+\r
+\r
+    /**\r
+     * return the size of the record header.\r
+     * <p>\r
+     * Calculates the size of the record header, mostly used to allow a\r
+     * reader to skip over the record header and position on the 1st field\r
+     * of the record.\r
+     * <p>\r
+     * This low level routine is performance critical to processing lots of\r
+     * rows, so calls to CompressNumber have been hand inlined.\r
+     *\r
+        * @return The length of the record header.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public int size() \r
+    {\r
+        // account for length of fieldDataLength field stored as a compressed\r
+        // int plus one byte for status.  \r
+        //\r
+        //    int len = CompressedNumber.sizeInt(id) + 1;\r
+        int len = \r
+          (id <= CompressedNumber.MAX_COMPRESSED_INT_ONE_BYTE) ?\r
+              2 : \r
+          (id <= CompressedNumber.MAX_COMPRESSED_INT_TWO_BYTES) ?\r
+              3 : 5;\r
+\r
+        if ((status & (RECORD_OVERFLOW | RECORD_HAS_FIRST_FIELD)) == 0)\r
+        {\r
+            // usual case, not a record overflow and does not have first field\r
+            len += \r
+              (numberFields <= CompressedNumber.MAX_COMPRESSED_INT_ONE_BYTE) ?\r
+                  1 : \r
+              (numberFields <= CompressedNumber.MAX_COMPRESSED_INT_TWO_BYTES) ?\r
+                  2 : 4;\r
+        }\r
+        else if ((status & RECORD_OVERFLOW) == 0)\r
+        {\r
+            // not overflow, and has first field set.\r
+\r
+            // account for size of the numberFields field + size fo the \r
+            // firstField field.\r
+            //\r
+            //     len += (CompressedNumber.sizeInt(numberFields) +\r
+            //             CompressedNumber.sizeInt(firstField);\r
+            //\r
+            len += \r
+              ((numberFields <= CompressedNumber.MAX_COMPRESSED_INT_ONE_BYTE) ?\r
+                  1 : \r
+               (numberFields <= CompressedNumber.MAX_COMPRESSED_INT_TWO_BYTES) ?\r
+                  2 : 4) +\r
+\r
+              ((firstField <= CompressedNumber.MAX_COMPRESSED_INT_ONE_BYTE) ?\r
+                  1 : \r
+               (firstField <= CompressedNumber.MAX_COMPRESSED_INT_TWO_BYTES) ?\r
+                  2 : 4);\r
+        }\r
+        else\r
+        {\r
+            // is an overflow field\r
+\r
+                       len += CompressedNumber.sizeLong(overflowPage);\r
+                       len += CompressedNumber.sizeInt(overflowId);\r
+\r
+            if (hasFirstField())\r
+            {\r
+                len += CompressedNumber.sizeInt(firstField);\r
+                len += CompressedNumber.sizeInt(numberFields);\r
+            }\r
+               }\r
+\r
+               return len;\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public Accessor "Set" Methods of This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Set the deleted state of the record.\r
+     * <p>\r
+     * return  1, if delete status from not deleted to deleted\r
+     * return  -1, if delete status from deleted to not deleted\r
+     * return   0, if status unchanged.\r
+     *\r
+     * <BR> MT - single thread required\r
+     **/\r
+       public int setDeleted(boolean deleteTrue) \r
+    {\r
+\r
+               int retCode = 0;\r
+\r
+               if (deleteTrue) \r
+        {\r
+                       if (!isDeleted()) \r
+            {\r
+                               // setting the bit from not deleted to deleted\r
+                               retCode = 1;\r
+                               status |= RECORD_DELETED;\r
+                       }\r
+               } \r
+        else \r
+        {\r
+                       if (isDeleted()) \r
+            {\r
+                               // setting the bit from deleted to not deleted\r
+                               retCode = -1;\r
+                               status &= ~RECORD_DELETED;\r
+                       }\r
+               }\r
+\r
+               return(retCode);\r
+       }\r
+\r
+       public void setFirstField(int firstField) \r
+    {\r
+               this.firstField = firstField;\r
+        status |= RECORD_HAS_FIRST_FIELD;\r
+       }\r
+\r
+       public final void setId(int id) \r
+    {\r
+               this.id = id;\r
+       }\r
+\r
+       public void setOverflowDetails(RecordHandle overflowHandle) \r
+    {\r
+               this.overflowPage   = overflowHandle.getPageNumber();\r
+               this.overflowId     = overflowHandle.getId();\r
+       }\r
+\r
+    public void setOverflowFields(StoredRecordHeader loadFromTarget)\r
+    {\r
+               this.status         = (loadFromTarget.status | RECORD_OVERFLOW);\r
+               this.id             = loadFromTarget.id;\r
+               this.numberFields   = loadFromTarget.numberFields;\r
+        this.firstField     = loadFromTarget.firstField;\r
+               handle              = null;\r
+    }\r
+\r
+\r
+       public final void setNumberFields(int numberFields) \r
+    {\r
+               this.numberFields = numberFields;\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public Methods implmenting read/write of Storable Interface:\r
+     **************************************************************************\r
+     */\r
+       public int write(OutputStream out) \r
+        throws IOException \r
+    {\r
+        // check consistency of the status field - this has caught\r
+        // byte writing corruptions in StoredPage in the past.\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            if ((status & ~RECORD_VALID_MASK) != 0)\r
+               SanityManager.THROWASSERT(\r
+                       "Invalid status in StoredRecordHeaader = " + status);\r
+        }\r
+\r
+        // write status\r
+               int len = 1;\r
+               out.write(status);\r
+\r
+        // write id\r
+               len += CompressedNumber.writeInt(out, id);\r
+               \r
+\r
+        // write overflow information for overflow record headers\r
+               if (hasOverflow()) \r
+        {\r
+                       // if overflow bit is set, then write the overflow pointer info.\r
+                       len += CompressedNumber.writeLong(out, overflowPage);\r
+                       len += CompressedNumber.writeInt(out, overflowId);\r
+               }\r
+\r
+        // write first field info for long row parts\r
+               if (hasFirstField()) \r
+        {\r
+                       len += CompressedNumber.writeInt(out, firstField);\r
+               }\r
+\r
+        // write number of fields, except in the case of a record header\r
+        // which is solely a pointer to another row portion.\r
+        //\r
+               // see read\r
+               if (!hasOverflow() || hasFirstField())\r
+                       len += CompressedNumber.writeInt(out, numberFields);\r
+\r
+               return len;\r
+       }\r
+\r
+       public void read(java.io.ObjectInput in) \r
+        throws IOException \r
+    {\r
+\r
+        // read status\r
+               status = in.read();\r
+               if (status < 0)\r
+                       throw new EOFException();\r
+\r
+        // check consistency of the status field - this has caught\r
+        // byte writing corruptions in StoredPage in the past.\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            if ((status & ~RECORD_VALID_MASK) != 0)\r
+               SanityManager.THROWASSERT(\r
+                       "Invalid status in StoredRecordHeader = " + status);\r
+        }\r
+\r
+        // read the record id\r
+               id = CompressedNumber.readInt(in);\r
+\r
+        // initialize the overflow pointer based on status.\r
+               if (hasOverflow()) \r
+        {\r
+                       overflowPage = CompressedNumber.readLong(in);\r
+                       overflowId   = CompressedNumber.readInt(in);\r
+\r
+               } \r
+        else \r
+        {\r
+                       overflowPage = 0;\r
+                       overflowId   = 0;\r
+               }\r
+\r
+        // initialize the 1st field overflow pointer based on status.\r
+               if (hasFirstField()) \r
+        {\r
+                       firstField = CompressedNumber.readInt(in);\r
+               } \r
+        else \r
+        {\r
+                       firstField = 0;\r
+               }\r
+       \r
+               // In releases prior to 1.3 an overflow record was handled\r
+               // by an overflow header pointing to a complete record on\r
+               // another page. This header had the has overflow bit set but not\r
+               // the has first field bit. This header also did not have the\r
+               // number of fields written out, but it can be seen as\r
+               // a header with 0 fields and a first field of 0.\r
+               if (!hasOverflow() || hasFirstField())\r
+                       numberFields = CompressedNumber.readInt(in);\r
+               else\r
+                       numberFields = 0;\r
+\r
+               handle = null;\r
+       }\r
+\r
+    private int readId(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+               int value = data[offset++];\r
+\r
+        if ((value & ~0x3f) == 0)\r
+        {\r
+            // value stored in this byte.\r
+            id = value;\r
+\r
+            return(1);\r
+        }\r
+               else if ((value & 0x80) == 0)\r
+               {\r
+            // value is stored in 2 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            id = (((value & 0x3f) << 8) | (data[offset] & 0xff));\r
+\r
+            return(2);\r
+               }\r
+        else\r
+        {\r
+            // value is stored in 4 bytes.  only use low 7 bits from 1st byte.\r
+            id = \r
+                ((value          & 0x7f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset]   & 0xff)      );\r
+\r
+            return(4);\r
+        }\r
+    }\r
+    private int readOverFlowPage(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+               int int_value = data[offset++];\r
+\r
+        if ((int_value & ~0x3f) == 0)\r
+        {\r
+            // test for small case first - assuming this is usual case.\r
+            // this is stored in 2 bytes.\r
+\r
+            overflowPage = ((int_value << 8) | (data[offset] & 0xff));\r
+\r
+            return(2);\r
+               }\r
+               else if ((int_value & 0x80) == 0)\r
+               {\r
+            // value is stored in 4 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            overflowPage = \r
+                ((int_value      & 0x3f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset]   & 0xff)      );\r
+\r
+            return(4);\r
+\r
+               } \r
+        else\r
+               {\r
+            // value is stored in 8 bytes.  only use low 6 bits from 1st byte.\r
+            overflowPage = \r
+                (((long) (int_value      & 0x7f)) << 56) |\r
+                (((long) (data[offset++] & 0xff)) << 48) |\r
+                (((long) (data[offset++] & 0xff)) << 40) |\r
+                (((long) (data[offset++] & 0xff)) << 32) |\r
+                (((long) (data[offset++] & 0xff)) << 24) |\r
+                (((long) (data[offset++] & 0xff)) << 16) |\r
+                (((long) (data[offset++] & 0xff)) <<  8) |\r
+                (((long) (data[offset]   & 0xff))      );\r
+\r
+            return(8);\r
+               }\r
+    }\r
+    private int readOverFlowId(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+               int value = data[offset++];\r
+\r
+        if ((value & ~0x3f) == 0)\r
+        {\r
+            // length stored in this byte.\r
+            overflowId = value;\r
+\r
+            return(1);\r
+        }\r
+               else if ((value & 0x80) == 0)\r
+               {\r
+            // length is stored in 2 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            overflowId = (((value & 0x3f) << 8) | (data[offset] & 0xff));\r
+\r
+            return(2);\r
+               }\r
+        else\r
+        {\r
+            // length is stored in 4 bytes.  only use low 7 bits from 1st byte.\r
+            overflowId = \r
+                ((value          & 0x7f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset]   & 0xff)      );\r
+\r
+            return(4);\r
+        }\r
+    }\r
+    private int readFirstField(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+               int value = data[offset++];\r
+\r
+        if ((value & ~0x3f) == 0)\r
+        {\r
+            // length stored in this byte.\r
+            firstField = value;\r
+\r
+            return(1);\r
+        }\r
+               else if ((value & 0x80) == 0)\r
+               {\r
+            // length is stored in 2 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            firstField = (((value & 0x3f) << 8) | (data[offset] & 0xff));\r
+\r
+            return(2);\r
+               }\r
+        else\r
+        {\r
+            // length is stored in 4 bytes.  only use low 7 bits from 1st byte.\r
+            firstField = \r
+                ((value          & 0x7f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset]   & 0xff)      );\r
+\r
+            return(4);\r
+        }\r
+    }\r
+    private void readNumberFields(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+               int value = data[offset++];\r
+\r
+        if ((value & ~0x3f) == 0)\r
+        {\r
+            // length stored in this byte.\r
+            numberFields = value;\r
+        }\r
+               else if ((value & 0x80) == 0)\r
+               {\r
+            // length is stored in 2 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            numberFields = (((value & 0x3f) << 8) | (data[offset] & 0xff));\r
+               }\r
+        else\r
+        {\r
+            // length is stored in 4 bytes.  only use low 7 bits from 1st byte.\r
+            numberFields = \r
+                ((value          & 0x7f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset]   & 0xff)      );\r
+        }\r
+    }\r
+\r
+\r
+       private void read(\r
+    byte[]  data,\r
+    int     offset)\r
+    {\r
+        status = data[offset++];\r
+\r
+               int value = data[offset++];\r
+\r
+        if ((value & ~0x3f) == 0)\r
+        {\r
+            // value stored in this byte.\r
+            id = value;\r
+        }\r
+               else if ((value & 0x80) == 0)\r
+               {\r
+            // value is stored in 2 bytes.  only use low 6 bits from 1st byte.\r
+\r
+            id = (((value & 0x3f) << 8) | (data[offset++] & 0xff));\r
+               }\r
+        else\r
+        {\r
+            // value is stored in 4 bytes.  only use low 7 bits from 1st byte.\r
+            id = \r
+                ((value          & 0x7f) << 24) |\r
+                ((data[offset++] & 0xff) << 16) |\r
+                ((data[offset++] & 0xff) <<  8) |\r
+                ((data[offset++] & 0xff)      );\r
+        }\r
+\r
+        if ((status & (RECORD_OVERFLOW | RECORD_HAS_FIRST_FIELD)) == 0)\r
+        {\r
+            // usual case, not a record overflow and does not have first field\r
+                       overflowPage = 0;\r
+                       overflowId   = 0;\r
+            firstField   = 0;\r
+\r
+            readNumberFields(data, offset);\r
+        }\r
+        else if ((status & RECORD_OVERFLOW) == 0)\r
+        {\r
+            // not overflow, and has first field set.\r
+                       overflowPage = 0;\r
+                       overflowId   = 0;\r
+\r
+            offset += readFirstField(data, offset);\r
+\r
+            readNumberFields(data, offset);\r
+        }\r
+        else\r
+        {\r
+            // is an overflow field\r
+\r
+            offset += readOverFlowPage(data, offset);\r
+            offset += readOverFlowId(data, offset);\r
+\r
+            if (hasFirstField())\r
+            {\r
+                offset += readFirstField(data, offset);\r
+                readNumberFields(data, offset);\r
+            }\r
+            else\r
+            {\r
+                firstField   = 0;\r
+                numberFields = 0;\r
+            }\r
+               }\r
+\r
+        handle = null;\r
+\r
+        return;\r
+       }\r
+\r
+\r
+       public String toString()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       String str = "recordHeader: Id=" + getId();\r
+                       \r
+                       str += "\n  isDeleted     = " + isDeleted();\r
+                       str += "\n  hasOverflow   = " + hasOverflow();\r
+                       str += "\n  hasFirstField = " + hasFirstField();\r
+                       str += "\n  numberFields  = " + getNumberFields();\r
+                       str += "\n  firstField    = " + getFirstField();\r
+                       str += "\n  overflowPage  = " + getOverflowPage();\r
+                       str += "\n  overflowId    = " + getOverflowId();\r
+\r
+                       return str;\r
+               }\r
+               else\r
+        {\r
+                       return null;\r
+        }\r
+       }\r
+}\r