--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.store.access.btree.BranchRow\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
+\r
+package org.apache.derby.impl.store.access.btree;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.store.access.RowUtil;\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+import org.apache.derby.iapi.types.SQLLongint;\r
+\r
+/**\r
+ * Implements row which is stored in the branch pages of a btree. A non-suffix\r
+ * compressed branch row contains all of the columns of the leaf rows of a btree\r
+ * and contains an additional field at the end. The extra field of a branch row\r
+ * in a branch page at level N, is the child page field pointing the page at \r
+ * level N-1 which has keys which follow or equal the branch row entry.\r
+ *\r
+ * There are 3 ways to use this class to produce a branch row:\r
+ * createEmptyTemplate() \r
+ * creates a empty row template\r
+ * createBranchRowFromOldBranchRow() \r
+ * creates a new row with reference to an old branch row.\r
+ * createBranchRowFromOldLeafRow()\r
+ * creates a new row with reference to an old leaf row.\r
+ */\r
+\r
+public class BranchRow\r
+{\r
+ /* a dummy page number value (should not be compressable) */\r
+ public static final long DUMMY_PAGE_NUMBER = 0xffffffffffffffffL;\r
+\r
+ /**\r
+ * The branch child page pointer. All keys that Follow or equal the\r
+ * key in this row can be found by following the child page pointer.\r
+ * A reference to this object will be placed in the last slot of branchrow,\r
+ * and this class expects that no-one will replace that reference.\r
+ */\r
+ // private SQLLongint child_page = null;\r
+\r
+ /**\r
+ * The array of object to be used as the row.\r
+ */\r
+ private DataValueDescriptor[] branchrow = null;\r
+\r
+ /*\r
+ ** Constructors of BranchRow\r
+ */\r
+\r
+ /**\r
+ Constuctor for creating an "empty" BranchRow template, suitable for reading\r
+ in a branchRow from disk.\r
+ **/\r
+ private BranchRow()\r
+ {\r
+ }\r
+\r
+ private BranchRow(\r
+ Transaction rawtran,\r
+ BTree btree)\r
+ throws StandardException\r
+ {\r
+ SQLLongint child_page = \r
+ new SQLLongint(ContainerHandle.INVALID_PAGE_NUMBER);\r
+\r
+ branchrow = btree.createBranchTemplate(rawtran, child_page);\r
+\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(\r
+ child_page == ((SQLLongint) branchrow[branchrow.length - 1]));\r
+ }\r
+ }\r
+\r
+ /*\r
+ ** The following methods implement the BranchRow Private interface.\r
+ */\r
+\r
+ /**\r
+ * Accessor for the child page field of the branch row.\r
+ *\r
+ * @return The child page object.\r
+ **/\r
+ private SQLLongint getChildPage()\r
+ {\r
+ // last column of branch row should be the child page pointer.\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT(branchrow != null);\r
+ SanityManager.ASSERT(\r
+ branchrow[branchrow.length - 1] instanceof SQLLongint);\r
+ }\r
+\r
+ return((SQLLongint) branchrow[branchrow.length - 1]);\r
+ }\r
+\r
+ /*\r
+ ** The following methods implement the BranchRow Public interface.\r
+ */\r
+\r
+ /**\r
+ * Create an empty branch row template suitable for reading branch rows in\r
+ * from disk. This routine will create newly allocated "empty" objects for\r
+ * every column in the template row.\r
+ *\r
+ * @exception StandardException Standard exception policy.\r
+ */\r
+ public static BranchRow createEmptyTemplate(\r
+ Transaction rawtran,\r
+ BTree btree)\r
+ throws StandardException\r
+ {\r
+ return(new BranchRow(rawtran, btree));\r
+ }\r
+\r
+ /**\r
+ * Create a new branch row, given a old branch row and a new child page.\r
+ * Used by BranchControlRow to manufacture new branch rows when splitting\r
+ * or growing the tree.\r
+ *\r
+ * There is no way to "copy" values of a template row, so this class just\r
+ * stores a reference to each of the columns of the Indexable row passed \r
+ * in. This is ok as all\r
+ * usages of this class when instantiated this way, have an old branch row\r
+ * from which they are creating a new branch row with the same key values,\r
+ * and a different child page number.\r
+ *\r
+ * WARNING - this branch row is only valid while the old branch row is\r
+ * valid, as it contains references to the columns of the old branch row.\r
+ * So use of the row should only provide read-only access to the objects\r
+ * of the old branch row which are referenced.\r
+ */\r
+ public BranchRow createBranchRowFromOldBranchRow(long childpageno)\r
+ {\r
+ BranchRow newbranch = new BranchRow();\r
+\r
+ /* create new object array, and shallow copy all object references \r
+ * from old branch row to new branch row.\r
+ */\r
+\r
+ newbranch.branchrow = new DataValueDescriptor[this.branchrow.length]; \r
+ System.arraycopy(\r
+ this.branchrow, 0, newbranch.branchrow, 0, \r
+ newbranch.branchrow.length - 1);\r
+\r
+ /* now create a different child page pointer object and place it as\r
+ * last column in the new branch row.\r
+ */\r
+ newbranch.branchrow[newbranch.branchrow.length - 1] = \r
+ new SQLLongint(childpageno);\r
+\r
+ return(newbranch);\r
+ }\r
+\r
+ /**\r
+ * Create a new branch row, given a old leaf row and a new child page.\r
+ * Used by LeafControlRow to manufacture new branch rows when splitting\r
+ * or growing the tree.\r
+ *\r
+ * There is no way to "copy" values of a template row, so this class just\r
+ * stores a referece to the Indexable row passed in. This is ok as all\r
+ * usages of this class when instantiated this way, have an old leaf row\r
+ * from which they are creating a new branch row with the same key values,\r
+ * and a different child page number.\r
+ *\r
+ * WARNING - this branch row is only valid while the old leaf row is\r
+ * valid, as it contains references to the columns of the old leaf row.\r
+ * So use of the row should only provide read-only access to the objects\r
+ * of the old leaf row which are referenced.\r
+ */\r
+ public static BranchRow createBranchRowFromOldLeafRow(\r
+ DataValueDescriptor[] leafrow, \r
+ long childpageno)\r
+ {\r
+ BranchRow newbranch = new BranchRow();\r
+\r
+ /* create new object array for the row, and copy all object references \r
+ * from old leaf row to new branch row.\r
+ */\r
+ newbranch.branchrow = new DataValueDescriptor[leafrow.length + 1];\r
+\r
+ System.arraycopy(leafrow, 0, newbranch.branchrow, 0, leafrow.length);\r
+\r
+ /* now create a different child page pointer object and place it as\r
+ * last column in the new branch row.\r
+ */\r
+ newbranch.branchrow[newbranch.branchrow.length - 1] = \r
+ new SQLLongint(childpageno);\r
+\r
+ return(newbranch);\r
+ }\r
+\r
+ /**\r
+ * Return the branch row.\r
+ * <p>\r
+ * Return the DataValueDescriptor array that represents the branch row, \r
+ * for use in raw store calls to fetch, insert, and update.\r
+ * <p>\r
+ *\r
+ * @return The branch row object array.\r
+ **/\r
+ protected DataValueDescriptor[] getRow()\r
+ {\r
+ return(this.branchrow);\r
+ }\r
+\r
+ /**\r
+ * Set the page number field of the branch row to a new value.\r
+ *\r
+ * @param page_number the new page number.\r
+ **/\r
+ protected void setPageNumber(long page_number)\r
+ {\r
+ getChildPage().setValue(page_number);\r
+ }\r
+\r
+\r
+ public String toString()\r
+ {\r
+ if (SanityManager.DEBUG)\r
+ {\r
+ return(\r
+ RowUtil.toString(branchrow) + \r
+ "child page: (" + getChildPage() + ")");\r
+ }\r
+ else\r
+ {\r
+ return(null);\r
+ }\r
+ }\r
+}\r