2 from zope.interface import implements
3 from allmydata.interfaces import ICheckResults, ICheckAndRepairResults, \
4 IDeepCheckResults, IDeepCheckAndRepairResults, IURI, IDisplayableServer
5 from allmydata.util import base32, dictutil
8 implements(ICheckResults)
10 def __init__(self, uri, storage_index,
11 healthy, recoverable, needs_rebalancing,
12 count_shares_needed, count_shares_expected,
13 count_shares_good, count_good_share_hosts,
14 count_recoverable_versions, count_unrecoverable_versions,
15 servers_responding, sharemap,
16 count_wrong_shares, list_corrupt_shares, count_corrupt_shares,
17 list_incompatible_shares, count_incompatible_shares,
18 summary, report, share_problems, servermap):
19 assert IURI.providedBy(uri), uri
21 self._storage_index = storage_index
23 self._healthy = bool(healthy)
30 summary = "not healthy"
31 self._recoverable = recoverable
32 if not self._recoverable:
33 assert not self._healthy
34 self._needs_rebalancing_p = bool(needs_rebalancing)
36 self._count_shares_needed = count_shares_needed
37 self._count_shares_expected = count_shares_expected
38 self._count_shares_good = count_shares_good
39 self._count_good_share_hosts = count_good_share_hosts
40 self._count_recoverable_versions = count_recoverable_versions
41 self._count_unrecoverable_versions = count_unrecoverable_versions
42 for server in servers_responding:
43 assert IDisplayableServer.providedBy(server), server
44 self._servers_responding = servers_responding
45 for shnum, servers in sharemap.items():
46 for server in servers:
47 assert IDisplayableServer.providedBy(server), server
48 self._sharemap = sharemap
49 self._count_wrong_shares = count_wrong_shares
50 for (server, SI, shnum) in list_corrupt_shares:
51 assert IDisplayableServer.providedBy(server), server
52 self._list_corrupt_shares = list_corrupt_shares
53 self._count_corrupt_shares = count_corrupt_shares
54 for (server, SI, shnum) in list_incompatible_shares:
55 assert IDisplayableServer.providedBy(server), server
56 self._list_incompatible_shares = list_incompatible_shares
57 self._count_incompatible_shares = count_incompatible_shares
59 assert isinstance(summary, str) # should be a single string
60 self._summary = summary
61 assert not isinstance(report, str) # should be list of strings
64 from allmydata.mutable.servermap import ServerMap
65 assert isinstance(servermap, ServerMap), servermap
66 self._servermap = servermap # mutable only
67 self._share_problems = share_problems
69 def get_storage_index(self):
70 return self._storage_index
71 def get_storage_index_string(self):
72 return base32.b2a(self._storage_index)
78 def is_recoverable(self):
79 return self._recoverable
81 def needs_rebalancing(self):
82 return self._needs_rebalancing_p
84 def get_encoding_needed(self):
85 return self._count_shares_needed
86 def get_encoding_expected(self):
87 return self._count_shares_expected
89 def get_share_counter_good(self):
90 return self._count_shares_good
91 def get_share_counter_wrong(self):
92 return self._count_wrong_shares
94 def get_new_corrupt_shares(self):
95 return self._list_corrupt_shares
96 def get_corrupt_shares(self):
97 return [(s.get_serverid(), SI, shnum)
98 for (s, SI, shnum) in self._list_corrupt_shares]
100 def get_new_incompatible_shares(self):
101 return self._list_incompatible_shares
102 def get_incompatible_shares(self):
103 return [(s.get_serverid(), SI, shnum)
104 for (s, SI, shnum) in self._list_incompatible_shares]
106 def get_new_servers_responding(self):
107 return self._servers_responding
108 def get_servers_responding(self):
109 return [s.get_serverid() for s in self._servers_responding]
111 def get_host_counter_good_shares(self):
112 return self._count_good_share_hosts
114 def get_version_counter_recoverable(self):
115 return self._count_recoverable_versions
116 def get_version_counter_unrecoverable(self):
117 return self._count_unrecoverable_versions
119 def get_sharemap(self):
120 sharemap = dictutil.DictOfSets()
121 for shnum, servers in self._sharemap.items():
123 sharemap.add(shnum, s.get_serverid())
125 def get_new_sharemap(self):
126 # this one returns IServers, even when get_sharemap returns serverids
127 return self._sharemap
131 for shnum, servers in self._sharemap.items():
132 sharemap[shnum] = sorted([s.get_serverid() for s in servers])
133 responding = [s.get_serverid() for s in self._servers_responding]
134 corrupt = [(s.get_serverid(), SI, shnum)
135 for (s, SI, shnum) in self._list_corrupt_shares]
136 incompatible = [(s.get_serverid(), SI, shnum)
137 for (s, SI, shnum) in self._list_incompatible_shares]
138 d = {"count-shares-needed": self._count_shares_needed,
139 "count-shares-expected": self._count_shares_expected,
140 "count-shares-good": self._count_shares_good,
141 "count-good-share-hosts": self._count_good_share_hosts,
142 "count-recoverable-versions": self._count_recoverable_versions,
143 "count-unrecoverable-versions": self._count_unrecoverable_versions,
144 "servers-responding": responding,
145 "sharemap": sharemap,
146 "count-wrong-shares": self._count_wrong_shares,
147 "list-corrupt-shares": corrupt,
148 "count-corrupt-shares": self._count_corrupt_shares,
149 "list-incompatible-shares": incompatible,
150 "count-incompatible-shares": self._count_incompatible_shares,
154 def get_summary(self):
156 def get_report(self):
158 def get_share_problems(self):
159 return self._share_problems
160 def get_servermap(self):
161 return self._servermap
163 class CheckAndRepairResults:
164 implements(ICheckAndRepairResults)
166 def __init__(self, storage_index):
167 self.storage_index = storage_index
168 self.repair_attempted = False
170 def get_storage_index(self):
171 return self.storage_index
172 def get_storage_index_string(self):
173 return base32.b2a(self.storage_index)
174 def get_repair_attempted(self):
175 return self.repair_attempted
176 def get_repair_successful(self):
177 if not self.repair_attempted:
179 return self.repair_successful
180 def get_pre_repair_results(self):
181 return self.pre_repair_results
182 def get_post_repair_results(self):
183 return self.post_repair_results
186 class DeepResultsBase:
188 def __init__(self, root_storage_index):
189 self.root_storage_index = root_storage_index
190 if root_storage_index is None:
191 self.root_storage_index_s = "<none>" # is this correct?
193 self.root_storage_index_s = base32.b2a(root_storage_index)
195 self.objects_checked = 0
196 self.objects_healthy = 0
197 self.objects_unhealthy = 0
198 self.objects_unrecoverable = 0
199 self.corrupt_shares = []
200 self.all_results = {}
201 self.all_results_by_storage_index = {}
204 def update_stats(self, new_stats):
205 self.stats.update(new_stats)
207 def get_root_storage_index_string(self):
208 return self.root_storage_index_s
210 def get_corrupt_shares(self):
211 return self.corrupt_shares
213 def get_all_results(self):
214 return self.all_results
216 def get_results_for_storage_index(self, storage_index):
217 return self.all_results_by_storage_index[storage_index]
223 class DeepCheckResults(DeepResultsBase):
224 implements(IDeepCheckResults)
226 def add_check(self, r, path):
228 return # non-distributed object, i.e. LIT file
230 assert isinstance(path, (list, tuple))
231 self.objects_checked += 1
233 self.objects_healthy += 1
235 self.objects_unhealthy += 1
236 if not r.is_recoverable():
237 self.objects_unrecoverable += 1
238 self.all_results[tuple(path)] = r
239 self.all_results_by_storage_index[r.get_storage_index()] = r
240 self.corrupt_shares.extend(r.get_corrupt_shares())
242 def get_counters(self):
243 return {"count-objects-checked": self.objects_checked,
244 "count-objects-healthy": self.objects_healthy,
245 "count-objects-unhealthy": self.objects_unhealthy,
246 "count-objects-unrecoverable": self.objects_unrecoverable,
247 "count-corrupt-shares": len(self.corrupt_shares),
251 class DeepCheckAndRepairResults(DeepResultsBase):
252 implements(IDeepCheckAndRepairResults)
254 def __init__(self, root_storage_index):
255 DeepResultsBase.__init__(self, root_storage_index)
256 self.objects_healthy_post_repair = 0
257 self.objects_unhealthy_post_repair = 0
258 self.objects_unrecoverable_post_repair = 0
259 self.repairs_attempted = 0
260 self.repairs_successful = 0
261 self.repairs_unsuccessful = 0
262 self.corrupt_shares_post_repair = []
264 def add_check_and_repair(self, r, path):
266 return # non-distributed object, i.e. LIT file
267 r = ICheckAndRepairResults(r)
268 assert isinstance(path, (list, tuple))
269 pre_repair = r.get_pre_repair_results()
270 post_repair = r.get_post_repair_results()
271 self.objects_checked += 1
272 if pre_repair.is_healthy():
273 self.objects_healthy += 1
275 self.objects_unhealthy += 1
276 if not pre_repair.is_recoverable():
277 self.objects_unrecoverable += 1
278 self.corrupt_shares.extend(pre_repair.get_corrupt_shares())
279 if r.get_repair_attempted():
280 self.repairs_attempted += 1
281 if r.get_repair_successful():
282 self.repairs_successful += 1
284 self.repairs_unsuccessful += 1
285 if post_repair.is_healthy():
286 self.objects_healthy_post_repair += 1
288 self.objects_unhealthy_post_repair += 1
289 if not post_repair.is_recoverable():
290 self.objects_unrecoverable_post_repair += 1
291 self.all_results[tuple(path)] = r
292 self.all_results_by_storage_index[r.get_storage_index()] = r
293 self.corrupt_shares_post_repair.extend(post_repair.get_corrupt_shares())
295 def get_counters(self):
296 return {"count-objects-checked": self.objects_checked,
297 "count-objects-healthy-pre-repair": self.objects_healthy,
298 "count-objects-unhealthy-pre-repair": self.objects_unhealthy,
299 "count-objects-unrecoverable-pre-repair": self.objects_unrecoverable,
300 "count-objects-healthy-post-repair": self.objects_healthy_post_repair,
301 "count-objects-unhealthy-post-repair": self.objects_unhealthy_post_repair,
302 "count-objects-unrecoverable-post-repair": self.objects_unrecoverable_post_repair,
303 "count-repairs-attempted": self.repairs_attempted,
304 "count-repairs-successful": self.repairs_successful,
305 "count-repairs-unsuccessful": self.repairs_unsuccessful,
306 "count-corrupt-shares-pre-repair": len(self.corrupt_shares),
307 "count-corrupt-shares-post-repair": len(self.corrupt_shares_post_repair),
310 def get_remaining_corrupt_shares(self):
311 return self.corrupt_shares_post_repair