jpayne@68
|
1 package bloom;
|
jpayne@68
|
2
|
jpayne@68
|
3 import java.util.Arrays;
|
jpayne@68
|
4 import java.util.Random;
|
jpayne@68
|
5 import java.util.concurrent.ArrayBlockingQueue;
|
jpayne@68
|
6
|
jpayne@68
|
7 import shared.Shared;
|
jpayne@68
|
8 import shared.Timer;
|
jpayne@68
|
9
|
jpayne@68
|
10
|
jpayne@68
|
11 /**
|
jpayne@68
|
12 *
|
jpayne@68
|
13 * Uses hashing rather than direct-mapping to support longer kmers.
|
jpayne@68
|
14 *
|
jpayne@68
|
15 * @author Brian Bushnell
|
jpayne@68
|
16 * @date Aug 17, 2012
|
jpayne@68
|
17 *
|
jpayne@68
|
18 */
|
jpayne@68
|
19 public class KCountArray5MT extends KCountArray {
|
jpayne@68
|
20
|
jpayne@68
|
21 /**
|
jpayne@68
|
22 *
|
jpayne@68
|
23 */
|
jpayne@68
|
24 private static final long serialVersionUID = -5456926900022701212L;
|
jpayne@68
|
25
|
jpayne@68
|
26 public static void main(String[] args){
|
jpayne@68
|
27 long cells=Long.parseLong(args[0]);
|
jpayne@68
|
28 int bits=Integer.parseInt(args[1]);
|
jpayne@68
|
29 int gap=Integer.parseInt(args[2]);
|
jpayne@68
|
30 int hashes=Integer.parseInt(args[3]);
|
jpayne@68
|
31
|
jpayne@68
|
32 verbose=false;
|
jpayne@68
|
33
|
jpayne@68
|
34 KCountArray5MT kca=new KCountArray5MT(cells, bits, gap, hashes);
|
jpayne@68
|
35
|
jpayne@68
|
36 System.out.println(kca.read(0));
|
jpayne@68
|
37 kca.increment(0);
|
jpayne@68
|
38 System.out.println(kca.read(0));
|
jpayne@68
|
39 kca.increment(0);
|
jpayne@68
|
40 System.out.println(kca.read(0));
|
jpayne@68
|
41 System.out.println();
|
jpayne@68
|
42
|
jpayne@68
|
43 System.out.println(kca.read(1));
|
jpayne@68
|
44 kca.increment(1);
|
jpayne@68
|
45 System.out.println(kca.read(1));
|
jpayne@68
|
46 kca.increment(1);
|
jpayne@68
|
47 System.out.println(kca.read(1));
|
jpayne@68
|
48 System.out.println();
|
jpayne@68
|
49
|
jpayne@68
|
50 System.out.println(kca.read(100));
|
jpayne@68
|
51 kca.increment(100);
|
jpayne@68
|
52 System.out.println(kca.read(100));
|
jpayne@68
|
53 kca.increment(100);
|
jpayne@68
|
54 System.out.println(kca.read(100));
|
jpayne@68
|
55 kca.increment(100);
|
jpayne@68
|
56 System.out.println(kca.read(100));
|
jpayne@68
|
57 System.out.println();
|
jpayne@68
|
58
|
jpayne@68
|
59
|
jpayne@68
|
60 System.out.println(kca.read(150));
|
jpayne@68
|
61 kca.increment(150);
|
jpayne@68
|
62 System.out.println(kca.read(150));
|
jpayne@68
|
63 System.out.println();
|
jpayne@68
|
64
|
jpayne@68
|
65 }
|
jpayne@68
|
66
|
jpayne@68
|
67 public KCountArray5MT(long cells_, int bits_, int gap_, int hashes_){
|
jpayne@68
|
68 super(cells_, bits_);
|
jpayne@68
|
69 // verbose=false;
|
jpayne@68
|
70 long words=cells/cellsPerWord;
|
jpayne@68
|
71 assert(words/numArrays<=Integer.MAX_VALUE);
|
jpayne@68
|
72 wordsPerArray=(int)(words/numArrays);
|
jpayne@68
|
73 cellsPerArray=cells/numArrays;
|
jpayne@68
|
74 cellMod=cellsPerArray-1;
|
jpayne@68
|
75 hashes=hashes_;
|
jpayne@68
|
76 // System.out.println("cells="+cells+", words="+words+", wordsPerArray="+wordsPerArray+", numArrays="+numArrays+", hashes="+hashes);
|
jpayne@68
|
77 // assert(false);
|
jpayne@68
|
78 matrix=new int[numArrays][];
|
jpayne@68
|
79 assert(hashes>0 && hashes<=hashMasks.length);
|
jpayne@68
|
80 }
|
jpayne@68
|
81
|
jpayne@68
|
82 @Override
|
jpayne@68
|
83 public int read(final long rawKey){
|
jpayne@68
|
84 assert(finished);
|
jpayne@68
|
85 if(verbose){System.err.println("Reading raw key "+rawKey);}
|
jpayne@68
|
86 long key2=hash(rawKey, 0);
|
jpayne@68
|
87 int min=readHashed(key2);
|
jpayne@68
|
88 for(int i=1; i<hashes && min>0; i++){
|
jpayne@68
|
89 if(verbose){System.err.println("Reading. i="+i+", key2="+key2);}
|
jpayne@68
|
90 key2=Long.rotateRight(key2, hashBits);
|
jpayne@68
|
91 key2=hash(key2, i);
|
jpayne@68
|
92 if(verbose){System.err.println("Rot/hash. i="+i+", key2="+key2);}
|
jpayne@68
|
93 min=min(min, readHashed(key2));
|
jpayne@68
|
94 }
|
jpayne@68
|
95 return min;
|
jpayne@68
|
96 }
|
jpayne@68
|
97
|
jpayne@68
|
98 int readHashed(long key){
|
jpayne@68
|
99 assert(finished);
|
jpayne@68
|
100 if(verbose){System.err.print("Reading hashed key "+key);}
|
jpayne@68
|
101 // System.out.println("key="+key);
|
jpayne@68
|
102 int arrayNum=(int)(key&arrayMask);
|
jpayne@68
|
103 key=(key>>>arrayBits)%(cellMod);
|
jpayne@68
|
104 // System.out.println("array="+arrayNum);
|
jpayne@68
|
105 // System.out.println("key2="+key);
|
jpayne@68
|
106 int[] array=matrix[arrayNum];
|
jpayne@68
|
107 int index=(int)(key>>>indexShift);
|
jpayne@68
|
108 // assert(false) : indexShift;
|
jpayne@68
|
109 // System.out.println("index="+index);
|
jpayne@68
|
110 int word=array[index];
|
jpayne@68
|
111 // System.out.println("word="+Integer.toHexString(word));
|
jpayne@68
|
112 assert(word>>>(cellBits*key) == word>>>(cellBits*(key&cellMask)));
|
jpayne@68
|
113 // int cellShift=(int)(cellBits*(key&cellMask));
|
jpayne@68
|
114 int cellShift=(int)(cellBits*key);
|
jpayne@68
|
115 if(verbose){System.err.println(", array="+arrayNum+", index="+index+", cellShift="+(cellShift%32)+", value="+((int)((word>>>cellShift)&valueMask)));}
|
jpayne@68
|
116 // System.out.println("cellShift="+cellShift);
|
jpayne@68
|
117 return (int)((word>>>cellShift)&valueMask);
|
jpayne@68
|
118 }
|
jpayne@68
|
119
|
jpayne@68
|
120 @Override
|
jpayne@68
|
121 public void write(final long key, int value){
|
jpayne@68
|
122 throw new RuntimeException("Not allowed for this class.");
|
jpayne@68
|
123 }
|
jpayne@68
|
124
|
jpayne@68
|
125 //Slow
|
jpayne@68
|
126 @Override
|
jpayne@68
|
127 public void increment(final long rawKey, int amt){
|
jpayne@68
|
128 for(int i=0; i<amt; i++){increment0(rawKey);}
|
jpayne@68
|
129 }
|
jpayne@68
|
130
|
jpayne@68
|
131 public void increment0(final long rawKey){
|
jpayne@68
|
132 if(verbose){System.err.println("\n*** Incrementing raw key "+rawKey+" ***");}
|
jpayne@68
|
133
|
jpayne@68
|
134 buffer[bufferlen]=hash(rawKey, 0);
|
jpayne@68
|
135 bufferlen++;
|
jpayne@68
|
136
|
jpayne@68
|
137 if(bufferlen>=buffer.length){
|
jpayne@68
|
138
|
jpayne@68
|
139 if(verbose){System.err.println("Moving array.");}
|
jpayne@68
|
140
|
jpayne@68
|
141 for(int w=0; w<writers.length; w++){
|
jpayne@68
|
142 writers[w].add(buffer);
|
jpayne@68
|
143 }
|
jpayne@68
|
144 bufferlen=0;
|
jpayne@68
|
145 buffer=new long[buffer.length];
|
jpayne@68
|
146 if(verbose){System.err.println("Moved.");}
|
jpayne@68
|
147 }
|
jpayne@68
|
148
|
jpayne@68
|
149 }
|
jpayne@68
|
150
|
jpayne@68
|
151
|
jpayne@68
|
152 @Override
|
jpayne@68
|
153 public synchronized void increment(long[] keys){
|
jpayne@68
|
154 for(int i=0; i<keys.length; i++){
|
jpayne@68
|
155 keys[i]=hash(keys[i],0);
|
jpayne@68
|
156 }
|
jpayne@68
|
157 for(int w=0; w<writers.length; w++){
|
jpayne@68
|
158 writers[w].add(keys);
|
jpayne@68
|
159 }
|
jpayne@68
|
160 }
|
jpayne@68
|
161
|
jpayne@68
|
162 /** Returns unincremented value */
|
jpayne@68
|
163 @Override
|
jpayne@68
|
164 public int incrementAndReturnUnincremented(long key, int incr){
|
jpayne@68
|
165 throw new RuntimeException("Operation not supported.");
|
jpayne@68
|
166 }
|
jpayne@68
|
167
|
jpayne@68
|
168 @Override
|
jpayne@68
|
169 public long[] transformToFrequency(){
|
jpayne@68
|
170 return transformToFrequency(matrix);
|
jpayne@68
|
171 }
|
jpayne@68
|
172
|
jpayne@68
|
173 @Override
|
jpayne@68
|
174 public String toContentsString(){
|
jpayne@68
|
175 StringBuilder sb=new StringBuilder();
|
jpayne@68
|
176 sb.append("[");
|
jpayne@68
|
177 String comma="";
|
jpayne@68
|
178 for(int[] array : matrix){
|
jpayne@68
|
179 for(int i=0; i<array.length; i++){
|
jpayne@68
|
180 int word=array[i];
|
jpayne@68
|
181 for(int j=0; j<cellsPerWord; j++){
|
jpayne@68
|
182 int x=word&valueMask;
|
jpayne@68
|
183 sb.append(comma);
|
jpayne@68
|
184 sb.append(x);
|
jpayne@68
|
185 word>>>=cellBits;
|
jpayne@68
|
186 comma=", ";
|
jpayne@68
|
187 }
|
jpayne@68
|
188 }
|
jpayne@68
|
189 }
|
jpayne@68
|
190 sb.append("]");
|
jpayne@68
|
191 return sb.toString();
|
jpayne@68
|
192 }
|
jpayne@68
|
193
|
jpayne@68
|
194 @Override
|
jpayne@68
|
195 public double usedFraction(){return cellsUsed/(double)cells;}
|
jpayne@68
|
196
|
jpayne@68
|
197 @Override
|
jpayne@68
|
198 public double usedFraction(int mindepth){return cellsUsed(mindepth)/(double)cells;}
|
jpayne@68
|
199
|
jpayne@68
|
200 @Override
|
jpayne@68
|
201 public long cellsUsed(int mindepth){
|
jpayne@68
|
202 long count=0;
|
jpayne@68
|
203 for(int[] array : matrix){
|
jpayne@68
|
204 if(array!=null){
|
jpayne@68
|
205 for(int word : array){
|
jpayne@68
|
206 while(word>0){
|
jpayne@68
|
207 int x=word&valueMask;
|
jpayne@68
|
208 if(x>=mindepth){count++;}
|
jpayne@68
|
209 word>>>=cellBits;
|
jpayne@68
|
210 }
|
jpayne@68
|
211 }
|
jpayne@68
|
212 }
|
jpayne@68
|
213 }
|
jpayne@68
|
214 return count;
|
jpayne@68
|
215 }
|
jpayne@68
|
216
|
jpayne@68
|
217
|
jpayne@68
|
218 @Override
|
jpayne@68
|
219 final long hash(long key, int row){
|
jpayne@68
|
220 int cell=(int)((Long.MAX_VALUE&key)%(hashArrayLength-1));
|
jpayne@68
|
221 // int cell=(int)(hashCellMask&(key));
|
jpayne@68
|
222
|
jpayne@68
|
223 if(row==0){//Doublehash only first time
|
jpayne@68
|
224 key=key^hashMasks[(row+4)%hashMasks.length][cell];
|
jpayne@68
|
225 cell=(int)(hashCellMask&(key>>4));
|
jpayne@68
|
226 // cell=(int)(hashCellMask&(key>>hashBits));
|
jpayne@68
|
227 // cell=(int)((Long.MAX_VALUE&key)%(hashArrayLength-1));
|
jpayne@68
|
228 }
|
jpayne@68
|
229
|
jpayne@68
|
230 return key^hashMasks[row][cell];
|
jpayne@68
|
231 }
|
jpayne@68
|
232
|
jpayne@68
|
233 /**
|
jpayne@68
|
234 * @param i
|
jpayne@68
|
235 * @param j
|
jpayne@68
|
236 * @return
|
jpayne@68
|
237 */
|
jpayne@68
|
238 private static long[][] makeMasks(int rows, int cols) {
|
jpayne@68
|
239
|
jpayne@68
|
240 long seed;
|
jpayne@68
|
241 synchronized(KCountArray5MT.class){
|
jpayne@68
|
242 seed=counter;
|
jpayne@68
|
243 counter++;
|
jpayne@68
|
244 }
|
jpayne@68
|
245
|
jpayne@68
|
246 Timer t=new Timer();
|
jpayne@68
|
247 long[][] r=new long[rows][cols];
|
jpayne@68
|
248 Random randy=Shared.threadLocalRandom(seed);
|
jpayne@68
|
249 for(int i=0; i<r.length; i++){
|
jpayne@68
|
250 fillMasks(r[i], randy);
|
jpayne@68
|
251 }
|
jpayne@68
|
252 t.stop();
|
jpayne@68
|
253 if(t.elapsed>200000000L){System.out.println("Mask-creation time: "+t);}
|
jpayne@68
|
254 return r;
|
jpayne@68
|
255 }
|
jpayne@68
|
256
|
jpayne@68
|
257 private static void fillMasks(long[] r, Random randy) {
|
jpayne@68
|
258 // for(int i=0; i<r.length; i++){
|
jpayne@68
|
259 // long x=0;
|
jpayne@68
|
260 // while(Long.bitCount(x&0xFFFFFFFF)!=16){
|
jpayne@68
|
261 // x=randy.nextLong();
|
jpayne@68
|
262 // }
|
jpayne@68
|
263 // r[i]=(x&Long.MAX_VALUE);
|
jpayne@68
|
264 // }
|
jpayne@68
|
265
|
jpayne@68
|
266 final int hlen=(1<<hashBits);
|
jpayne@68
|
267 assert(r.length==hlen);
|
jpayne@68
|
268 int[] count1=new int[hlen];
|
jpayne@68
|
269 int[] count2=new int[hlen];
|
jpayne@68
|
270 final long mask=hlen-1;
|
jpayne@68
|
271
|
jpayne@68
|
272 for(int i=0; i<r.length; i++){
|
jpayne@68
|
273 long x=0;
|
jpayne@68
|
274 int y=0;
|
jpayne@68
|
275 int z=0;
|
jpayne@68
|
276 while(Long.bitCount(x&0xFFFFFFFFL)!=16){
|
jpayne@68
|
277 x=randy.nextLong();
|
jpayne@68
|
278 while(Long.bitCount(x&0xFFFFFFFFL)<16){
|
jpayne@68
|
279 x|=(1L<<randy.nextInt(32));
|
jpayne@68
|
280 }
|
jpayne@68
|
281 while(Long.bitCount(x&0xFFFFFFFFL)>16){
|
jpayne@68
|
282 x&=(~(1L<<randy.nextInt(32)));
|
jpayne@68
|
283 }
|
jpayne@68
|
284 while(Long.bitCount(x&0xFFFFFFFF00000000L)<16){
|
jpayne@68
|
285 x|=(1L<<(randy.nextInt(32)+32));
|
jpayne@68
|
286 }
|
jpayne@68
|
287 while(Long.bitCount(x&0xFFFFFFFF00000000L)>16){
|
jpayne@68
|
288 x&=(~(1L<<(randy.nextInt(32)+32)));
|
jpayne@68
|
289 }
|
jpayne@68
|
290
|
jpayne@68
|
291 // System.out.print(".");
|
jpayne@68
|
292 // y=(((int)(x&mask))^i);
|
jpayne@68
|
293 y=(((int)(x&mask)));
|
jpayne@68
|
294 z=(int)((x>>hashBits)&mask);
|
jpayne@68
|
295 if(count1[y]>0 || count2[z]>0){
|
jpayne@68
|
296 x=0;
|
jpayne@68
|
297 }
|
jpayne@68
|
298 }
|
jpayne@68
|
299 // System.out.println(Long.toBinaryString(x));
|
jpayne@68
|
300 r[i]=(x&Long.MAX_VALUE);
|
jpayne@68
|
301 count1[y]++;
|
jpayne@68
|
302 count2[z]++;
|
jpayne@68
|
303 }
|
jpayne@68
|
304
|
jpayne@68
|
305 }
|
jpayne@68
|
306
|
jpayne@68
|
307
|
jpayne@68
|
308 @Override
|
jpayne@68
|
309 public void initialize(){
|
jpayne@68
|
310 for(int i=0; i<writers.length; i++){
|
jpayne@68
|
311 writers[i]=new WriteThread(i);
|
jpayne@68
|
312 writers[i].start();
|
jpayne@68
|
313
|
jpayne@68
|
314 while(!writers[i].isAlive()){
|
jpayne@68
|
315 System.out.print(".");
|
jpayne@68
|
316 }
|
jpayne@68
|
317 }
|
jpayne@68
|
318 }
|
jpayne@68
|
319
|
jpayne@68
|
320 @Override
|
jpayne@68
|
321 public void shutdown(){
|
jpayne@68
|
322 if(finished){return;}
|
jpayne@68
|
323 synchronized(this){
|
jpayne@68
|
324 if(finished){return;}
|
jpayne@68
|
325
|
jpayne@68
|
326 //Clear buffer
|
jpayne@68
|
327 if(bufferlen<buffer.length){
|
jpayne@68
|
328 buffer=Arrays.copyOf(buffer, bufferlen);
|
jpayne@68
|
329 }
|
jpayne@68
|
330
|
jpayne@68
|
331 if(buffer.length>0){
|
jpayne@68
|
332 for(int i=0; i<writers.length; i++)
|
jpayne@68
|
333 writers[i].add(buffer);
|
jpayne@68
|
334 }
|
jpayne@68
|
335 buffer=null;
|
jpayne@68
|
336 bufferlen=0;
|
jpayne@68
|
337
|
jpayne@68
|
338
|
jpayne@68
|
339 //Add poison
|
jpayne@68
|
340 for(WriteThread wt : writers){
|
jpayne@68
|
341 wt.add(poison);
|
jpayne@68
|
342 }
|
jpayne@68
|
343
|
jpayne@68
|
344 //Wait for termination
|
jpayne@68
|
345 for(WriteThread wt : writers){
|
jpayne@68
|
346 // System.out.println("wt"+wt.num+" is alive: "+wt.isAlive());
|
jpayne@68
|
347 while(wt.isAlive()){
|
jpayne@68
|
348 // System.out.println("wt"+wt.num+" is alive: "+wt.isAlive());
|
jpayne@68
|
349 try {
|
jpayne@68
|
350 wt.join(10000);
|
jpayne@68
|
351 } catch (InterruptedException e) {
|
jpayne@68
|
352 // TODO Auto-generated catch block
|
jpayne@68
|
353 e.printStackTrace();
|
jpayne@68
|
354 }
|
jpayne@68
|
355 if(wt.isAlive()){System.err.println(wt.getClass().getCanonicalName()+" is taking a long time to die.");}
|
jpayne@68
|
356 }
|
jpayne@68
|
357 cellsUsed+=wt.cellsUsedPersonal;
|
jpayne@68
|
358 // System.out.println("cellsUsed="+cellsUsed);
|
jpayne@68
|
359 }
|
jpayne@68
|
360
|
jpayne@68
|
361 assert(!finished);
|
jpayne@68
|
362 finished=true;
|
jpayne@68
|
363 }
|
jpayne@68
|
364 }
|
jpayne@68
|
365
|
jpayne@68
|
366 private class WriteThread extends Thread{
|
jpayne@68
|
367
|
jpayne@68
|
368 public WriteThread(int tnum){
|
jpayne@68
|
369 num=tnum;
|
jpayne@68
|
370 }
|
jpayne@68
|
371
|
jpayne@68
|
372 @Override
|
jpayne@68
|
373 public void run(){
|
jpayne@68
|
374 assert(matrix[num]==null);
|
jpayne@68
|
375 array=new int[wordsPerArray]; //Makes NUMA systems use local memory.
|
jpayne@68
|
376 // assert(false);
|
jpayne@68
|
377 matrix[num]=array;
|
jpayne@68
|
378
|
jpayne@68
|
379 // assert(num==1);
|
jpayne@68
|
380
|
jpayne@68
|
381 long[] keys=null;
|
jpayne@68
|
382 while(!shutdown){
|
jpayne@68
|
383 // assert(false);
|
jpayne@68
|
384
|
jpayne@68
|
385 if(verbose){System.err.println(" - Reading keys for wt"+num+".");}
|
jpayne@68
|
386 while(keys==null){
|
jpayne@68
|
387 // System.out.println("Searching for keys.");
|
jpayne@68
|
388 try {
|
jpayne@68
|
389 keys=writeQueue.take();
|
jpayne@68
|
390 } catch (InterruptedException e) {
|
jpayne@68
|
391 // TODO Auto-generated catch block
|
jpayne@68
|
392 e.printStackTrace();
|
jpayne@68
|
393 }
|
jpayne@68
|
394 // System.out.println("*******************************************Found keys: "+keys.length);
|
jpayne@68
|
395 // assert(false);
|
jpayne@68
|
396 }
|
jpayne@68
|
397 if(keys==poison){
|
jpayne@68
|
398 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~0 ";
|
jpayne@68
|
399 shutdown=true;
|
jpayne@68
|
400 }else{
|
jpayne@68
|
401 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~1 ";
|
jpayne@68
|
402 for(long rawKey : keys){
|
jpayne@68
|
403 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2 ";
|
jpayne@68
|
404 if(verbose){System.err.println("Writer "+num+" considering raw key "+rawKey);}
|
jpayne@68
|
405 long key2=rawKey;
|
jpayne@68
|
406 // int y=read(rawKey);
|
jpayne@68
|
407 if((key2&arrayMask)==num){
|
jpayne@68
|
408 int x=incrementHashedLocal(key2);
|
jpayne@68
|
409 assert(x>=0) : "i="+0+", original=?, new should be >=0, new="+readHashed(key2)+", max="+maxValue+", key="+rawKey;
|
jpayne@68
|
410 if(verbose){System.err.println("postIncr value="+readHashed(key2));}
|
jpayne@68
|
411
|
jpayne@68
|
412 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~4 ";
|
jpayne@68
|
413 }
|
jpayne@68
|
414
|
jpayne@68
|
415 for(int i=1; i<hashes; i++){
|
jpayne@68
|
416 key2=Long.rotateRight(key2, hashBits);
|
jpayne@68
|
417 key2=hash(key2, i);
|
jpayne@68
|
418 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~3 ";
|
jpayne@68
|
419 if(verbose){System.err.println("rawKey="+rawKey+", i="+i+", key2="+key2+", value="+readHashed(key2));}
|
jpayne@68
|
420 if((key2&arrayMask)==num){
|
jpayne@68
|
421 int x=incrementHashedLocal(key2);
|
jpayne@68
|
422 assert(x>=0) : "i="+i+", original=?, new should be >=0, new="+readHashed(key2)+", max="+maxValue+", key="+rawKey;
|
jpayne@68
|
423 if(verbose){System.err.println("postIncr value="+readHashed(key2));}
|
jpayne@68
|
424
|
jpayne@68
|
425 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~4 ";
|
jpayne@68
|
426 }
|
jpayne@68
|
427
|
jpayne@68
|
428 // assert(false) : " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~5 ";
|
jpayne@68
|
429 }
|
jpayne@68
|
430 // int z=read(rawKey);
|
jpayne@68
|
431 // assert(hashes!=1 || !b || z==maxValue || z==y+1) : "b="+b+", y="+y+", z="+z+", rawKey="+rawKey+", num="+num;
|
jpayne@68
|
432 }
|
jpayne@68
|
433 }
|
jpayne@68
|
434 // System.out.println(" -- Read keys for wt"+num+". poison="+(keys==poison)+", len="+keys.length);
|
jpayne@68
|
435 if(verbose){System.err.println(" -- Read keys for wt"+num+". (success)");}
|
jpayne@68
|
436 keys=null;
|
jpayne@68
|
437 if(verbose){System.err.println("shutdown="+shutdown);}
|
jpayne@68
|
438 }
|
jpayne@68
|
439
|
jpayne@68
|
440 // System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I died: "+shutdown+", "+(keys==null)+".");
|
jpayne@68
|
441 // assert(false) : ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> I died: "+shutdown+", "+(keys==null)+".";
|
jpayne@68
|
442
|
jpayne@68
|
443 array=null;
|
jpayne@68
|
444 }
|
jpayne@68
|
445
|
jpayne@68
|
446 void add(long[] keys){
|
jpayne@68
|
447 // assert(isAlive());
|
jpayne@68
|
448
|
jpayne@68
|
449 // assert(!shutdown);
|
jpayne@68
|
450 // if(shutdown){return;}
|
jpayne@68
|
451
|
jpayne@68
|
452 if(verbose){System.err.println(" + Adding keys to wt"+num+".");}
|
jpayne@68
|
453 boolean success=false;
|
jpayne@68
|
454 while(!success){
|
jpayne@68
|
455 try {
|
jpayne@68
|
456 writeQueue.put(keys);
|
jpayne@68
|
457 success=true;
|
jpayne@68
|
458 } catch (InterruptedException e) {
|
jpayne@68
|
459 // TODO Auto-generated catch block
|
jpayne@68
|
460 e.printStackTrace();
|
jpayne@68
|
461 }
|
jpayne@68
|
462 }
|
jpayne@68
|
463 if(verbose){System.err.println(" ++ Added keys to wt"+num+". (success)");}
|
jpayne@68
|
464 }
|
jpayne@68
|
465
|
jpayne@68
|
466 private int incrementHashedLocal(final long key_){
|
jpayne@68
|
467 if(verbose){System.err.println("\n*** wt"+num+" incrementing hashed key "+key_+" ***");}
|
jpayne@68
|
468 assert((key_&arrayMask)==num);
|
jpayne@68
|
469 long key=(key_>>>arrayBits)%(cellMod);
|
jpayne@68
|
470 int index=(int)(key>>>indexShift);
|
jpayne@68
|
471 int word=array[index];
|
jpayne@68
|
472 int cellShift=(int)(cellBits*key);
|
jpayne@68
|
473 int value=((word>>>cellShift)&valueMask);
|
jpayne@68
|
474 if(value==0){cellsUsedPersonal++;}
|
jpayne@68
|
475 value=min(value+1, maxValue);
|
jpayne@68
|
476 word=(value<<cellShift)|(word&~((valueMask)<<cellShift));
|
jpayne@68
|
477 array[index]=word;
|
jpayne@68
|
478 if(verbose){System.err.println("\n*** wt"+num+" Incremented hashed key "+key_+". Value = "+readHashed(key_)+" ***");}
|
jpayne@68
|
479 return value;
|
jpayne@68
|
480 }
|
jpayne@68
|
481
|
jpayne@68
|
482 private int[] array;
|
jpayne@68
|
483 private final int num;
|
jpayne@68
|
484 public long cellsUsedPersonal=0;
|
jpayne@68
|
485
|
jpayne@68
|
486 public ArrayBlockingQueue<long[]> writeQueue=new ArrayBlockingQueue<long[]>(8);
|
jpayne@68
|
487 public boolean shutdown=false;
|
jpayne@68
|
488
|
jpayne@68
|
489 }
|
jpayne@68
|
490
|
jpayne@68
|
491
|
jpayne@68
|
492 public long cellsUsed(){return cellsUsed;}
|
jpayne@68
|
493
|
jpayne@68
|
494 private boolean finished=false;
|
jpayne@68
|
495
|
jpayne@68
|
496 private long cellsUsed;
|
jpayne@68
|
497 final int[][] matrix;
|
jpayne@68
|
498 private final WriteThread[] writers=new WriteThread[numArrays];
|
jpayne@68
|
499 final int hashes;
|
jpayne@68
|
500 final int wordsPerArray;
|
jpayne@68
|
501 private final long cellsPerArray;
|
jpayne@68
|
502 final long cellMod;
|
jpayne@68
|
503 private final long[][] hashMasks=makeMasks(8, hashArrayLength);
|
jpayne@68
|
504
|
jpayne@68
|
505 private long[] buffer=new long[2000];
|
jpayne@68
|
506 private int bufferlen=0;
|
jpayne@68
|
507
|
jpayne@68
|
508 private static final int hashBits=6;
|
jpayne@68
|
509 private static final int hashArrayLength=1<<hashBits;
|
jpayne@68
|
510 private static final int hashCellMask=hashArrayLength-1;
|
jpayne@68
|
511 static final long[] poison=new long[0];
|
jpayne@68
|
512
|
jpayne@68
|
513 private static long counter=0;
|
jpayne@68
|
514
|
jpayne@68
|
515 }
|