File D:\maven-qcr-plugin-testsunitaires\qcr4java\h2-1.3.170-sources\target\site\qc\lecode\index\PageDataOverflow.java.html

1 /*
2 * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
3 * Version 1.0, and under the Eclipse Public License, Version 1.0
4 * (http://h2database.com/html/license.html).
5 * Initial Developer: H2 Group
6 */
7 package org.h2.index;
8
9 import org.h2.constant.ErrorCode;
10 import org.h2.constant.SysProperties;
11 import org.h2.engine.Constants;
12 import org.h2.engine.Session;
13 import org.h2.message.DbException;
14 import org.h2.store.Data;
15 import org.h2.store.Page;
16 import org.h2.store.PageStore;
17
18 /**
19 * Overflow data for a leaf page. Format:
20 * <ul>
21 * <li>page type: byte (0)</li>
22 * <li>checksum: short (1-2)</li>
23 * <li>parent page id (0 for root): int (3-6)</li>
24 * <li>more data: next overflow page id: int (7-10)</li>
25 * <li>last remaining size: short (7-8)</li>
26 * <li>data (11-/9-)</li>
27 * </ul>
28 */
29 public class PageDataOverflow extends Page {
30
31 /**
32 * The start of the data in the last overflow page.
33 */
34 static final int START_LAST = 9;
35
36 /**
37 * The start of the data in a overflow page that is not the last one.
38 */
39 static final int START_MORE = 11;
40
41 private static final int START_NEXT_OVERFLOW = 7;
42
43 /**
44 * The page store.
45 */
46 private final PageStore store;
47
48 /**
49 * The page type.
50 */
51 private int type;
52
53 /**
54 * The parent page (overflow or leaf).
55 */
56 private int parentPageId;
57
58 /**
59 * The next overflow page, or 0.
60 */
61 private int nextPage;
62
63 private final Data data;
64
65 private int start;
66 private int size;
67
68 /**
69 * Create an object from the given data page.
70 *
71 * @param store the page store
72 * @param pageId the page id
73 * @param data the data page
74 */
75 private PageDataOverflow(PageStore store, int pageId, Data data) {
76 this.store = store;
77 setPos(pageId);
78 this.data = data;
79 }
80
81 /**
82 * Read an overflow page.
83 *
84 * @param store the page store
85 * @param data the data
86 * @param pageId the page id
87 * @return the page
88 */
89 public static Page read(PageStore store, Data data, int pageId) {
90 PageDataOverflow p = new PageDataOverflow(store, pageId, data);
91 p.read();
92 return p;
93 }
94
95 /**
96 * Create a new overflow page.
97 *
98 * @param store the page store
99 * @param page the page id
100 * @param type the page type
101 * @param parentPageId the parent page id
102 * @param next the next page or 0
103 * @param all the data
104 * @param offset the offset within the data
105 * @param size the number of bytes
106 * @return the page
107 */
108 static PageDataOverflow create(PageStore store, int page,
109 int type, int parentPageId, int next,
110 Data all, int offset, int size) {
111 Data data = store.createData();
112 PageDataOverflow p = new PageDataOverflow(store, page, data);
113 store.logUndo(p, null);
114 data.writeByte((byte) type);
115 data.writeShortInt(0);
116 data.writeInt(parentPageId);
117 if (type == Page.TYPE_DATA_OVERFLOW) {
118 data.writeInt(next);
119 } else {
120 data.writeShortInt(size);
121 }
122 p.start = data.length();
123 data.write(all.getBytes(), offset, size);
124 p.type = type;
125 p.parentPageId = parentPageId;
126 p.nextPage = next;
127 p.size = size;
128 return p;
129 }
130
131 /**
132 * Read the page.
133 */
134 private void read() {
135 data.reset();
136 type = data.readByte();
137 data.readShortInt();
138 parentPageId = data.readInt();
139 if (type == (Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST)) {
140 size = data.readShortInt();
141 nextPage = 0;
142 } else if (type == Page.TYPE_DATA_OVERFLOW) {
143 nextPage = data.readInt();
144 size = store.getPageSize() - data.length();
145 } else {
146 throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "page:" + getPos() + " type:" + type);
147 }
148 start = data.length();
149 }
150
151 /**
152 * Read the data into a target buffer.
153 *
154 * @param target the target data page
155 * @return the next page, or 0 if no next page
156 */
157 int readInto(Data target) {
158 target.checkCapacity(size);
159 if (type == (Page.TYPE_DATA_OVERFLOW | Page.FLAG_LAST)) {
160 target.write(data.getBytes(), START_LAST, size);
161 return 0;
162 }
163 target.write(data.getBytes(), START_MORE, size);
164 return nextPage;
165 }
166
167 int getNextOverflow() {
168 return nextPage;
169 }
170
171 private void writeHead() {
172 data.writeByte((byte) type);
173 data.writeShortInt(0);
174 data.writeInt(parentPageId);
175 }
176
177 public void write() {
178 writeData();
179 store.writePage(getPos(), data);
180 }
181
182
183 private void writeData() {
184 data.reset();
185 writeHead();
186 if (type == Page.TYPE_DATA_OVERFLOW) {
187 data.writeInt(nextPage);
188 } else {
189 data.writeShortInt(size);
190 }
191 }
192
193
194 public String toString() {
195 return "page[" + getPos() + "] data leaf overflow parent:" + parentPageId + " next:" + nextPage;
196 }
197
198 /**
199 * Get the estimated memory size.
200 *
201 * @return number of double words (4 bytes)
202 */
203 public int getMemory() {
204 return (Constants.MEMORY_PAGE_DATA_OVERFLOW + store.getPageSize()) >> 2;
205 }
206
207 void setParentPageId(int parent) {
208 store.logUndo(this, data);
209 this.parentPageId = parent;
210 }
211
212 public void moveTo(Session session, int newPos) {
213 // load the pages into the cache, to ensure old pages
214 // are written
215 Page parent = store.getPage(parentPageId);
216 if (parent == null) {
217 throw DbException.throwInternalError();
218 }
219 PageDataOverflow next = null;
220 if (nextPage != 0) {
221 next = (PageDataOverflow) store.getPage(nextPage);
222 }
223 store.logUndo(this, data);
224 PageDataOverflow p2 = PageDataOverflow.create(store, newPos, type, parentPageId, nextPage, data, start, size);
225 store.update(p2);
226 if (next != null) {
227 next.setParentPageId(newPos);
228 store.update(next);
229 }
230 if (parent instanceof PageDataOverflow) {
231 PageDataOverflow p1 = (PageDataOverflow) parent;
232 p1.setNext(getPos(), newPos);
233 } else {
234 PageDataLeaf p1 = (PageDataLeaf) parent;
235 p1.setOverflow(getPos(), newPos);
236 }
237 store.update(parent);
238 store.free(getPos());
239 }
240
241 private void setNext(int old, int nextPage) {
242 if (SysProperties.CHECK && old != this.nextPage) {
243 DbException.throwInternalError("move " + this + " " + nextPage);
244 }
245 store.logUndo(this, data);
246 this.nextPage = nextPage;
247 data.setInt(START_NEXT_OVERFLOW, nextPage);
248 }
249
250 /**
251 * Free this page.
252 */
253 void free() {
254 store.logUndo(this, data);
255 store.free(getPos());
256 }
257
258 public boolean canRemove() {
259 return true;
260 }
261
262 public boolean isStream() {
263 return true;
264 }
265
266 }
267