1 | package net.spy.memcached; |
2 | |
3 | import java.util.Collection; |
4 | import java.util.Collections; |
5 | import java.util.List; |
6 | import java.util.concurrent.BlockingQueue; |
7 | |
8 | import net.spy.memcached.ops.Operation; |
9 | import net.spy.memcached.ops.OperationQueueFactory; |
10 | import net.spy.memcached.protocol.ascii.AsciiOperationFactory; |
11 | import net.spy.memcached.protocol.binary.BinaryOperationFactory; |
12 | import net.spy.memcached.transcoders.Transcoder; |
13 | |
14 | /** |
15 | * Builder for more easily configuring a ConnectionFactory. |
16 | */ |
17 | public class ConnectionFactoryBuilder { |
18 | |
19 | private OperationQueueFactory opQueueFactory; |
20 | private OperationQueueFactory readQueueFactory; |
21 | private OperationQueueFactory writeQueueFactory; |
22 | |
23 | private Transcoder<Object> transcoder; |
24 | |
25 | private FailureMode failureMode; |
26 | |
27 | private Collection<ConnectionObserver> initialObservers |
28 | = Collections.emptyList(); |
29 | |
30 | private OperationFactory opFact; |
31 | |
32 | private Locator locator = Locator.ARRAY_MOD; |
33 | private long opTimeout = -1; |
34 | private boolean isDaemon = true; |
35 | private boolean shouldOptimize = true; |
36 | private boolean useNagle = false; |
37 | private long maxReconnectDelay = |
38 | DefaultConnectionFactory.DEFAULT_MAX_RECONNECT_DELAY; |
39 | |
40 | private int readBufSize = -1; |
41 | private HashAlgorithm hashAlg; |
42 | |
43 | /** |
44 | * Set the operation queue factory. |
45 | */ |
46 | public ConnectionFactoryBuilder setOpQueueFactory(OperationQueueFactory q) { |
47 | opQueueFactory = q; |
48 | return this; |
49 | } |
50 | |
51 | /** |
52 | * Set the read queue factory. |
53 | */ |
54 | public ConnectionFactoryBuilder setReadOpQueueFactory(OperationQueueFactory q) { |
55 | readQueueFactory = q; |
56 | return this; |
57 | } |
58 | |
59 | /** |
60 | * Set the write queue factory. |
61 | */ |
62 | public ConnectionFactoryBuilder setWriteOpQueueFactory(OperationQueueFactory q) { |
63 | writeQueueFactory = q; |
64 | return this; |
65 | } |
66 | |
67 | /** |
68 | * Set the default transcoder. |
69 | */ |
70 | public ConnectionFactoryBuilder setTranscoder(Transcoder<Object> t) { |
71 | transcoder = t; |
72 | return this; |
73 | } |
74 | |
75 | /** |
76 | * Set the failure mode. |
77 | */ |
78 | public ConnectionFactoryBuilder setFailureMode(FailureMode fm) { |
79 | failureMode = fm; |
80 | return this; |
81 | } |
82 | |
83 | /** |
84 | * Set the initial connection observers (will observe initial connection). |
85 | */ |
86 | public ConnectionFactoryBuilder setInitialObservers( |
87 | Collection<ConnectionObserver> obs) { |
88 | initialObservers = obs; |
89 | return this; |
90 | } |
91 | |
92 | /** |
93 | * Set the operation factory. |
94 | * |
95 | * Note that the operation factory is used to also imply the type of |
96 | * nodes to create. |
97 | * |
98 | * @see MemcachedNode |
99 | */ |
100 | public ConnectionFactoryBuilder setOpFact(OperationFactory f) { |
101 | opFact = f; |
102 | return this; |
103 | } |
104 | |
105 | /** |
106 | * Set the default operation timeout in milliseconds. |
107 | */ |
108 | public ConnectionFactoryBuilder setOpTimeout(long t) { |
109 | opTimeout = t; |
110 | return this; |
111 | } |
112 | |
113 | /** |
114 | * Set the daemon state of the IO thread (defaults to true). |
115 | */ |
116 | public ConnectionFactoryBuilder setDaemon(boolean d) { |
117 | isDaemon = d; |
118 | return this; |
119 | } |
120 | |
121 | /** |
122 | * Set to false if the default operation optimization is not desirable. |
123 | */ |
124 | public ConnectionFactoryBuilder setShouldOptimize(boolean o) { |
125 | shouldOptimize = o; |
126 | return this; |
127 | } |
128 | |
129 | /** |
130 | * Set the read buffer size. |
131 | */ |
132 | public ConnectionFactoryBuilder setReadBufferSize(int to) { |
133 | readBufSize = to; |
134 | return this; |
135 | } |
136 | |
137 | /** |
138 | * Set the hash algorithm. |
139 | */ |
140 | public ConnectionFactoryBuilder setHashAlg(HashAlgorithm to) { |
141 | hashAlg = to; |
142 | return this; |
143 | } |
144 | |
145 | /** |
146 | * Set to true if you'd like to enable the Nagle algorithm. |
147 | */ |
148 | public ConnectionFactoryBuilder setUseNagleAlgorithm(boolean to) { |
149 | useNagle = to; |
150 | return this; |
151 | } |
152 | |
153 | /** |
154 | * Convenience method to specify the protocol to use. |
155 | */ |
156 | public ConnectionFactoryBuilder setProtocol(Protocol prot) { |
157 | switch(prot) { |
158 | case TEXT: |
159 | opFact = new AsciiOperationFactory(); |
160 | break; |
161 | case BINARY: |
162 | opFact = new BinaryOperationFactory(); |
163 | break; |
164 | default: assert false : "Unhandled protocol: " + prot; |
165 | } |
166 | return this; |
167 | } |
168 | |
169 | /** |
170 | * Set the locator type. |
171 | */ |
172 | public ConnectionFactoryBuilder setLocatorType(Locator l) { |
173 | locator = l; |
174 | return this; |
175 | } |
176 | |
177 | /** |
178 | * Set the maximum reconnect delay. |
179 | */ |
180 | public ConnectionFactoryBuilder setMaxReconnectDelay(long to) { |
181 | assert to > 0 : "Reconnect delay must be a positive number"; |
182 | maxReconnectDelay = to; |
183 | return this; |
184 | } |
185 | |
186 | /** |
187 | * Get the ConnectionFactory set up with the provided parameters. |
188 | */ |
189 | public ConnectionFactory build() { |
190 | return new DefaultConnectionFactory() { |
191 | |
192 | @Override |
193 | public BlockingQueue<Operation> createOperationQueue() { |
194 | return opQueueFactory == null ? |
195 | super.createOperationQueue() : opQueueFactory.create(); |
196 | } |
197 | |
198 | @Override |
199 | public BlockingQueue<Operation> createReadOperationQueue() { |
200 | return readQueueFactory == null ? |
201 | super.createReadOperationQueue() |
202 | : readQueueFactory.create(); |
203 | } |
204 | |
205 | @Override |
206 | public BlockingQueue<Operation> createWriteOperationQueue() { |
207 | return writeQueueFactory == null ? |
208 | super.createReadOperationQueue() |
209 | : writeQueueFactory.create(); |
210 | } |
211 | |
212 | @Override |
213 | public NodeLocator createLocator(List<MemcachedNode> nodes) { |
214 | switch(locator) { |
215 | case ARRAY_MOD: |
216 | return new ArrayModNodeLocator(nodes, getHashAlg()); |
217 | case CONSISTENT: |
218 | return new KetamaNodeLocator(nodes, getHashAlg()); |
219 | default: throw new IllegalStateException( |
220 | "Unhandled locator type: " + locator); |
221 | } |
222 | } |
223 | |
224 | @Override |
225 | public Transcoder<Object> getDefaultTranscoder() { |
226 | return transcoder == null ? |
227 | super.getDefaultTranscoder() : transcoder; |
228 | } |
229 | |
230 | @Override |
231 | public FailureMode getFailureMode() { |
232 | return failureMode == null ? |
233 | super.getFailureMode() : failureMode; |
234 | } |
235 | |
236 | @Override |
237 | public HashAlgorithm getHashAlg() { |
238 | return hashAlg == null ? super.getHashAlg() : hashAlg; |
239 | } |
240 | |
241 | @Override |
242 | public Collection<ConnectionObserver> getInitialObservers() { |
243 | return initialObservers; |
244 | } |
245 | |
246 | @Override |
247 | public OperationFactory getOperationFactory() { |
248 | return opFact == null ? super.getOperationFactory() : opFact; |
249 | } |
250 | |
251 | @Override |
252 | public long getOperationTimeout() { |
253 | return opTimeout == -1 ? |
254 | super.getOperationTimeout() : opTimeout; |
255 | } |
256 | |
257 | @Override |
258 | public int getReadBufSize() { |
259 | return readBufSize == -1 ? |
260 | super.getReadBufSize() : readBufSize; |
261 | } |
262 | |
263 | @Override |
264 | public boolean isDaemon() { |
265 | return isDaemon; |
266 | } |
267 | |
268 | @Override |
269 | public boolean shouldOptimize() { |
270 | return shouldOptimize; |
271 | } |
272 | |
273 | @Override |
274 | public boolean useNagleAlgorithm() { |
275 | return useNagle; |
276 | } |
277 | |
278 | @Override |
279 | public long getMaxReconnectDelay() { |
280 | return maxReconnectDelay; |
281 | } |
282 | |
283 | }; |
284 | |
285 | } |
286 | |
287 | /** |
288 | * Type of protocol to use for connections. |
289 | */ |
290 | public static enum Protocol { |
291 | /** |
292 | * Use the text (ascii) protocol. |
293 | */ |
294 | TEXT, |
295 | /** |
296 | * Use the binary protocol. |
297 | */ |
298 | BINARY |
299 | } |
300 | |
301 | /** |
302 | * Type of node locator to use. |
303 | */ |
304 | public static enum Locator { |
305 | /** |
306 | * Array modulus - the classic node location algorithm. |
307 | */ |
308 | ARRAY_MOD, |
309 | /** |
310 | * Consistent hash algorithm. |
311 | * |
312 | * This uses ketema's distribution algorithm, but may be used with any |
313 | * hash algorithm. |
314 | */ |
315 | CONSISTENT |
316 | } |
317 | } |