1 package net.obsearch.index.bucket.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import java.nio.ByteBuffer;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.LinkedList;
27 import java.util.List;
28 import java.util.ListIterator;
29 import net.obsearch.stats.Statistics;
30 import net.obsearch.Index;
31 import net.obsearch.OperationStatus;
32 import net.obsearch.Status;
33 import net.obsearch.exception.IllegalIdException;
34 import net.obsearch.exception.OBException;
35 import net.obsearch.index.utils.IntegerHolder;
36 import net.obsearch.index.bucket.BucketContainer;
37 import net.obsearch.query.AbstractOBQuery;
38
39 import net.obsearch.ob.OBFloat;
40 import net.obsearch.query.OBQueryFloat;
41 import net.obsearch.utils.bytes.ByteConversion;
42 import net.obsearch.filter.Filter;
43 import net.obsearch.storage.OBStore;
44 import net.obsearch.storage.OBStoreFloat;
45 import net.obsearch.storage.CloseIterator;
46 import net.obsearch.storage.TupleBytes;
47 import net.obsearch.constants.ByteConstants;
48
49
50
51
52
53
54
55 /
56
57
58
59
60
61
62
63
64
65 private B current = instantiateBucketObject();
66
67
68
69 private OBStore<TupleBytes> storage;
70
71
72
73
74 private int pivots;
75
76
77
78
79 private Index < O > index;
80
81
82
83 private int TUPLE_SIZE;
84
85
86
87
88 protected byte[] key;
89
90
91
92
93
94
95 private int secondaryIndexPivot;
96
97
98
99
100
101
102
103
104
105
106 public AbstractBucketContainerFloat(Index < O > index, int pivots, OBStore<TupleBytes> storage, byte[] key) {
107 this(index,pivots, storage,key,-1);
108 }
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public AbstractBucketContainerFloat(Index < O > index, int pivots, OBStore<TupleBytes> storage, byte[] key, int secondaryIndexPivot) {
123 assert index != null;
124 updateTupleSize(pivots);
125 this.index = index;
126 this.pivots = pivots;
127 this.storage = storage;
128 this.key = key;
129 this.secondaryIndexPivot = secondaryIndexPivot;
130 }
131
132
133
134
135
136 public List<B> getObjects(){
137 return null;
138 }
139
140
141
142
143 private byte[] buildKey(byte[] key, B bucket){
144 if(secondaryIndexPivot == -1){
145 return key;
146 }else{
147
148 return buildKey(key, bucket.getSmapVector()[this.secondaryIndexPivot]);
149 }
150 }
151
152 private byte[] buildKey(byte[] key, float value){
153 if(secondaryIndexPivot == -1){
154 return key;
155 }else{
156 ByteBuffer temp = ByteConversion.createByteBuffer(key.length + ByteConstants.Float.getSize());
157 temp.put(key);
158 temp.put(storage.getFactory().serializeFloat(value));
159 return temp.array();
160 }
161 }
162
163
164
165
166
167
168
169
170 protected abstract B instantiateBucketObject();
171
172 @Override
173 public void setPivots(int pivots) {
174 this.pivots = pivots;
175
176 }
177
178
179
180
181 @Override
182 public OperationStatus delete(B bucket, O object)
183 throws OBException, IllegalIdException, IllegalAccessException,
184 InstantiationException {
185 byte[] key2 = buildKey(key, bucket);
186 CloseIterator<TupleBytes> pr = storage.processRange(key2,key2);
187 OperationStatus res = new OperationStatus();
188 res.setStatus(Status.NOT_EXISTS);
189 try{
190 B cmp = instantiateBucketObject();
191
192 while(pr.hasNext()){
193 TupleBytes t = pr.next();
194 cmp.read(ByteConversion.createByteBuffer(t.getValue()), getPivots());
195
196 if(index.getObject(cmp.getId()).distance(object) == 0){
197 res.setStatus(Status.OK);
198 res.setId(cmp.getId());
199 pr.remove();
200 break;
201 }
202 }
203 }finally{
204 pr.closeCursor();
205 }
206
207
208 return res;
209 }
210
211 private void updateTupleSize(int pivots) {
212 TUPLE_SIZE = (pivots * net.obsearch.constants.ByteConstants.Float
213 .getSize())
214 + Index.ID_SIZE;
215 }
216
217
218
219
220
221
222
223
224
225 public OperationStatus insert(B bucket, O object) throws OBException,
226 IllegalIdException, IllegalAccessException, InstantiationException {
227
228 OperationStatus res = exists(bucket, object);
229
230 if(res.getStatus() == Status.NOT_EXISTS){
231 res = insertBulk(bucket, object);
232 }
233 return res;
234
235
236
237 }
238
239
240
241
242
243
244
245 public OperationStatus insertBulk(B bucket, O object) throws OBException,
246 IllegalIdException, IllegalAccessException, InstantiationException {
247
248 ByteBuffer out = ByteConversion
249 .createByteBuffer(calculateBufferSize(getPivots()));
250 OperationStatus res = new OperationStatus();
251 res.setStatus(Status.OK);
252 assert bucket.getId() != -1;
253 res.setId(bucket.getId());
254 bucket.write(out);
255 byte[] key2 = buildKey(key, bucket);
256 storage.put(key2, out.array());
257 return res;
258 }
259
260
261
262
263
264
265
266 /
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 public void search(OBQueryFloat < O > query, B b,
350 Filter<O> filter, Statistics stats) throws IllegalAccessException,
351 OBException, InstantiationException, IllegalIdException {
352
353 byte[] key1;
354 byte[] key2;
355 if(secondaryIndexPivot != -1){
356 key1 = buildKey(key, query.getLow()[this.secondaryIndexPivot]);
357 key2 = buildKey(key, query.getHigh()[this.secondaryIndexPivot]);
358 }else{
359 key1 = key;
360 key2 = key;
361 }
362 search(query,b,filter,key1,key2, stats);
363 }
364
365
366
367
368
369 public void search(OBQueryFloat < O > query, B b,
370 Filter<O> filter, byte[] key1, byte[] key2, Statistics stats) throws IllegalAccessException,
371 OBException, InstantiationException, IllegalIdException {
372
373
374 CloseIterator<TupleBytes> pr = storage.processRange(key1,key2);
375 long res = 0;
376 try{
377 B current = instantiateBucketObject();
378
379 while(pr.hasNext()){
380 TupleBytes t = pr.next();
381
382 current.read(ByteConversion.createByteBuffer(t.getValue()), getPivots());
383 stats.incDataRead(t.getValue().length);
384 float max = current.lInf(b);
385 stats.incSmapCount();
386 if (max <= query.getDistance() && query.isCandidate(max)) {
387 long id = current.getId();
388 O toCompare = index.getObject(id);
389
390 if(filter == null || filter.accept(toCompare, query.getObject())){
391 float realDistance = query.getObject().distance(toCompare);
392 stats.incDistanceCount();
393 if (realDistance <= query.getDistance()) {
394 query.add(id, toCompare, realDistance);
395 }
396 }
397 }
398
399 }
400 }finally{
401 pr.closeCursor();
402 }
403 }
404
405
406
407
408
409 /
410
411
412
413
414
415
416
417
418
419
420
421 public int size() throws OBException{
422 CloseIterator<TupleBytes> pr = storage.processRange(key,key);
423 int res = 0;
424 try{
425 while(pr.hasNext()){
426 TupleBytes t = pr.next();
427 res++;
428 }
429 }finally{
430 pr.closeCursor();
431 }
432 return res;
433 }
434
435 public void setKey(byte[] key){
436 this.key = key;
437 }
438
439
440 public byte[] serialize(){
441 return null;
442 }
443
444 public boolean isModified(){
445 return true;
446 }
447
448
449 }
450