Source code: org/apache/derby/impl/store/access/btree/BranchRow.java
1 /*
2
3 Derby - Class org.apache.derby.impl.store.access.btree.BranchRow
4
5 Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
18
19 */
20
21 package org.apache.derby.impl.store.access.btree;
22
23 import org.apache.derby.iapi.services.sanity.SanityManager;
24 import org.apache.derby.iapi.services.io.Storable;
25
26 import org.apache.derby.iapi.error.StandardException;
27
28 import org.apache.derby.iapi.store.access.RowUtil;
29
30 import org.apache.derby.iapi.store.raw.ContainerHandle;
31
32 import org.apache.derby.iapi.types.DataValueDescriptor;
33
34 import org.apache.derby.iapi.types.SQLLongint;
35 import org.apache.derby.iapi.services.io.FormatableBitSet;
36
37
38 /**
39 * Implements row which is stored in the branch pages of a btree. A non-suffix
40 * compressed branch row contains all of the columns of the leaf rows of a btree
41 * and contains an additional field at the end. The extra field of a branch row
42 * in a branch page at level N, is the child page field pointing the page at
43 * level N-1 which has keys which follow or equal the branch row entry.
44 *
45 * There are 3 ways to use this class to produce a branch row:
46 * createEmptyTemplate()
47 * creates a empty row template
48 * createBranchRowFromOldBranchRow()
49 * creates a new row with reference to an old branch row.
50 * createBranchRowFromOldLeafRow()
51 * creates a new row with reference to an old leaf row.
52 */
53
54 public class BranchRow
55 {
56 /* a dummy page number value (should not be compressable) */
57 public static final long DUMMY_PAGE_NUMBER = 0xffffffffffffffffL;
58
59 /**
60 * The branch child page pointer. All keys that Follow or equal the
61 * key in this row can be found by following the child page pointer.
62 * A reference to this object will be placed in the last slot of branchrow,
63 * and this class expects that no-one will replace that reference.
64 */
65 // private SQLLongint child_page = null;
66
67 /**
68 * The array of object to be used as the row.
69 */
70 private DataValueDescriptor[] branchrow = null;
71
72 /*
73 ** Constructors of BranchRow
74 */
75
76 /**
77 Constuctor for creating an "empty" BranchRow template, suitable for reading
78 in a branchRow from disk.
79 **/
80 private BranchRow()
81 {
82 }
83
84 private BranchRow(BTree btree)
85 throws StandardException
86 {
87 SQLLongint child_page =
88 new SQLLongint(ContainerHandle.INVALID_PAGE_NUMBER);
89
90 branchrow = btree.createBranchTemplate(child_page);
91
92 if (SanityManager.DEBUG)
93 {
94 SanityManager.ASSERT(
95 child_page == ((SQLLongint) branchrow[branchrow.length - 1]));
96 }
97 }
98
99 /*
100 ** The following methods implement the BranchRow Private interface.
101 */
102
103 /**
104 * Accessor for the child page field of the branch row.
105 *
106 * @return The child page object.
107 **/
108 private SQLLongint getChildPage()
109 {
110 // last column of branch row should be the child page pointer.
111 if (SanityManager.DEBUG)
112 {
113 SanityManager.ASSERT(branchrow != null);
114 SanityManager.ASSERT(
115 branchrow[branchrow.length - 1] instanceof SQLLongint);
116 }
117
118 return((SQLLongint) branchrow[branchrow.length - 1]);
119 }
120
121 /*
122 ** The following methods implement the BranchRow Public interface.
123 */
124
125 /**
126 * Create an empty branch row template suitable for reading branch rows in
127 * from disk. This routine will create newly allocated "empty" objects for
128 * every column in the template row.
129 *
130 * @exception StandardException Standard exception policy.
131 */
132 public static BranchRow createEmptyTemplate(BTree btree)
133 throws StandardException
134 {
135 BranchRow newbranch = new BranchRow(btree);
136
137 return(new BranchRow(btree));
138 }
139
140 /**
141 * Create a new branch row, given a old branch row and a new child page.
142 * Used by BranchControlRow to manufacture new branch rows when splitting
143 * or growing the tree.
144 *
145 * There is no way to "copy" values of a template row, so this class just
146 * stores a reference to each of the columns of the Indexable row passed
147 * in. This is ok as all
148 * usages of this class when instantiated this way, have an old branch row
149 * from which they are creating a new branch row with the same key values,
150 * and a different child page number.
151 *
152 * WARNING - this branch row is only valid while the old branch row is
153 * valid, as it contains references to the columns of the old branch row.
154 * So use of the row should only provide read-only access to the objects
155 * of the old branch row which are referenced.
156 */
157 public BranchRow createBranchRowFromOldBranchRow(long childpageno)
158 {
159 BranchRow newbranch = new BranchRow();
160
161 /* create new object array, and shallow copy all object references
162 * from old branch row to new branch row.
163 */
164
165 newbranch.branchrow = new DataValueDescriptor[this.branchrow.length];
166 System.arraycopy(
167 this.branchrow, 0, newbranch.branchrow, 0,
168 newbranch.branchrow.length - 1);
169
170 /* now create a different child page pointer object and place it as
171 * last column in the new branch row.
172 */
173 newbranch.branchrow[newbranch.branchrow.length - 1] =
174 new SQLLongint(childpageno);
175
176 return(newbranch);
177 }
178
179 /**
180 * Create a new branch row, given a old leaf row and a new child page.
181 * Used by LeafControlRow to manufacture new branch rows when splitting
182 * or growing the tree.
183 *
184 * There is no way to "copy" values of a template row, so this class just
185 * stores a referece to the Indexable row passed in. This is ok as all
186 * usages of this class when instantiated this way, have an old leaf row
187 * from which they are creating a new branch row with the same key values,
188 * and a different child page number.
189 *
190 * WARNING - this branch row is only valid while the old leaf row is
191 * valid, as it contains references to the columns of the old leaf row.
192 * So use of the row should only provide read-only access to the objects
193 * of the old leaf row which are referenced.
194 */
195 public static BranchRow createBranchRowFromOldLeafRow(
196 DataValueDescriptor[] leafrow,
197 long childpageno)
198 {
199 BranchRow newbranch = new BranchRow();
200
201 /* create new object array for the row, and copy all object references
202 * from old leaf row to new branch row.
203 */
204 newbranch.branchrow = new DataValueDescriptor[leafrow.length + 1];
205
206 System.arraycopy(leafrow, 0, newbranch.branchrow, 0, leafrow.length);
207
208 /* now create a different child page pointer object and place it as
209 * last column in the new branch row.
210 */
211 newbranch.branchrow[newbranch.branchrow.length - 1] =
212 new SQLLongint(childpageno);
213
214 return(newbranch);
215 }
216
217 /**
218 * Return the branch row.
219 * <p>
220 * Return the DataValueDescriptor array that represents the branch row,
221 * for use in raw store calls to fetch, insert, and update.
222 * <p>
223 *
224 * @return The branch row object array.
225 **/
226 protected DataValueDescriptor[] getRow()
227 {
228 return(this.branchrow);
229 }
230
231 /**
232 * Set the page number field of the branch row to a new value.
233 *
234 * @param page_number the new page number.
235 **/
236 protected void setPageNumber(long page_number)
237 {
238 getChildPage().setValue(page_number);
239 }
240
241
242 public String toString()
243 {
244 if (SanityManager.DEBUG)
245 {
246 return(
247 RowUtil.toString(branchrow) +
248 "child page: (" + getChildPage() + ")");
249 }
250 else
251 {
252 return(null);
253 }
254 }
255 }