1 | package net.spy.memcached.internal; |
2 | |
3 | import java.util.Collection; |
4 | import java.util.Collections; |
5 | import java.util.concurrent.TimeoutException; |
6 | |
7 | import net.spy.memcached.MemcachedNode; |
8 | import net.spy.memcached.ops.Operation; |
9 | |
10 | /** |
11 | * Timeout exception that tracks the original operation. |
12 | */ |
13 | public class CheckedOperationTimeoutException extends TimeoutException { |
14 | |
15 | private final Collection<Operation> operations; |
16 | |
17 | /** |
18 | * Construct a CheckedOperationTimeoutException with the given message |
19 | * and operation. |
20 | * |
21 | * @param message the message |
22 | * @param op the operation that timed out |
23 | */ |
24 | public CheckedOperationTimeoutException(String message, Operation op) { |
25 | this(message, Collections.singleton(op)); |
26 | } |
27 | |
28 | public CheckedOperationTimeoutException(String message, |
29 | Collection<Operation> ops) { |
30 | super(createMessage(message, ops)); |
31 | operations = ops; |
32 | } |
33 | |
34 | private static String createMessage(String message, |
35 | Collection<Operation> ops) { |
36 | StringBuilder rv = new StringBuilder(message); |
37 | rv.append(" - failing node"); |
38 | rv.append(ops.size() == 1 ? ": " : "s: "); |
39 | boolean first = true; |
40 | for(Operation op : ops) { |
41 | if(first) { |
42 | first = false; |
43 | } else { |
44 | rv.append(", "); |
45 | } |
46 | MemcachedNode node = op == null ? null : op.getHandlingNode(); |
47 | rv.append(node == null ? "<unknown>" : node.getSocketAddress()); |
48 | } |
49 | return rv.toString(); |
50 | } |
51 | |
52 | /** |
53 | * Get the operation that timed out. |
54 | */ |
55 | public Collection<Operation> getOperations() { |
56 | return operations; |
57 | } |
58 | } |