2 from zope.interface import implements
3 from allmydata.interfaces import ICheckResults, ICheckAndRepairResults, \
4 IDeepCheckResults, IDeepCheckAndRepairResults, IURI
5 from allmydata.util import base32
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
24 self.healthy = bool(healthy)
31 summary = "not healthy"
32 self.recoverable = recoverable
33 if not self.recoverable:
34 assert not self.healthy
35 self.needs_rebalancing_p = bool(needs_rebalancing)
36 for s in servers_responding:
37 assert isinstance(s, str), s
38 for shnum, serverids in sharemap.items():
39 for serverid in serverids:
40 assert isinstance(serverid, str), serverid
41 for (serverid, SI, shnum) in list_corrupt_shares:
42 assert isinstance(serverid, str), serverid
43 for (serverid, SI, shnum) in list_incompatible_shares:
44 assert isinstance(serverid, str), serverid
45 data = {"count-shares-needed": count_shares_needed,
46 "count-shares-expected": count_shares_expected,
47 "count-shares-good": count_shares_good,
48 "count-good-share-hosts": count_good_share_hosts,
49 "count-recoverable-versions": count_recoverable_versions,
50 "count-unrecoverable-versions": count_unrecoverable_versions,
51 "servers-responding": servers_responding,
53 "count-wrong-shares": count_wrong_shares,
54 "list-corrupt-shares": list_corrupt_shares,
55 "count-corrupt-shares": count_corrupt_shares,
56 "list-incompatible-shares": list_incompatible_shares,
57 "count-incompatible-shares": count_incompatible_shares,
60 assert isinstance(summary, str) # should be a single string
61 self.summary = summary
62 assert not isinstance(report, str) # should be list of strings
65 from allmydata.mutable.servermap import ServerMap
66 assert isinstance(servermap, ServerMap), servermap
67 self.servermap = servermap # mutable only
68 self._share_problems = share_problems
70 def get_storage_index(self):
71 return self.storage_index
72 def get_storage_index_string(self):
73 return base32.b2a(self.storage_index)
79 def is_recoverable(self):
80 return self.recoverable
82 def needs_rebalancing(self):
83 return self.needs_rebalancing_p
85 def get_encoding_needed(self):
86 return self._data["count-shares-needed"]
87 def get_encoding_expected(self):
88 return self._data["count-shares-expected"]
90 def get_share_counter_good(self):
91 return self._data["count-shares-good"]
92 def get_share_counter_wrong(self):
93 return self._data["count-wrong-shares"]
95 def get_corrupt_shares(self):
96 return self._data["list-corrupt-shares"]
98 def get_incompatible_shares(self):
99 return self._data["list-incompatible-shares"]
101 def get_servers_responding(self):
102 return self._data["servers-responding"]
104 def get_host_counter_good_shares(self):
105 return self._data["count-good-share-hosts"]
107 def get_version_counter_recoverable(self):
108 return self._data["count-recoverable-versions"]
109 def get_version_counter_unrecoverable(self):
110 return self._data["count-unrecoverable-versions"]
112 def get_sharemap(self):
113 return self._data["sharemap"]
118 def get_summary(self):
120 def get_report(self):
122 def get_share_problems(self):
123 return self._share_problems
124 def get_servermap(self):
125 return self.servermap
127 class CheckAndRepairResults:
128 implements(ICheckAndRepairResults)
130 def __init__(self, storage_index):
131 self.storage_index = storage_index
132 self.repair_attempted = False
134 def get_storage_index(self):
135 return self.storage_index
136 def get_storage_index_string(self):
137 return base32.b2a(self.storage_index)
138 def get_repair_attempted(self):
139 return self.repair_attempted
140 def get_repair_successful(self):
141 if not self.repair_attempted:
143 return self.repair_successful
144 def get_pre_repair_results(self):
145 return self.pre_repair_results
146 def get_post_repair_results(self):
147 return self.post_repair_results
150 class DeepResultsBase:
152 def __init__(self, root_storage_index):
153 self.root_storage_index = root_storage_index
154 if root_storage_index is None:
155 self.root_storage_index_s = "<none>" # is this correct?
157 self.root_storage_index_s = base32.b2a(root_storage_index)
159 self.objects_checked = 0
160 self.objects_healthy = 0
161 self.objects_unhealthy = 0
162 self.objects_unrecoverable = 0
163 self.corrupt_shares = []
164 self.all_results = {}
165 self.all_results_by_storage_index = {}
168 def update_stats(self, new_stats):
169 self.stats.update(new_stats)
171 def get_root_storage_index_string(self):
172 return self.root_storage_index_s
174 def get_corrupt_shares(self):
175 return self.corrupt_shares
177 def get_all_results(self):
178 return self.all_results
180 def get_results_for_storage_index(self, storage_index):
181 return self.all_results_by_storage_index[storage_index]
187 class DeepCheckResults(DeepResultsBase):
188 implements(IDeepCheckResults)
190 def add_check(self, r, path):
192 return # non-distributed object, i.e. LIT file
194 assert isinstance(path, (list, tuple))
195 self.objects_checked += 1
197 self.objects_healthy += 1
199 self.objects_unhealthy += 1
200 if not r.is_recoverable():
201 self.objects_unrecoverable += 1
202 self.all_results[tuple(path)] = r
203 self.all_results_by_storage_index[r.get_storage_index()] = r
204 self.corrupt_shares.extend(r.get_corrupt_shares())
206 def get_counters(self):
207 return {"count-objects-checked": self.objects_checked,
208 "count-objects-healthy": self.objects_healthy,
209 "count-objects-unhealthy": self.objects_unhealthy,
210 "count-objects-unrecoverable": self.objects_unrecoverable,
211 "count-corrupt-shares": len(self.corrupt_shares),
215 class DeepCheckAndRepairResults(DeepResultsBase):
216 implements(IDeepCheckAndRepairResults)
218 def __init__(self, root_storage_index):
219 DeepResultsBase.__init__(self, root_storage_index)
220 self.objects_healthy_post_repair = 0
221 self.objects_unhealthy_post_repair = 0
222 self.objects_unrecoverable_post_repair = 0
223 self.repairs_attempted = 0
224 self.repairs_successful = 0
225 self.repairs_unsuccessful = 0
226 self.corrupt_shares_post_repair = []
228 def add_check_and_repair(self, r, path):
230 return # non-distributed object, i.e. LIT file
231 r = ICheckAndRepairResults(r)
232 assert isinstance(path, (list, tuple))
233 pre_repair = r.get_pre_repair_results()
234 post_repair = r.get_post_repair_results()
235 self.objects_checked += 1
236 if pre_repair.is_healthy():
237 self.objects_healthy += 1
239 self.objects_unhealthy += 1
240 if not pre_repair.is_recoverable():
241 self.objects_unrecoverable += 1
242 self.corrupt_shares.extend(pre_repair.get_corrupt_shares())
243 if r.get_repair_attempted():
244 self.repairs_attempted += 1
245 if r.get_repair_successful():
246 self.repairs_successful += 1
248 self.repairs_unsuccessful += 1
249 if post_repair.is_healthy():
250 self.objects_healthy_post_repair += 1
252 self.objects_unhealthy_post_repair += 1
253 if not post_repair.is_recoverable():
254 self.objects_unrecoverable_post_repair += 1
255 self.all_results[tuple(path)] = r
256 self.all_results_by_storage_index[r.get_storage_index()] = r
257 self.corrupt_shares_post_repair.extend(post_repair.get_corrupt_shares())
259 def get_counters(self):
260 return {"count-objects-checked": self.objects_checked,
261 "count-objects-healthy-pre-repair": self.objects_healthy,
262 "count-objects-unhealthy-pre-repair": self.objects_unhealthy,
263 "count-objects-unrecoverable-pre-repair": self.objects_unrecoverable,
264 "count-objects-healthy-post-repair": self.objects_healthy_post_repair,
265 "count-objects-unhealthy-post-repair": self.objects_unhealthy_post_repair,
266 "count-objects-unrecoverable-post-repair": self.objects_unrecoverable_post_repair,
267 "count-repairs-attempted": self.repairs_attempted,
268 "count-repairs-successful": self.repairs_successful,
269 "count-repairs-unsuccessful": self.repairs_unsuccessful,
270 "count-corrupt-shares-pre-repair": len(self.corrupt_shares),
271 "count-corrupt-shares-post-repair": len(self.corrupt_shares_post_repair),
274 def get_remaining_corrupt_shares(self):
275 return self.corrupt_shares_post_repair