Refactor partition gathering.
RingBuilder._reassign_parts() is really moving one (partition, replica) pair at a time. However, the way that _gather_reassign_parts passes that data in was strange; it would update each replica's entry in _replica2part2dev to 0xffff, then return a list of affected partitions. Now it just returns the pairs to move. This is helpful in the presence of bugs that affect partition assignment (e.g. #943493), there's no chance of stray 0xffff values hanging around and corrupting the partition map. Also, update my email address. Change-Id: Ifb3aeb4fac750f66e2ddbad88eb5846e72bac20c
This commit is contained in:
parent
3c7e983793
commit
e994d033a6
2
AUTHORS
2
AUTHORS
@ -39,7 +39,7 @@ Dragos Manolescu (dragosm@hp.com)
|
|||||||
Juan J. Martinez (juan@memset.com)
|
Juan J. Martinez (juan@memset.com)
|
||||||
Donagh McCabe (donagh.mccabe@hp.com)
|
Donagh McCabe (donagh.mccabe@hp.com)
|
||||||
Ewan Mellor (ewan.mellor@citrix.com)
|
Ewan Mellor (ewan.mellor@citrix.com)
|
||||||
Samuel Merritt (spam@andcheese.org)
|
Samuel Merritt (sam@swiftstack.com)
|
||||||
Stephen Milton (milton@isomedia.com)
|
Stephen Milton (milton@isomedia.com)
|
||||||
Russ Nelson (russ@crynwr.com)
|
Russ Nelson (russ@crynwr.com)
|
||||||
Maru Newby (mnewby@internap.com)
|
Maru Newby (mnewby@internap.com)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from array import array
|
from array import array
|
||||||
|
from collections import defaultdict
|
||||||
from random import randint, shuffle
|
from random import randint, shuffle
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
@ -449,11 +450,11 @@ class RingBuilder(object):
|
|||||||
|
|
||||||
def _gather_reassign_parts(self):
|
def _gather_reassign_parts(self):
|
||||||
"""
|
"""
|
||||||
Returns an array('I') of partitions to be reassigned by gathering them
|
Returns a list of (partition, replicas) pairs to be reassigned
|
||||||
from removed devices and overweight devices.
|
by gathering them from removed devices and overweight devices.
|
||||||
"""
|
"""
|
||||||
removed_dev_parts = set()
|
reassign_parts = defaultdict(list)
|
||||||
reassign_parts = array('I')
|
removed_dev_parts = defaultdict(list)
|
||||||
if self._remove_devs:
|
if self._remove_devs:
|
||||||
dev_ids = [d['id'] for d in self._remove_devs if d['parts']]
|
dev_ids = [d['id'] for d in self._remove_devs if d['parts']]
|
||||||
if dev_ids:
|
if dev_ids:
|
||||||
@ -461,9 +462,8 @@ class RingBuilder(object):
|
|||||||
part2dev = self._replica2part2dev[replica]
|
part2dev = self._replica2part2dev[replica]
|
||||||
for part in xrange(self.parts):
|
for part in xrange(self.parts):
|
||||||
if part2dev[part] in dev_ids:
|
if part2dev[part] in dev_ids:
|
||||||
part2dev[part] = 0xffff
|
|
||||||
self._last_part_moves[part] = 0
|
self._last_part_moves[part] = 0
|
||||||
removed_dev_parts.add(part)
|
removed_dev_parts[part].append(replica)
|
||||||
|
|
||||||
start = self._last_part_gather_start / 4 + randint(0, self.parts / 2)
|
start = self._last_part_gather_start / 4 + randint(0, self.parts / 2)
|
||||||
self._last_part_gather_start = start
|
self._last_part_gather_start = start
|
||||||
@ -477,15 +477,16 @@ class RingBuilder(object):
|
|||||||
continue
|
continue
|
||||||
dev = self.devs[part2dev[part]]
|
dev = self.devs[part2dev[part]]
|
||||||
if dev['parts_wanted'] < 0:
|
if dev['parts_wanted'] < 0:
|
||||||
part2dev[part] = 0xffff
|
|
||||||
self._last_part_moves[part] = 0
|
self._last_part_moves[part] = 0
|
||||||
dev['parts_wanted'] += 1
|
dev['parts_wanted'] += 1
|
||||||
dev['parts'] -= 1
|
dev['parts'] -= 1
|
||||||
reassign_parts.append(part)
|
reassign_parts[part].append(replica)
|
||||||
|
|
||||||
reassign_parts.extend(removed_dev_parts)
|
reassign_parts.update(removed_dev_parts)
|
||||||
shuffle(reassign_parts)
|
|
||||||
return reassign_parts
|
reassign_parts_list = list(reassign_parts.iteritems())
|
||||||
|
shuffle(reassign_parts_list)
|
||||||
|
return reassign_parts_list
|
||||||
|
|
||||||
def _reassign_parts(self, reassign_parts):
|
def _reassign_parts(self, reassign_parts):
|
||||||
"""
|
"""
|
||||||
@ -502,11 +503,12 @@ class RingBuilder(object):
|
|||||||
available_devs = \
|
available_devs = \
|
||||||
sorted((d for d in self.devs if d is not None and d['weight']),
|
sorted((d for d in self.devs if d is not None and d['weight']),
|
||||||
key=lambda x: x['sort_key'])
|
key=lambda x: x['sort_key'])
|
||||||
for part in reassign_parts:
|
|
||||||
|
for part, replace_replicas in reassign_parts:
|
||||||
other_zones = array('H')
|
other_zones = array('H')
|
||||||
replace = []
|
replace = []
|
||||||
for replica in xrange(self.replicas):
|
for replica in xrange(self.replicas):
|
||||||
if self._replica2part2dev[replica][part] == 0xffff:
|
if replica in replace_replicas:
|
||||||
replace.append(replica)
|
replace.append(replica)
|
||||||
else:
|
else:
|
||||||
other_zones.append(self.devs[
|
other_zones.append(self.devs[
|
||||||
|
@ -179,7 +179,7 @@ class TestRingBuilder(unittest.TestCase):
|
|||||||
max_run = 0
|
max_run = 0
|
||||||
run = 0
|
run = 0
|
||||||
last_part = 0
|
last_part = 0
|
||||||
for part in parts:
|
for part, _ in parts:
|
||||||
if part > last_part:
|
if part > last_part:
|
||||||
run += 1
|
run += 1
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user