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 package org.treetank.bucket;
28
29 import static com.google.common.base.Objects.toStringHelper;
30
31 import java.io.DataOutput;
32 import java.io.IOException;
33 import java.util.Arrays;
34
35 import org.treetank.access.conf.StandardSettings;
36 import org.treetank.api.IData;
37 import org.treetank.bucket.interfaces.IBucket;
38 import org.treetank.exception.TTIOException;
39
40 import com.google.common.hash.Funnel;
41 import com.google.common.hash.HashCode;
42 import com.google.common.hash.Hasher;
43 import com.google.common.hash.PrimitiveSink;
44
45
46
47
48
49
50
51
52
53
54
55 public final class DataBucket implements IBucket {
56
57
58 private final long mBucketKey;
59
60
61 private final IData[] mDatas;
62
63
64 private final long mLastBucketKey;
65
66
67
68
69
70
71
72 public DataBucket(final long pBucketKey, final long pLastBucketKey) {
73 mBucketKey = pBucketKey;
74 mLastBucketKey = pLastBucketKey;
75 mDatas = new IData[IConstants.CONTENT_COUNT];
76 }
77
78
79
80
81 @Override
82 public long getBucketKey() {
83 return mBucketKey;
84 }
85
86
87
88
89
90
91 public long getLastBucketPointer() {
92 return mLastBucketKey;
93 }
94
95
96
97
98
99
100
101
102 public IData getData(final int pOffset) {
103 return getDatas()[pOffset];
104 }
105
106
107
108
109
110
111
112
113
114 public void setData(final int pOffset, final IData pData) {
115 getDatas()[pOffset] = pData;
116 }
117
118
119
120
121
122
123 public IData[] getDatas() {
124 return mDatas;
125 }
126
127
128
129
130 @Override
131 public void serialize(final DataOutput pOutput) throws TTIOException {
132 try {
133 pOutput.writeInt(IConstants.DATABUCKET);
134 pOutput.writeLong(mBucketKey);
135 pOutput.writeLong(mLastBucketKey);
136 for (final IData data : getDatas()) {
137 if (data == null) {
138 pOutput.writeInt(IConstants.NULLDATA);
139 } else {
140 if (data instanceof DeletedData) {
141 pOutput.writeInt(IConstants.DELETEDDATA);
142 } else {
143 pOutput.writeInt(IConstants.INTERFACEDATA);
144 }
145 data.serialize(pOutput);
146 }
147 }
148 } catch (final IOException exc) {
149 throw new TTIOException(exc);
150 }
151 }
152
153
154
155
156 @Override
157 public String toString() {
158 return toStringHelper(this).add("mBucketKey", mBucketKey).add("mDatas", Arrays.toString(mDatas))
159 .toString();
160 }
161
162
163
164
165
166
167
168 public static class DeletedData implements IData {
169
170
171
172
173
174
175 enum DeletedDataFunnel implements Funnel<IData> {
176 INSTANCE;
177 public void funnel(IData from, PrimitiveSink into) {
178 into.putLong(from.getDataKey());
179 }
180 }
181
182
183
184
185 private long mDataKey;
186
187
188
189
190
191
192
193 public DeletedData(final long pDataKey) {
194 mDataKey = pDataKey;
195 }
196
197
198
199
200 @Override
201 public long getDataKey() {
202 return mDataKey;
203 }
204
205
206
207
208 @Override
209 public void serialize(final DataOutput pOutput) throws TTIOException {
210 try {
211 pOutput.writeLong(mDataKey);
212 } catch (final IOException exc) {
213 throw new TTIOException(exc);
214 }
215 }
216
217
218
219
220 @Override
221 public String toString() {
222 return toStringHelper(this).add("mDataKey", mDataKey).toString();
223 }
224
225
226
227
228 @Override
229 public Funnel<IData> getFunnel() {
230 return (Funnel<IData>)DeletedDataFunnel.INSTANCE;
231
232 }
233 }
234
235
236
237
238 @Override
239 public HashCode secureHash() {
240 final Hasher code = StandardSettings.HASHFUNC.newHasher().putLong(mBucketKey).putLong(mLastBucketKey);
241 for (int i = 0; i < mDatas.length; i++) {
242 if (mDatas[i] != null) {
243 code.putObject(mDatas[i], mDatas[i].getFunnel());
244 }
245 }
246 return code.hash();
247 }
248
249
250
251
252 @Override
253 public int hashCode() {
254 final int prime = 26267;
255 int result = 1;
256 result = prime * result + (int)(mLastBucketKey ^ (mLastBucketKey >>> 32));
257 result = prime * result + Arrays.deepHashCode(mDatas);
258 result = prime * result + (int)(mBucketKey ^ (mBucketKey >>> 32));
259 return result;
260 }
261
262
263
264
265 @Override
266 public boolean equals(Object obj) {
267 return obj.hashCode() == this.hashCode();
268 }
269
270 }