##// END OF EJS Templates
config: use copy-on-write to improve copy performance...
Jun Wu -
r34353:c41444a3 default
parent child Browse files
Show More
@@ -20,13 +20,14 b' from . import ('
20 class config(object):
20 class config(object):
21 def __init__(self, data=None, includepaths=None):
21 def __init__(self, data=None, includepaths=None):
22 self._data = {}
22 self._data = {}
23 self._source = {}
24 self._unset = []
23 self._unset = []
25 self._includepaths = includepaths or []
24 self._includepaths = includepaths or []
26 if data:
25 if data:
27 for k in data._data:
26 for k in data._data:
28 self._data[k] = data[k].copy()
27 self._data[k] = data[k].copy()
29 self._source = data._source.copy()
28 self._source = data._source.copy()
29 else:
30 self._source = util.cowdict()
30 def copy(self):
31 def copy(self):
31 return config(self)
32 return config(self)
32 def __contains__(self, section):
33 def __contains__(self, section):
@@ -39,13 +40,19 b' class config(object):'
39 for d in self.sections():
40 for d in self.sections():
40 yield d
41 yield d
41 def update(self, src):
42 def update(self, src):
43 self._source = self._source.preparewrite()
42 for s, n in src._unset:
44 for s, n in src._unset:
43 if s in self and n in self._data[s]:
45 ds = self._data.get(s, None)
46 if ds is not None and n in ds:
47 self._data[s] = ds.preparewrite()
44 del self._data[s][n]
48 del self._data[s][n]
45 del self._source[(s, n)]
49 del self._source[(s, n)]
46 for s in src:
50 for s in src:
47 if s not in self:
51 ds = self._data.get(s, None)
48 self._data[s] = util.sortdict()
52 if ds:
53 self._data[s] = ds.preparewrite()
54 else:
55 self._data[s] = util.cowsortdict()
49 self._data[s].update(src._data[s])
56 self._data[s].update(src._data[s])
50 self._source.update(src._source)
57 self._source.update(src._source)
51 def get(self, section, item, default=None):
58 def get(self, section, item, default=None):
@@ -74,16 +81,21 b' class config(object):'
74 assert not isinstance(value, str), (
81 assert not isinstance(value, str), (
75 'config values may not be unicode strings on Python 3')
82 'config values may not be unicode strings on Python 3')
76 if section not in self:
83 if section not in self:
77 self._data[section] = util.sortdict()
84 self._data[section] = util.cowsortdict()
85 else:
86 self._data[section] = self._data[section].preparewrite()
78 self._data[section][item] = value
87 self._data[section][item] = value
79 if source:
88 if source:
89 self._source = self._source.preparewrite()
80 self._source[(section, item)] = source
90 self._source[(section, item)] = source
81
91
82 def restore(self, data):
92 def restore(self, data):
83 """restore data returned by self.backup"""
93 """restore data returned by self.backup"""
94 self._source = self._source.preparewrite()
84 if len(data) == 4:
95 if len(data) == 4:
85 # restore old data
96 # restore old data
86 section, item, value, source = data
97 section, item, value, source = data
98 self._data[section] = self._data[section].preparewrite()
87 self._data[section][item] = value
99 self._data[section][item] = value
88 self._source[(section, item)] = source
100 self._source[(section, item)] = source
89 else:
101 else:
@@ -149,7 +161,7 b' class config(object):'
149 if remap:
161 if remap:
150 section = remap.get(section, section)
162 section = remap.get(section, section)
151 if section not in self:
163 if section not in self:
152 self._data[section] = util.sortdict()
164 self._data[section] = util.cowsortdict()
153 continue
165 continue
154 m = itemre.match(l)
166 m = itemre.match(l)
155 if m:
167 if m:
@@ -588,6 +588,24 b' def cachefunc(func):'
588
588
589 return f
589 return f
590
590
591 class cow(object):
592 """helper class to make copy-on-write easier
593
594 Call preparewrite before doing any writes.
595 """
596
597 def preparewrite(self):
598 """call this before writes, return self or a copied new object"""
599 if getattr(self, '_copied', 0):
600 self._copied -= 1
601 return self.__class__(self)
602 return self
603
604 def copy(self):
605 """always do a cheap copy"""
606 self._copied = getattr(self, '_copied', 0) + 1
607 return self
608
591 class sortdict(collections.OrderedDict):
609 class sortdict(collections.OrderedDict):
592 '''a simple sorted dictionary
610 '''a simple sorted dictionary
593
611
@@ -613,6 +631,38 b' class sortdict(collections.OrderedDict):'
613 for k, v in src:
631 for k, v in src:
614 self[k] = v
632 self[k] = v
615
633
634 class cowdict(cow, dict):
635 """copy-on-write dict
636
637 Be sure to call d = d.preparewrite() before writing to d.
638
639 >>> a = cowdict()
640 >>> a is a.preparewrite()
641 True
642 >>> b = a.copy()
643 >>> b is a
644 True
645 >>> c = b.copy()
646 >>> c is a
647 True
648 >>> a = a.preparewrite()
649 >>> b is a
650 False
651 >>> a is a.preparewrite()
652 True
653 >>> c = c.preparewrite()
654 >>> b is c
655 False
656 >>> b is b.preparewrite()
657 True
658 """
659
660 class cowsortdict(cow, sortdict):
661 """copy-on-write sortdict
662
663 Be sure to call d = d.preparewrite() before writing to d.
664 """
665
616 class transactional(object):
666 class transactional(object):
617 """Base class for making a transactional type into a context manager."""
667 """Base class for making a transactional type into a context manager."""
618 __metaclass__ = abc.ABCMeta
668 __metaclass__ = abc.ABCMeta
General Comments 0
You need to be logged in to leave comments. Login now