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