1 package kmer;
2 
3 import java.util.ArrayList;
4 import java.util.concurrent.atomic.AtomicLong;
5 
6 import fileIO.ByteStreamWriter;
7 import fileIO.TextStreamWriter;
8 import shared.Tools;
9 import structures.ByteBuilder;
10 import structures.SuperLongList;
11 
12 /**
13  * @author Brian Bushnell
14  * @date Oct 22, 2013
15  *
16  */
17 public class KmerLink extends AbstractKmerTable {
18 
19 	/*--------------------------------------------------------------*/
20 	/*----------------        Initialization        ----------------*/
21 	/*--------------------------------------------------------------*/
22 
KmerLink(long pivot_)23 	public KmerLink(long pivot_){
24 		pivot=pivot_;
25 	}
26 
KmerLink(long pivot_, int value_)27 	public KmerLink(long pivot_, int value_){
28 		pivot=pivot_;
29 		value=value_;
30 	}
31 
32 	/*--------------------------------------------------------------*/
33 	/*----------------        Public Methods        ----------------*/
34 	/*--------------------------------------------------------------*/
35 
36 	@Override
incrementAndReturnNumCreated(final long kmer, final int incr)37 	public final int incrementAndReturnNumCreated(final long kmer, final int incr) {
38 		int x=increment(kmer, incr);
39 		return x==incr ? 1 : 0;
40 	}
41 
42 	@Override
increment(final long kmer, final int incr)43 	public int increment(final long kmer, final int incr){
44 		if(pivot<0){pivot=kmer; return (value=incr);} //Allows initializing empty nodes to -1
45 		if(kmer==pivot){
46 			if(value<Integer.MAX_VALUE){value+=incr;}
47 			return value;
48 		}
49 		if(next==null){next=new KmerLink(kmer, incr); return 1;}
50 		return next.increment(kmer, incr);
51 	}
52 
53 	/*--------------------------------------------------------------*/
54 	/*----------------      Nonpublic Methods       ----------------*/
55 	/*--------------------------------------------------------------*/
56 
57 	/** Returns number of nodes added */
58 	@Override
set(long kmer, int value_)59 	public int set(long kmer, int value_){
60 		if(pivot<0){pivot=kmer; value=value_; return 1;} //Allows initializing empty nodes to -1
61 		if(kmer==pivot){value=value_; return 0;}
62 		if(next==null){next=new KmerLink(kmer, value_); return 1;}
63 		return next.set(kmer, value_);
64 	}
65 
66 	/** Returns number of nodes added */
67 	@Override
setIfNotPresent(long kmer, int value_)68 	public int setIfNotPresent(long kmer, int value_){
69 		if(pivot<0){pivot=kmer; value=value_; return 1;} //Allows initializing empty nodes to -1
70 		if(kmer==pivot){return 0;}
71 		if(next==null){next=new KmerLink(kmer, value_); return 1;}
72 		return next.setIfNotPresent(kmer, value_);
73 	}
74 
75 	@Override
get(long kmer)76 	KmerLink get(long kmer){
77 		if(kmer==pivot){return this;}
78 		return next==null ? null : next.get(kmer);
79 	}
80 
insert(KmerLink n)81 	boolean insert(KmerLink n){
82 		assert(pivot!=-1);
83 		if(pivot==n.pivot){return false;}
84 		if(next==null){next=n; return true;}
85 		return next.insert(n);
86 	}
87 
88 	@Override
contains(long kmer)89 	public boolean contains(long kmer){
90 		KmerLink node=get(kmer);
91 		return node!=null;
92 	}
93 
traversePrefix(ArrayList<KmerLink> list)94 	void traversePrefix(ArrayList<KmerLink> list){
95 		if(next!=null){next.traversePrefix(list);}
96 		list.add(this);
97 	}
98 
traverseInfix(ArrayList<KmerLink> list)99 	void traverseInfix(ArrayList<KmerLink> list){
100 		list.add(this);
101 		if(next!=null){next.traverseInfix(list);}
102 	}
103 
104 	/*--------------------------------------------------------------*/
105 	/*----------------   Resizing and Rebalancing   ----------------*/
106 	/*--------------------------------------------------------------*/
107 
108 	@Override
canResize()109 	boolean canResize() {
110 		return false;
111 	}
112 
113 	@Override
canRebalance()114 	public boolean canRebalance() {
115 		return true;
116 	}
117 
118 	@Deprecated
119 	@Override
arrayLength()120 	public int arrayLength() {
121 		throw new RuntimeException("Unsupported.");
122 	}
123 
124 	@Deprecated
125 	@Override
resize()126 	void resize() {
127 		throw new RuntimeException("Unsupported.");
128 	}
129 
130 	@Deprecated
131 	@Override
rebalance()132 	public void rebalance() {
133 		throw new RuntimeException("Please call rebalance(ArrayList<KmerNode>) instead, with an empty list.");
134 	}
135 
136 	/*--------------------------------------------------------------*/
137 	/*----------------          Ownership           ----------------*/
138 	/*--------------------------------------------------------------*/
139 
140 	@Override
initializeOwnership()141 	public final void initializeOwnership(){
142 		owner=-1;
143 		if(next!=null){next.initializeOwnership();}
144 	}
145 
146 	@Override
clearOwnership()147 	public final void clearOwnership(){initializeOwnership();}
148 
149 	@Override
setOwner(final long kmer, final int newOwner)150 	public final int setOwner(final long kmer, final int newOwner){
151 		KmerLink n=get(kmer);
152 		assert(n!=null);
153 		if(n.owner<=newOwner){
154 			synchronized(n){
155 				if(n.owner<newOwner){
156 					n.owner=newOwner;
157 				}
158 			}
159 		}
160 		return n.owner;
161 	}
162 
163 	@Override
clearOwner(final long kmer, final int owner)164 	public final boolean clearOwner(final long kmer, final int owner){
165 		KmerLink n=get(kmer);
166 		assert(n!=null);
167 		synchronized(n){
168 			if(n.owner==owner){
169 				n.owner=-1;
170 				return true;
171 			}
172 		}
173 		return false;
174 	}
175 
176 	@Override
getOwner(final long kmer)177 	public final int getOwner(final long kmer){
178 		KmerLink n=get(kmer);
179 		assert(n!=null);
180 		return n.owner;
181 	}
182 
183 	/*--------------------------------------------------------------*/
184 
185 	@Override
set(long kmer, int[] vals, int vlen)186 	public int set(long kmer, int[] vals, int vlen) {
187 		throw new RuntimeException("Unimplemented.");
188 	}
189 
190 	@Override
getValue(long kmer)191 	public final int getValue(long kmer){
192 		KmerLink n=get(kmer);
193 		return n==null ? -1 : n.value;
194 	}
195 
196 	@Override
getValues(long kmer, int[] singleton)197 	public final int[] getValues(long kmer, int[] singleton){
198 		KmerLink n=get(kmer);
199 		if(n==null){return null;}
200 		singleton[0]=n.value;
201 		return singleton;
202 	}
203 
204 	@Override
size()205 	public final long size() {
206 		if(value<1){return 0;}
207 		long size=1;
208 		if(next!=null){size+=next.size();}
209 		return size;
210 	}
211 
212 	/*--------------------------------------------------------------*/
213 	/*----------------         Info Dumping         ----------------*/
214 	/*--------------------------------------------------------------*/
215 
216 	@Override
dumpKmersAsBytes(ByteStreamWriter bsw, int k, int mincount, int maxcount, AtomicLong remaining)217 	public final boolean dumpKmersAsBytes(ByteStreamWriter bsw, int k, int mincount, int maxcount, AtomicLong remaining){
218 		if(value<1){return true;}
219 		if(value>=mincount){
220 			if(remaining!=null && remaining.decrementAndGet()<0){return true;}
221 			bsw.printlnKmer(pivot, value, k);
222 		}
223 		if(next!=null){next.dumpKmersAsBytes(bsw, k, mincount, maxcount, remaining);}
224 		return true;
225 	}
226 
227 	@Override
dumpKmersAsBytes_MT(final ByteStreamWriter bsw, final ByteBuilder bb, final int k, final int mincount, int maxcount, AtomicLong remaining)228 	public final boolean dumpKmersAsBytes_MT(final ByteStreamWriter bsw, final ByteBuilder bb, final int k, final int mincount, int maxcount, AtomicLong remaining){
229 		if(value<1){return true;}
230 		if(value>=mincount){
231 			if(remaining!=null && remaining.decrementAndGet()<0){return true;}
232 			toBytes(pivot, value, k, bb);
233 			bb.nl();
234 			if(bb.length()>=16000){
235 				ByteBuilder bb2=new ByteBuilder(bb);
236 				synchronized(bsw){bsw.addJob(bb2);}
237 				bb.clear();
238 			}
239 		}
240 		if(next!=null){next.dumpKmersAsBytes_MT(bsw, bb, k, mincount, maxcount, remaining);}
241 		return true;
242 	}
243 
244 	@Override
dumpKmersAsText(TextStreamWriter tsw, int k, int mincount, int maxcount)245 	public final boolean dumpKmersAsText(TextStreamWriter tsw, int k, int mincount, int maxcount) {
246 		tsw.print(dumpKmersAsText(new StringBuilder(32), k, mincount, maxcount));
247 		return true;
248 	}
249 
dumpKmersAsText(StringBuilder sb, int k, int mincount, int maxcount)250 	private final StringBuilder dumpKmersAsText(StringBuilder sb, int k, int mincount, int maxcount){
251 		if(value<1){return sb;}
252 		if(sb==null){sb=new StringBuilder(32);}
253 		if(value>=mincount){sb.append(AbstractKmerTable.toText(pivot, value, k)).append('\n');}
254 		if(next!=null){next.dumpKmersAsText(sb, k, mincount, maxcount);}
255 		return sb;
256 	}
257 
258 	@Override
fillHistogram(long[] ca, int max)259 	public final void fillHistogram(long[] ca, int max){
260 		if(value<1){return;}
261 		ca[Tools.min(value, max)]++;
262 		if(next!=null){next.fillHistogram(ca, max);}
263 	}
264 
265 	@Override
fillHistogram(SuperLongList sll)266 	public final void fillHistogram(SuperLongList sll){
267 		if(value<1){return;}
268 		sll.add(value);
269 		if(next!=null){next.fillHistogram(sll);}
270 	}
271 
272 	@Override
countGC(long[] gcCounts, int max)273 	public void countGC(long[] gcCounts, int max){
274 		if(value<1){return;}
275 		gcCounts[Tools.min(value, max)]+=gc(pivot);
276 		if(next!=null){next.countGC(gcCounts, max);}
277 	}
278 
279 
280 	/*--------------------------------------------------------------*/
281 	/*----------------       Private Methods        ----------------*/
282 	/*--------------------------------------------------------------*/
283 
284 	/*--------------------------------------------------------------*/
285 	/*----------------       Invalid Methods        ----------------*/
286 	/*--------------------------------------------------------------*/
287 
rebalance(ArrayList<KmerLink> list)288 	KmerLink rebalance(ArrayList<KmerLink> list){
289 		throw new RuntimeException("Unsupported.");
290 	}
291 
rebalance(ArrayList<KmerLink> list, int a, int b)292 	private static KmerLink rebalance(ArrayList<KmerLink> list, int a, int b){
293 		throw new RuntimeException("Unsupported.");
294 	}
295 
296 	@Deprecated
297 	@Override
regenerate(final int limit)298 	public long regenerate(final int limit){
299 		throw new RuntimeException("TODO - remove zero-value links.");
300 	}
301 
302 	/*--------------------------------------------------------------*/
303 	/*----------------            Fields            ----------------*/
304 	/*--------------------------------------------------------------*/
305 
306 	long pivot;
307 	int value;
308 	int owner=-1;
309 	KmerLink next;
310 }
311