Merge lp:~david-goetz/swift/zero_handoff into lp:~hudson-openstack/swift/trunk

Proposed by David Goetz
Status: Merged
Approved by: gholt
Approved revision: 211
Merged at revision: 224
Proposed branch: lp:~david-goetz/swift/zero_handoff
Merge into: lp:~hudson-openstack/swift/trunk
Diff against target: 197 lines (+68/-27)
2 files modified
swift/common/ring/ring.py (+9/-1)
test/unit/common/ring/test_ring.py (+59/-26)
To merge this branch: bzr merge lp:~david-goetz/swift/zero_handoff
Reviewer Review Type Date Requested Status
gholt (community) Approve
Review via email: mp+50080@code.launchpad.net

Description of the change

nodes with a weight of zero should not be valid for handoff

To post a comment you must log in.
Revision history for this message
gholt (gholt) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'swift/common/ring/ring.py'
2--- swift/common/ring/ring.py 2011-02-16 15:02:38 +0000
3+++ swift/common/ring/ring.py 2011-02-17 00:41:31 +0000
4@@ -141,4 +141,12 @@
5 zones.remove(self.devs[part2dev_id[part]]['zone'])
6 while zones:
7 zone = zones.pop(part % len(zones))
8- yield self.zone2devs[zone][part % len(self.zone2devs[zone])]
9+ weighted_node = None
10+ for i in xrange(len(self.zone2devs[zone])):
11+ node = self.zone2devs[zone][(part + i) %
12+ len(self.zone2devs[zone])]
13+ if node.get('weight'):
14+ weighted_node = node
15+ break
16+ if weighted_node:
17+ yield weighted_node
18
19=== modified file 'test/unit/common/ring/test_ring.py'
20--- test/unit/common/ring/test_ring.py 2011-02-16 15:02:38 +0000
21+++ test/unit/common/ring/test_ring.py 2011-02-17 00:41:31 +0000
22@@ -50,7 +50,8 @@
23 os.mkdir(self.testdir)
24 self.testgz = os.path.join(self.testdir, 'ring.gz')
25 self.intended_replica2part2dev_id = [[0, 2, 0, 2], [2, 0, 2, 0]]
26- self.intended_devs = [{'id': 0, 'zone': 0}, None, {'id': 2, 'zone': 2}]
27+ self.intended_devs = [{'id': 0, 'zone': 0, 'weight': 1.0}, None,
28+ {'id': 2, 'zone': 2, 'weight': 1.0}]
29 self.intended_part_shift = 30
30 self.intended_reload_time = 15
31 pickle.dump(ring.RingData(self.intended_replica2part2dev_id,
32@@ -79,7 +80,7 @@
33
34 def test_has_changed(self):
35 self.assertEquals(self.ring.has_changed(), False)
36- os.utime(self.testgz, (time()+60, time()+60))
37+ os.utime(self.testgz, (time() + 60, time() + 60))
38 self.assertEquals(self.ring.has_changed(), True)
39
40 def test_reload(self):
41@@ -87,7 +88,7 @@
42 self.ring = ring.Ring(self.testgz, reload_time=0.001)
43 orig_mtime = self.ring._mtime
44 self.assertEquals(len(self.ring.devs), 3)
45- self.intended_devs.append({'id': 3, 'zone': 3})
46+ self.intended_devs.append({'id': 3, 'zone': 3, 'weight': 1.0})
47 pickle.dump(ring.RingData(self.intended_replica2part2dev_id,
48 self.intended_devs, self.intended_part_shift),
49 GzipFile(self.testgz, 'wb'))
50@@ -100,7 +101,7 @@
51 self.ring = ring.Ring(self.testgz, reload_time=0.001)
52 orig_mtime = self.ring._mtime
53 self.assertEquals(len(self.ring.devs), 4)
54- self.intended_devs.append({'id': 4, 'zone': 4})
55+ self.intended_devs.append({'id': 4, 'zone': 4, 'weight': 1.0})
56 pickle.dump(ring.RingData(self.intended_replica2part2dev_id,
57 self.intended_devs, self.intended_part_shift),
58 GzipFile(self.testgz, 'wb'))
59@@ -115,7 +116,7 @@
60 orig_mtime = self.ring._mtime
61 part, nodes = self.ring.get_nodes('a')
62 self.assertEquals(len(self.ring.devs), 5)
63- self.intended_devs.append({'id': 5, 'zone': 5})
64+ self.intended_devs.append({'id': 5, 'zone': 5, 'weight': 1.0})
65 pickle.dump(ring.RingData(self.intended_replica2part2dev_id,
66 self.intended_devs, self.intended_part_shift),
67 GzipFile(self.testgz, 'wb'))
68@@ -134,57 +135,71 @@
69 self.assertRaises(TypeError, self.ring.get_nodes)
70 part, nodes = self.ring.get_nodes('a')
71 self.assertEquals(part, 0)
72- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
73+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
74+ {'id': 2, 'zone': 2, 'weight': 1.0}])
75 part, nodes = self.ring.get_nodes('a1')
76 self.assertEquals(part, 0)
77- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
78+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
79+ {'id': 2, 'zone': 2, 'weight': 1.0}])
80 part, nodes = self.ring.get_nodes('a4')
81 self.assertEquals(part, 1)
82- self.assertEquals(nodes, [{'id': 2, 'zone': 2}, {'id': 0, 'zone': 0}])
83+ self.assertEquals(nodes, [{'id': 2, 'zone': 2, 'weight': 1.0},
84+ {'id': 0, 'zone': 0, 'weight': 1.0}])
85 part, nodes = self.ring.get_nodes('aa')
86 self.assertEquals(part, 1)
87- self.assertEquals(nodes, [{'id': 2, 'zone': 2}, {'id': 0, 'zone': 0}])
88+ self.assertEquals(nodes, [{'id': 2, 'zone': 2, 'weight': 1.0},
89+ {'id': 0, 'zone': 0, 'weight': 1.0}])
90
91 part, nodes = self.ring.get_nodes('a', 'c1')
92 self.assertEquals(part, 0)
93- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
94+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
95+ {'id': 2, 'zone': 2, 'weight': 1.0}])
96 part, nodes = self.ring.get_nodes('a', 'c0')
97 self.assertEquals(part, 3)
98- self.assertEquals(nodes, [{'id': 2, 'zone': 2}, {'id': 0, 'zone': 0}])
99+ self.assertEquals(nodes, [{'id': 2, 'zone': 2, 'weight': 1.0},
100+ {'id': 0, 'zone': 0, 'weight': 1.0}])
101 part, nodes = self.ring.get_nodes('a', 'c3')
102 self.assertEquals(part, 2)
103- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
104+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
105+ {'id': 2, 'zone': 2, 'weight': 1.0}])
106 part, nodes = self.ring.get_nodes('a', 'c2')
107 self.assertEquals(part, 2)
108- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
109+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
110+ {'id': 2, 'zone': 2, 'weight': 1.0}])
111
112 part, nodes = self.ring.get_nodes('a', 'c', 'o1')
113 self.assertEquals(part, 1)
114- self.assertEquals(nodes, [{'id': 2, 'zone': 2}, {'id': 0, 'zone': 0}])
115+ self.assertEquals(nodes, [{'id': 2, 'zone': 2, 'weight': 1.0},
116+ {'id': 0, 'zone': 0, 'weight': 1.0}])
117 part, nodes = self.ring.get_nodes('a', 'c', 'o5')
118 self.assertEquals(part, 0)
119- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
120+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
121+ {'id': 2, 'zone': 2, 'weight': 1.0}])
122 part, nodes = self.ring.get_nodes('a', 'c', 'o0')
123 self.assertEquals(part, 0)
124- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
125+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
126+ {'id': 2, 'zone': 2, 'weight': 1.0}])
127 part, nodes = self.ring.get_nodes('a', 'c', 'o2')
128 self.assertEquals(part, 2)
129- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
130+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
131+ {'id': 2, 'zone': 2, 'weight': 1.0}])
132
133 def test_get_more_nodes(self):
134 # Yes, these tests are deliberately very fragile. We want to make sure
135 # that if someone changes the results the ring produces, they know it.
136 part, nodes = self.ring.get_nodes('a', 'c', 'o2')
137 self.assertEquals(part, 2)
138- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
139+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
140+ {'id': 2, 'zone': 2, 'weight': 1.0}])
141 nodes = list(self.ring.get_more_nodes(part))
142 self.assertEquals(nodes, [])
143
144- self.ring.devs.append({'id': 3, 'zone': 0})
145+ self.ring.devs.append({'id': 3, 'zone': 0, 'weight': 1.0})
146 self.ring.zone2devs[0].append(self.ring.devs[3])
147 part, nodes = self.ring.get_nodes('a', 'c', 'o2')
148 self.assertEquals(part, 2)
149- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
150+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
151+ {'id': 2, 'zone': 2, 'weight': 1.0}])
152 nodes = list(self.ring.get_more_nodes(part))
153 self.assertEquals(nodes, [])
154
155@@ -193,18 +208,36 @@
156 self.ring.zone2devs[3] = [self.ring.devs[3]]
157 part, nodes = self.ring.get_nodes('a', 'c', 'o2')
158 self.assertEquals(part, 2)
159- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
160+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
161+ {'id': 2, 'zone': 2, 'weight': 1.0}])
162 nodes = list(self.ring.get_more_nodes(part))
163- self.assertEquals(nodes, [{'id': 3, 'zone': 3}])
164+ self.assertEquals(nodes, [{'id': 3, 'zone': 3, 'weight': 1.0}])
165
166 self.ring.devs.append(None)
167- self.ring.devs.append({'id': 5, 'zone': 5})
168+ self.ring.devs.append({'id': 5, 'zone': 5, 'weight': 1.0})
169 self.ring.zone2devs[5] = [self.ring.devs[5]]
170 part, nodes = self.ring.get_nodes('a', 'c', 'o2')
171 self.assertEquals(part, 2)
172- self.assertEquals(nodes, [{'id': 0, 'zone': 0}, {'id': 2, 'zone': 2}])
173- nodes = list(self.ring.get_more_nodes(part))
174- self.assertEquals(nodes, [{'id': 3, 'zone': 3}, {'id': 5, 'zone': 5}])
175+ self.assertEquals(nodes, [{'id': 0, 'zone': 0, 'weight': 1.0},
176+ {'id': 2, 'zone': 2, 'weight': 1.0}])
177+ nodes = list(self.ring.get_more_nodes(part))
178+ self.assertEquals(nodes, [{'id': 3, 'zone': 3, 'weight': 1.0},
179+ {'id': 5, 'zone': 5, 'weight': 1.0}])
180+
181+ self.ring.devs.append({'id': 6, 'zone': 5, 'weight': 1.0})
182+ self.ring.zone2devs[5].append(self.ring.devs[6])
183+ nodes = list(self.ring.get_more_nodes(part))
184+ self.assertEquals(nodes, [{'id': 3, 'zone': 3, 'weight': 1.0},
185+ {'id': 5, 'zone': 5, 'weight': 1.0}])
186+ self.ring.devs[5]['weight'] = 0
187+ nodes = list(self.ring.get_more_nodes(part))
188+ self.assertEquals(nodes, [{'id': 3, 'zone': 3, 'weight': 1.0},
189+ {'id': 6, 'zone': 5, 'weight': 1.0}])
190+ self.ring.devs[3]['weight'] = 0
191+ self.ring.devs.append({'id': 7, 'zone': 6, 'weight': 0.0})
192+ self.ring.zone2devs[6] = [self.ring.devs[7]]
193+ nodes = list(self.ring.get_more_nodes(part))
194+ self.assertEquals(nodes, [{'id': 6, 'zone': 5, 'weight': 1.0}])
195
196
197 if __name__ == '__main__':