Merge "Make RingBuilders deep-copy-able"

This commit is contained in:
Jenkins 2015-04-24 04:38:21 +00:00 committed by Gerrit Code Review
commit f2d4851b17
3 changed files with 34 additions and 2 deletions

View File

@ -1073,8 +1073,7 @@ swift-ring-builder <ring_file> write_builder [min_part_hours]
'_last_part_gather_start': 0,
'_remove_devs': [],
}
builder = RingBuilder(1, 1, 1)
builder.copy_from(builder_dict)
builder = RingBuilder.from_dict(builder_dict)
for parts in builder._replica2part2dev:
for dev_id in parts:
builder.devs[dev_id]['parts'] += 1

View File

@ -21,6 +21,7 @@ import logging
import math
import random
import cPickle as pickle
from copy import deepcopy
from array import array
from collections import defaultdict
@ -125,6 +126,12 @@ class RingBuilder(object):
'ring, or all devices have been '
'deleted')
@classmethod
def from_dict(cls, builder_data):
b = cls(1, 1, 1) # Dummy values
b.copy_from(builder_data)
return b
def copy_from(self, builder):
"""
Reinitializes this RingBuilder instance from data obtained from the
@ -173,6 +180,11 @@ class RingBuilder(object):
for dev in self._iter_devs():
dev.setdefault("region", 1)
def __deepcopy__(self, memo):
the_copy = type(self).from_dict(deepcopy(self.to_dict(), memo))
memo[id(self)] = the_copy
return the_copy
def to_dict(self):
"""
Returns a dict that can be used later with copy_from to

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import errno
import mock
import operator
@ -84,6 +85,26 @@ class TestRingBuilder(unittest.TestCase):
ring.RingBuilder(8, 3, 0) # passes by not crashing
self.assertRaises(ValueError, ring.RingBuilder, 8, 3, -1)
def test_deepcopy(self):
rb = ring.RingBuilder(8, 3, 1)
rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,
'ip': '127.0.0.1', 'port': 10000, 'device': 'sda1'})
rb.add_dev({'id': 1, 'region': 0, 'zone': 1, 'weight': 1,
'ip': '127.0.0.1', 'port': 10001, 'device': 'sda1'})
rb.add_dev({'id': 2, 'region': 0, 'zone': 2, 'weight': 1,
'ip': '127.0.0.1', 'port': 10002, 'device': 'sda1'})
rb.add_dev({'id': 3, 'region': 0, 'zone': 1, 'weight': 1,
'ip': '127.0.0.1', 'port': 10004, 'device': 'sda1'})
rb.rebalance()
rb_copy = copy.deepcopy(rb)
self.assertEqual(rb.to_dict(), rb_copy.to_dict())
self.assertTrue(rb.devs is not rb_copy.devs)
self.assertTrue(rb._replica2part2dev is not rb_copy._replica2part2dev)
self.assertTrue(rb._last_part_moves is not rb_copy._last_part_moves)
self.assertTrue(rb._remove_devs is not rb_copy._remove_devs)
self.assertTrue(rb._dispersion_graph is not rb_copy._dispersion_graph)
def test_get_ring(self):
rb = ring.RingBuilder(8, 3, 1)
rb.add_dev({'id': 0, 'region': 0, 'zone': 0, 'weight': 1,