001: /*
002:
003: Derby - Class org.apache.derby.impl.store.access.btree.BranchRow
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.access.btree;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025: import org.apache.derby.iapi.services.io.Storable;
026:
027: import org.apache.derby.iapi.error.StandardException;
028:
029: import org.apache.derby.iapi.store.access.RowUtil;
030:
031: import org.apache.derby.iapi.store.raw.ContainerHandle;
032:
033: import org.apache.derby.iapi.types.DataValueDescriptor;
034:
035: import org.apache.derby.iapi.types.SQLLongint;
036: import org.apache.derby.iapi.services.io.FormatableBitSet;
037:
038: /**
039: * Implements row which is stored in the branch pages of a btree. A non-suffix
040: * compressed branch row contains all of the columns of the leaf rows of a btree
041: * and contains an additional field at the end. The extra field of a branch row
042: * in a branch page at level N, is the child page field pointing the page at
043: * level N-1 which has keys which follow or equal the branch row entry.
044: *
045: * There are 3 ways to use this class to produce a branch row:
046: * createEmptyTemplate()
047: * creates a empty row template
048: * createBranchRowFromOldBranchRow()
049: * creates a new row with reference to an old branch row.
050: * createBranchRowFromOldLeafRow()
051: * creates a new row with reference to an old leaf row.
052: */
053:
054: public class BranchRow {
055: /* a dummy page number value (should not be compressable) */
056: public static final long DUMMY_PAGE_NUMBER = 0xffffffffffffffffL;
057:
058: /**
059: * The branch child page pointer. All keys that Follow or equal the
060: * key in this row can be found by following the child page pointer.
061: * A reference to this object will be placed in the last slot of branchrow,
062: * and this class expects that no-one will replace that reference.
063: */
064: // private SQLLongint child_page = null;
065: /**
066: * The array of object to be used as the row.
067: */
068: private DataValueDescriptor[] branchrow = null;
069:
070: /*
071: ** Constructors of BranchRow
072: */
073:
074: /**
075: Constuctor for creating an "empty" BranchRow template, suitable for reading
076: in a branchRow from disk.
077: **/
078: private BranchRow() {
079: }
080:
081: private BranchRow(BTree btree) throws StandardException {
082: SQLLongint child_page = new SQLLongint(
083: ContainerHandle.INVALID_PAGE_NUMBER);
084:
085: branchrow = btree.createBranchTemplate(child_page);
086:
087: if (SanityManager.DEBUG) {
088: SanityManager
089: .ASSERT(child_page == ((SQLLongint) branchrow[branchrow.length - 1]));
090: }
091: }
092:
093: /*
094: ** The following methods implement the BranchRow Private interface.
095: */
096:
097: /**
098: * Accessor for the child page field of the branch row.
099: *
100: * @return The child page object.
101: **/
102: private SQLLongint getChildPage() {
103: // last column of branch row should be the child page pointer.
104: if (SanityManager.DEBUG) {
105: SanityManager.ASSERT(branchrow != null);
106: SanityManager
107: .ASSERT(branchrow[branchrow.length - 1] instanceof SQLLongint);
108: }
109:
110: return ((SQLLongint) branchrow[branchrow.length - 1]);
111: }
112:
113: /*
114: ** The following methods implement the BranchRow Public interface.
115: */
116:
117: /**
118: * Create an empty branch row template suitable for reading branch rows in
119: * from disk. This routine will create newly allocated "empty" objects for
120: * every column in the template row.
121: *
122: * @exception StandardException Standard exception policy.
123: */
124: public static BranchRow createEmptyTemplate(BTree btree)
125: throws StandardException {
126: BranchRow newbranch = new BranchRow(btree);
127:
128: return (new BranchRow(btree));
129: }
130:
131: /**
132: * Create a new branch row, given a old branch row and a new child page.
133: * Used by BranchControlRow to manufacture new branch rows when splitting
134: * or growing the tree.
135: *
136: * There is no way to "copy" values of a template row, so this class just
137: * stores a reference to each of the columns of the Indexable row passed
138: * in. This is ok as all
139: * usages of this class when instantiated this way, have an old branch row
140: * from which they are creating a new branch row with the same key values,
141: * and a different child page number.
142: *
143: * WARNING - this branch row is only valid while the old branch row is
144: * valid, as it contains references to the columns of the old branch row.
145: * So use of the row should only provide read-only access to the objects
146: * of the old branch row which are referenced.
147: */
148: public BranchRow createBranchRowFromOldBranchRow(long childpageno) {
149: BranchRow newbranch = new BranchRow();
150:
151: /* create new object array, and shallow copy all object references
152: * from old branch row to new branch row.
153: */
154:
155: newbranch.branchrow = new DataValueDescriptor[this .branchrow.length];
156: System.arraycopy(this .branchrow, 0, newbranch.branchrow, 0,
157: newbranch.branchrow.length - 1);
158:
159: /* now create a different child page pointer object and place it as
160: * last column in the new branch row.
161: */
162: newbranch.branchrow[newbranch.branchrow.length - 1] = new SQLLongint(
163: childpageno);
164:
165: return (newbranch);
166: }
167:
168: /**
169: * Create a new branch row, given a old leaf row and a new child page.
170: * Used by LeafControlRow to manufacture new branch rows when splitting
171: * or growing the tree.
172: *
173: * There is no way to "copy" values of a template row, so this class just
174: * stores a referece to the Indexable row passed in. This is ok as all
175: * usages of this class when instantiated this way, have an old leaf row
176: * from which they are creating a new branch row with the same key values,
177: * and a different child page number.
178: *
179: * WARNING - this branch row is only valid while the old leaf row is
180: * valid, as it contains references to the columns of the old leaf row.
181: * So use of the row should only provide read-only access to the objects
182: * of the old leaf row which are referenced.
183: */
184: public static BranchRow createBranchRowFromOldLeafRow(
185: DataValueDescriptor[] leafrow, long childpageno) {
186: BranchRow newbranch = new BranchRow();
187:
188: /* create new object array for the row, and copy all object references
189: * from old leaf row to new branch row.
190: */
191: newbranch.branchrow = new DataValueDescriptor[leafrow.length + 1];
192:
193: System.arraycopy(leafrow, 0, newbranch.branchrow, 0,
194: leafrow.length);
195:
196: /* now create a different child page pointer object and place it as
197: * last column in the new branch row.
198: */
199: newbranch.branchrow[newbranch.branchrow.length - 1] = new SQLLongint(
200: childpageno);
201:
202: return (newbranch);
203: }
204:
205: /**
206: * Return the branch row.
207: * <p>
208: * Return the DataValueDescriptor array that represents the branch row,
209: * for use in raw store calls to fetch, insert, and update.
210: * <p>
211: *
212: * @return The branch row object array.
213: **/
214: protected DataValueDescriptor[] getRow() {
215: return (this .branchrow);
216: }
217:
218: /**
219: * Set the page number field of the branch row to a new value.
220: *
221: * @param page_number the new page number.
222: **/
223: protected void setPageNumber(long page_number) {
224: getChildPage().setValue(page_number);
225: }
226:
227: public String toString() {
228: if (SanityManager.DEBUG) {
229: return (RowUtil.toString(branchrow) + "child page: ("
230: + getChildPage() + ")");
231: } else {
232: return (null);
233: }
234: }
235: }
|