1 | package net.spy.memcached.util; |
2 | |
3 | import java.util.HashMap; |
4 | import java.util.Map; |
5 | |
6 | import net.spy.memcached.MemcachedNode; |
7 | |
8 | /** |
9 | * A Default implementation of the configuration required for the |
10 | * KetamaNodeLocator algorithm to run. |
11 | */ |
12 | public class DefaultKetamaNodeLocatorConfiguration implements |
13 | KetamaNodeLocatorConfiguration { |
14 | |
15 | final int NUM_REPS=160; |
16 | |
17 | // Internal lookup map to try to carry forward the optimisation that was |
18 | // previously in KetamaNodeLocator |
19 | protected Map<MemcachedNode, String> socketAddresses= |
20 | new HashMap<MemcachedNode, String>(); |
21 | |
22 | /** |
23 | * Returns the socket address of a given MemcachedNode. |
24 | * |
25 | * @param node The node which we're interested in |
26 | * @return String the socket address of that node. |
27 | */ |
28 | protected String getSocketAddressForNode(MemcachedNode node) { |
29 | // Using the internal map retrieve the socket addresses |
30 | // for given nodes. |
31 | // I'm aware that this code is inherently thread-unsafe as |
32 | // I'm using a HashMap implementation of the map, but the worst |
33 | // case ( I believe) is we're slightly in-efficient when |
34 | // a node has never been seen before concurrently on two different |
35 | // threads, so it the socketaddress will be requested multiple times! |
36 | // all other cases should be as fast as possible. |
37 | String result=socketAddresses.get(node); |
38 | if(result == null) { |
39 | result=String.valueOf(node.getSocketAddress()); |
40 | socketAddresses.put(node, result); |
41 | } |
42 | return result; |
43 | } |
44 | |
45 | /** |
46 | * Returns the number of discrete hashes that should be defined for each |
47 | * node in the continuum. |
48 | * |
49 | * @return NUM_REPS repetitions. |
50 | */ |
51 | public int getNodeRepetitions() { |
52 | return NUM_REPS; |
53 | } |
54 | |
55 | /** |
56 | * Returns a uniquely identifying key, suitable for hashing by the |
57 | * KetamaNodeLocator algorithm. |
58 | * |
59 | * <p> |
60 | * This default implementation uses the socket-address of the MemcachedNode |
61 | * and concatenates it with a hyphen directly against the repetition number |
62 | * for example a key for a particular server's first repetition may look |
63 | * like: |
64 | * <p> |
65 | * |
66 | * <p> |
67 | * <code>myhost/10.0.2.1-0</code> |
68 | * </p> |
69 | * |
70 | * <p>for the second repetition</p> |
71 | * |
72 | * <p><code>myhost/10.0.2.1-1</code></p> |
73 | * |
74 | * <p> |
75 | * for a server where reverse lookups are failing the returned keys |
76 | * may look like |
77 | * </p> |
78 | * |
79 | * <p> |
80 | * <code>/10.0.2.1-0</code> and <code>/10.0.2.1-1</code> |
81 | * </p> |
82 | * |
83 | * @param node The MemcachedNode to use to form the unique identifier |
84 | * @param repetition The repetition number for the particular node in |
85 | * question (0 is the first repetition) |
86 | * @return The key that represents the specific repetition of the |
87 | * node |
88 | */ |
89 | public String getKeyForNode(MemcachedNode node, int repetition) { |
90 | return getSocketAddressForNode(node) + "-" + repetition; |
91 | } |
92 | } |