Merge "Unify different ring-balancing methods."

This commit is contained in:
Jenkins 2012-04-19 21:09:26 +00:00 committed by Gerrit Code Review
commit 7ed3dc7e1b

View File

@ -391,46 +391,17 @@ class RingBuilder(object):
def _initial_balance(self):
"""
Initial partition assignment is treated separately from rebalancing an
existing ring. Initial assignment is performed by ordering all the
devices by how many partitions they still want (and kept in order
during the process). The partitions are then iterated through,
assigning them to the next "most wanted" device, with distinct zone
restrictions.
Initial partition assignment is the same as rebalancing an
existing ring, but with some initial setup beforehand.
"""
for dev in self._iter_devs():
dev['sort_key'] = \
'%08x.%04x' % (dev['parts_wanted'], randint(0, 0xffff))
available_devs = sorted((d for d in self._iter_devs()),
key=lambda x: x['sort_key'])
self._replica2part2dev = \
[array('H') for _junk in xrange(self.replicas)]
for _junk in xrange(self.parts):
other_zones = array('H')
for replica in xrange(self.replicas):
index = len(available_devs) - 1
while available_devs[index]['zone'] in other_zones:
index -= 1
dev = available_devs.pop(index)
self._replica2part2dev[replica].append(dev['id'])
dev['parts_wanted'] -= 1
dev['parts'] += 1
dev['sort_key'] = \
'%08x.%04x' % (dev['parts_wanted'], randint(0, 0xffff))
index = 0
end = len(available_devs)
while index < end:
mid = (index + end) // 2
if dev['sort_key'] < available_devs[mid]['sort_key']:
end = mid
else:
index = mid + 1
available_devs.insert(index, dev)
other_zones.append(dev['zone'])
[array('H', (0 for _junk in xrange(self.parts)))
for _junk in xrange(self.replicas)]
replicas = range(self.replicas)
self._last_part_moves = array('B', (0 for _junk in xrange(self.parts)))
self._last_part_moves_epoch = int(time())
for dev in self._iter_devs():
del dev['sort_key']
self._reassign_parts((p, replicas) for p in xrange(self.parts))
def _update_last_part_moves(self):
"""
@ -493,8 +464,7 @@ class RingBuilder(object):
according to the "most wanted" and distinct zone restrictions.
"""
for dev in self._iter_devs():
dev['sort_key'] = '%08x.%04x' % (self.parts +
dev['parts_wanted'], randint(0, 0xffff))
dev['sort_key'] = self._sort_key_for(dev)
available_devs = \
sorted((d for d in self._iter_devs() if d['weight']),
key=lambda x: x['sort_key'])
@ -518,17 +488,23 @@ class RingBuilder(object):
self._replica2part2dev[replica][part] = dev['id']
dev['parts_wanted'] -= 1
dev['parts'] += 1
dev['sort_key'] = \
'%08x.%04x' % (self.parts + dev['parts_wanted'],
randint(0, 0xffff))
index = 0
end = len(available_devs)
while index < end:
mid = (index + end) // 2
if dev['sort_key'] < available_devs[mid]['sort_key']:
end = mid
else:
index = mid + 1
available_devs.insert(index, dev)
dev['sort_key'] = self._sort_key_for(dev)
self._insert_dev_sorted(available_devs, dev)
for dev in self._iter_devs():
del dev['sort_key']
def _insert_dev_sorted(self, devs, dev):
index = 0
end = len(devs)
while index < end:
mid = (index + end) // 2
if dev['sort_key'] < devs[mid]['sort_key']:
end = mid
else:
index = mid + 1
devs.insert(index, dev)
def _sort_key_for(self, dev):
return '%08x.%04x' % (self.parts + dev['parts_wanted'],
randint(0, 0xffff))