1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.store; |
7 | |
8 | import org.h2.engine.Session; |
9 | |
10 | /** |
11 | * A data page of a stream. The format is: |
12 | * <ul> |
13 | * <li>page type: byte (0)</li> |
14 | * <li>checksum: short (1-2)</li> |
15 | * <li>the trunk page id: int (3-6)</li> |
16 | * <li>log key: int (7-10)</li> |
17 | * <li>data (11-)</li> |
18 | * </ul> |
19 | */ |
20 | public class PageStreamData extends Page { |
21 | |
22 | private static final int DATA_START = 11; |
23 | |
24 | private final PageStore store; |
25 | private int trunk; |
26 | private int logKey; |
27 | private Data data; |
28 | private int remaining; |
29 | |
30 | private PageStreamData(PageStore store, int pageId, int trunk, int logKey) { |
31 | setPos(pageId); |
32 | this.store = store; |
33 | this.trunk = trunk; |
34 | this.logKey = logKey; |
35 | } |
36 | |
37 | /** |
38 | * Read a stream data page. |
39 | * |
40 | * @param store the page store |
41 | * @param data the data |
42 | * @param pageId the page id |
43 | * @return the page |
44 | */ |
45 | static PageStreamData read(PageStore store, Data data, int pageId) { |
46 | PageStreamData p = new PageStreamData(store, pageId, 0, 0); |
47 | p.data = data; |
48 | p.read(); |
49 | return p; |
50 | } |
51 | |
52 | /** |
53 | * Create a new stream trunk page. |
54 | * |
55 | * @param store the page store |
56 | * @param pageId the page id |
57 | * @param trunk the trunk page |
58 | * @param logKey the log key |
59 | * @return the page |
60 | */ |
61 | static PageStreamData create(PageStore store, int pageId, int trunk, |
62 | int logKey) { |
63 | return new PageStreamData(store, pageId, trunk, logKey); |
64 | } |
65 | |
66 | /** |
67 | * Read the page from the disk. |
68 | */ |
69 | private void read() { |
70 | data.reset(); |
71 | data.readByte(); |
72 | data.readShortInt(); |
73 | trunk = data.readInt(); |
74 | logKey = data.readInt(); |
75 | } |
76 | |
77 | /** |
78 | * Write the header data. |
79 | */ |
80 | void initWrite() { |
81 | data = store.createData(); |
82 | data.writeByte((byte) Page.TYPE_STREAM_DATA); |
83 | data.writeShortInt(0); |
84 | data.writeInt(trunk); |
85 | data.writeInt(logKey); |
86 | remaining = store.getPageSize() - data.length(); |
87 | } |
88 | |
89 | /** |
90 | * Write the data to the buffer. |
91 | * |
92 | * @param buff the source data |
93 | * @param offset the offset in the source buffer |
94 | * @param len the number of bytes to write |
95 | * @return the number of bytes written |
96 | */ |
97 | int write(byte[] buff, int offset, int len) { |
98 | int max = Math.min(remaining, len); |
99 | data.write(buff, offset, max); |
100 | remaining -= max; |
101 | return max; |
102 | } |
103 | |
104 | @Override |
105 | public void write() { |
106 | store.writePage(getPos(), data); |
107 | } |
108 | |
109 | /** |
110 | * Get the number of bytes that fit in a page. |
111 | * |
112 | * @param pageSize the page size |
113 | * @return the number of bytes |
114 | */ |
115 | static int getCapacity(int pageSize) { |
116 | return pageSize - DATA_START; |
117 | } |
118 | |
119 | /** |
120 | * Read the next bytes from the buffer. |
121 | * |
122 | * @param startPos the position in the data page |
123 | * @param buff the target buffer |
124 | * @param off the offset in the target buffer |
125 | * @param len the number of bytes to read |
126 | */ |
127 | void read(int startPos, byte[] buff, int off, int len) { |
128 | System.arraycopy(data.getBytes(), startPos, buff, off, len); |
129 | } |
130 | |
131 | /** |
132 | * Get the number of remaining data bytes of this page. |
133 | * |
134 | * @return the remaining byte count |
135 | */ |
136 | int getRemaining() { |
137 | return remaining; |
138 | } |
139 | |
140 | /** |
141 | * Get the estimated memory size. |
142 | * |
143 | * @return number of double words (4 bytes) |
144 | */ |
145 | @Override |
146 | public int getMemory() { |
147 | return store.getPageSize() >> 2; |
148 | } |
149 | |
150 | @Override |
151 | public void moveTo(Session session, int newPos) { |
152 | // not required |
153 | } |
154 | |
155 | int getLogKey() { |
156 | return logKey; |
157 | } |
158 | |
159 | @Override |
160 | public String toString() { |
161 | return "[" + getPos() + "] stream data key:" + logKey + |
162 | " pos:" + data.length() + " remaining:" + remaining; |
163 | } |
164 | |
165 | @Override |
166 | public boolean canRemove() { |
167 | return true; |
168 | } |
169 | |
170 | public static int getReadStart() { |
171 | return DATA_START; |
172 | } |
173 | |
174 | @Override |
175 | public boolean canMove() { |
176 | return false; |
177 | } |
178 | |
179 | } |