1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package com.healthmarketscience.jackcess;
29
30 import java.lang.ref.Reference;
31 import java.lang.ref.SoftReference;
32 import java.nio.ByteBuffer;
33 import java.nio.ByteOrder;
34
35
36
37
38
39
40 public abstract class TempBufferHolder {
41
42 private static final Reference<ByteBuffer> EMPTY_BUFFER_REF =
43 new SoftReference<ByteBuffer>(null);
44
45
46
47
48 public enum Type {
49
50 HARD,
51
52
53 SOFT,
54
55
56 NONE;
57 }
58
59
60 private final boolean _autoRewind;
61
62 private final ByteOrder _order;
63
64 private int _modCount;
65
66 protected TempBufferHolder(boolean autoRewind, ByteOrder order) {
67 _autoRewind = autoRewind;
68 _order = order;
69 }
70
71
72
73
74
75 public int getModCount() {
76 return _modCount;
77 }
78
79
80
81
82
83
84
85 public static TempBufferHolder newHolder(Type type, boolean autoRewind) {
86 return newHolder(type, autoRewind, PageChannel.DEFAULT_BYTE_ORDER);
87 }
88
89
90
91
92
93
94
95
96 public static TempBufferHolder newHolder(Type type, boolean autoRewind,
97 ByteOrder order)
98 {
99 switch(type) {
100 case HARD:
101 return new HardTempBufferHolder(autoRewind, order);
102 case SOFT:
103 return new SoftTempBufferHolder(autoRewind, order);
104 case NONE:
105 return new NoneTempBufferHolder(autoRewind, order);
106 default:
107 throw new IllegalStateException("Unknown type " + type);
108 }
109 }
110
111
112
113
114
115
116 public final ByteBuffer getPageBuffer(PageChannel pageChannel) {
117 return getBuffer(pageChannel, pageChannel.getFormat().PAGE_SIZE);
118 }
119
120
121
122
123
124
125 public final ByteBuffer getBuffer(PageChannel pageChannel, int size) {
126 ByteBuffer buffer = getExistingBuffer();
127 if((buffer == null) || (buffer.capacity() < size)) {
128 buffer = pageChannel.createBuffer(size, _order);
129 ++_modCount;
130 setNewBuffer(buffer);
131 } else {
132 buffer.limit(size);
133 }
134 if(_autoRewind) {
135 buffer.rewind();
136 }
137 return buffer;
138 }
139
140
141
142
143 public abstract ByteBuffer getExistingBuffer();
144
145
146
147
148 public abstract void clear();
149
150
151
152
153 protected abstract void setNewBuffer(ByteBuffer newBuffer);
154
155
156
157
158 private static final class HardTempBufferHolder extends TempBufferHolder
159 {
160 private ByteBuffer _buffer;
161
162 private HardTempBufferHolder(boolean autoRewind, ByteOrder order) {
163 super(autoRewind, order);
164 }
165
166 @Override
167 public ByteBuffer getExistingBuffer() {
168 return _buffer;
169 }
170
171 @Override
172 protected void setNewBuffer(ByteBuffer newBuffer) {
173 _buffer = newBuffer;
174 }
175
176 @Override
177 public void clear() {
178 _buffer = null;
179 }
180 }
181
182
183
184
185 private static final class SoftTempBufferHolder extends TempBufferHolder
186 {
187 private Reference<ByteBuffer> _buffer = EMPTY_BUFFER_REF;
188
189 private SoftTempBufferHolder(boolean autoRewind, ByteOrder order) {
190 super(autoRewind, order);
191 }
192
193 @Override
194 public ByteBuffer getExistingBuffer() {
195 return _buffer.get();
196 }
197
198 @Override
199 protected void setNewBuffer(ByteBuffer newBuffer) {
200 _buffer.clear();
201 _buffer = new SoftReference<ByteBuffer>(newBuffer);
202 }
203
204 @Override
205 public void clear() {
206 _buffer.clear();
207 }
208 }
209
210
211
212
213 private static final class NoneTempBufferHolder extends TempBufferHolder
214 {
215 private NoneTempBufferHolder(boolean autoRewind, ByteOrder order) {
216 super(autoRewind, order);
217 }
218
219 @Override
220 public ByteBuffer getExistingBuffer() {
221 return null;
222 }
223
224 @Override
225 protected void setNewBuffer(ByteBuffer newBuffer) {
226
227 }
228
229 @Override
230 public void clear() {
231
232 }
233 }
234
235 }