34
34
return cmp((self.file, self.pos), (other.file, other.pos))
36
#pylint: disable-msg=C0103
37
User = collections.namedtuple('User', ['name', 'passwd'])
36
User = collections.namedtuple('User', 'name,passwd')
38
GTID = collections.namedtuple('GTID', 'uuid,gid')
41
"""Normalize a list of ranges by merging ranges, if possible, and
42
turning single-position ranges into tuples.
44
The normalization is sort the ranges first on the tuples, which
45
makes comparisons easy when merging range sets.
50
for rng in sorted(rngs):
52
rng = (rng[0], rng[0])
55
elif rng[1] <= last[1]:
57
elif rng[0] <= last[1] or last[1] + 1 >= rng[0]:
58
last = (last[0], max(rng[1], last[1]))
66
def _compare_sets(lhs, rhs):
67
"""Compare two GTID sets.
69
Return a tuple (lhs, rhs) where lhs is a boolean indicating that
70
the left hand side had at least one more item than the right hand
74
lcheck, rcheck = False, False
76
# Create a union of the lhs and rhs for comparison
77
both = copy.deepcopy(lhs)
80
for uuid, rngs in both._GTIDSet__gtids.items():
82
return lcheck, rcheck # They are incomparable, just return
84
def _inner_compare(gtid_set):
85
if uuid not in gtid_set._GTIDSet__gtids:
86
return True # UUID not in lhs ==> right hand side has more
88
for rng1, rng2 in zip(rngs, gtid_set._GTIDSet__gtids[uuid]):
93
if _inner_compare(lhs):
95
if _inner_compare(rhs):
100
class GTIDSet(object):
101
def __init__(self, obj):
103
if not isinstance(obj, basestring):
104
obj = str(obj) # Try to make it into a string that we parse
106
# Parse the string and construct a GTID set
107
for uuid_set in obj.split(','):
108
parts = uuid_set.split(':')
110
# This fandango is done to handle other forms of UUID that
111
# the UUID class can handle. We, however, use the standard
112
# form for our UUIDs.
113
uuid = str(UUID(parts.pop(0)))
115
if len(parts) == 0 or not parts[0]:
116
raise ValueError("At least one range have to be provided")
117
rngs = [ tuple(int(x) for x in part.split('-')) for part in parts ]
119
if len(rng) > 2 or len(rng) == 2 and int(rng[0]) > int(rng[1]):
120
raise ValueError("Range %s in '%s' is not a valid range" % (
121
'-'.join(str(i) for i in rng), rng
123
gtids[uuid] = _normalize(rngs)
128
for uuid, rngs in sorted(self.__gtids.items()):
130
[str(uuid)] + [ '-'.join(str(i) for i in rng) for rng in rngs ]
132
sets.append(uuid_set)
133
return ','.join(sets)
135
def union(self, other):
136
"""Compute the union of this GTID set and the GTID set in
139
The update of the GTID set is done in-place, so if you want to
140
compute the union of two sets 'lhs' and 'rhs' you have to do
143
result = copy.deepcopy(lhs)
148
# If it wasn't already a GTIDSet, try to make it one.
149
if not isinstance(other, GTIDSet):
150
other = GTIDSet(other)
153
for uuid, rngs in other.__gtids.items():
154
if uuid not in gtids:
157
gtids[uuid] = _normalize(gtids[uuid] + rngs)
160
def __lt__(self, other):
161
lhs, rhs = _compare_sets(self, other)
162
return not lhs and rhs
164
def __le__(self, other):
165
lhs, _ = _compare_sets(self, other)
168
def __eq__(self, other):
169
lhs, rhs = _compare_sets(self, other)
170
return not (lhs or rhs)
172
def __ne__(self, other):
173
return not self.__eq__(other)
175
def __ge__(self, other):
176
return other.__le__(self)
178
def __gt__(self, other):
179
return other.__lt__(self)
181
def __or__(self, other):
182
result = copy.deepcopy(self)
39
185
class Server(object):
40
186
"""A representation of a MySQL server.