]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/check_results.py
159a5a526091628634ef4425572d910987a763e2
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / check_results.py
1
2 from zope.interface import implements
3 from allmydata.interfaces import ICheckResults, ICheckAndRepairResults, \
4      IDeepCheckResults, IDeepCheckAndRepairResults, IURI
5 from allmydata.util import base32
6
7 class CheckResults:
8     implements(ICheckResults)
9
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
20         self._uri = uri
21         self._storage_index = storage_index
22         self._summary = ""
23         self._healthy = bool(healthy)
24         if self._healthy:
25             assert recoverable
26             if not summary:
27                 summary = "healthy"
28         else:
29             if not summary:
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)
35         for s in servers_responding:
36             assert isinstance(s, str), s
37         for shnum, serverids in sharemap.items():
38             for serverid in serverids:
39                 assert isinstance(serverid, str), serverid
40         for (serverid, SI, shnum) in list_corrupt_shares:
41             assert isinstance(serverid, str), serverid
42         for (serverid, SI, shnum) in list_incompatible_shares:
43             assert isinstance(serverid, str), serverid
44         data = {"count-shares-needed": count_shares_needed,
45                 "count-shares-expected": count_shares_expected,
46                 "count-shares-good": count_shares_good,
47                 "count-good-share-hosts": count_good_share_hosts,
48                 "count-recoverable-versions": count_recoverable_versions,
49                 "count-unrecoverable-versions": count_unrecoverable_versions,
50                 "servers-responding": servers_responding,
51                 "sharemap": sharemap,
52                 "count-wrong-shares": count_wrong_shares,
53                 "list-corrupt-shares": list_corrupt_shares,
54                 "count-corrupt-shares": count_corrupt_shares,
55                 "list-incompatible-shares": list_incompatible_shares,
56                 "count-incompatible-shares": count_incompatible_shares,
57                 }
58         self._data = data
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
62         self._report = report
63         if servermap:
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
68
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)
73     def get_uri(self):
74         return self._uri
75
76     def is_healthy(self):
77         return self._healthy
78     def is_recoverable(self):
79         return self._recoverable
80
81     def needs_rebalancing(self):
82         return self._needs_rebalancing_p
83
84     def get_encoding_needed(self):
85         return self._data["count-shares-needed"]
86     def get_encoding_expected(self):
87         return self._data["count-shares-expected"]
88
89     def get_share_counter_good(self):
90         return self._data["count-shares-good"]
91     def get_share_counter_wrong(self):
92         return self._data["count-wrong-shares"]
93
94     def get_corrupt_shares(self):
95         return self._data["list-corrupt-shares"]
96
97     def get_incompatible_shares(self):
98         return self._data["list-incompatible-shares"]
99
100     def get_servers_responding(self):
101         return self._data["servers-responding"]
102
103     def get_host_counter_good_shares(self):
104         return self._data["count-good-share-hosts"]
105
106     def get_version_counter_recoverable(self):
107         return self._data["count-recoverable-versions"]
108     def get_version_counter_unrecoverable(self):
109         return self._data["count-unrecoverable-versions"]
110
111     def get_sharemap(self):
112         return self._data["sharemap"]
113
114     def as_dict(self):
115         return self._data
116
117     def get_summary(self):
118         return self._summary
119     def get_report(self):
120         return self._report
121     def get_share_problems(self):
122         return self._share_problems
123     def get_servermap(self):
124         return self._servermap
125
126 class CheckAndRepairResults:
127     implements(ICheckAndRepairResults)
128
129     def __init__(self, storage_index):
130         self.storage_index = storage_index
131         self.repair_attempted = False
132
133     def get_storage_index(self):
134         return self.storage_index
135     def get_storage_index_string(self):
136         return base32.b2a(self.storage_index)
137     def get_repair_attempted(self):
138         return self.repair_attempted
139     def get_repair_successful(self):
140         if not self.repair_attempted:
141             return False
142         return self.repair_successful
143     def get_pre_repair_results(self):
144         return self.pre_repair_results
145     def get_post_repair_results(self):
146         return self.post_repair_results
147
148
149 class DeepResultsBase:
150
151     def __init__(self, root_storage_index):
152         self.root_storage_index = root_storage_index
153         if root_storage_index is None:
154             self.root_storage_index_s = "<none>"  # is this correct?
155         else:
156             self.root_storage_index_s = base32.b2a(root_storage_index)
157
158         self.objects_checked = 0
159         self.objects_healthy = 0
160         self.objects_unhealthy = 0
161         self.objects_unrecoverable = 0
162         self.corrupt_shares = []
163         self.all_results = {}
164         self.all_results_by_storage_index = {}
165         self.stats = {}
166
167     def update_stats(self, new_stats):
168         self.stats.update(new_stats)
169
170     def get_root_storage_index_string(self):
171         return self.root_storage_index_s
172
173     def get_corrupt_shares(self):
174         return self.corrupt_shares
175
176     def get_all_results(self):
177         return self.all_results
178
179     def get_results_for_storage_index(self, storage_index):
180         return self.all_results_by_storage_index[storage_index]
181
182     def get_stats(self):
183         return self.stats
184
185
186 class DeepCheckResults(DeepResultsBase):
187     implements(IDeepCheckResults)
188
189     def add_check(self, r, path):
190         if not r:
191             return # non-distributed object, i.e. LIT file
192         r = ICheckResults(r)
193         assert isinstance(path, (list, tuple))
194         self.objects_checked += 1
195         if r.is_healthy():
196             self.objects_healthy += 1
197         else:
198             self.objects_unhealthy += 1
199         if not r.is_recoverable():
200             self.objects_unrecoverable += 1
201         self.all_results[tuple(path)] = r
202         self.all_results_by_storage_index[r.get_storage_index()] = r
203         self.corrupt_shares.extend(r.get_corrupt_shares())
204
205     def get_counters(self):
206         return {"count-objects-checked": self.objects_checked,
207                 "count-objects-healthy": self.objects_healthy,
208                 "count-objects-unhealthy": self.objects_unhealthy,
209                 "count-objects-unrecoverable": self.objects_unrecoverable,
210                 "count-corrupt-shares": len(self.corrupt_shares),
211                 }
212
213
214 class DeepCheckAndRepairResults(DeepResultsBase):
215     implements(IDeepCheckAndRepairResults)
216
217     def __init__(self, root_storage_index):
218         DeepResultsBase.__init__(self, root_storage_index)
219         self.objects_healthy_post_repair = 0
220         self.objects_unhealthy_post_repair = 0
221         self.objects_unrecoverable_post_repair = 0
222         self.repairs_attempted = 0
223         self.repairs_successful = 0
224         self.repairs_unsuccessful = 0
225         self.corrupt_shares_post_repair = []
226
227     def add_check_and_repair(self, r, path):
228         if not r:
229             return # non-distributed object, i.e. LIT file
230         r = ICheckAndRepairResults(r)
231         assert isinstance(path, (list, tuple))
232         pre_repair = r.get_pre_repair_results()
233         post_repair = r.get_post_repair_results()
234         self.objects_checked += 1
235         if pre_repair.is_healthy():
236             self.objects_healthy += 1
237         else:
238             self.objects_unhealthy += 1
239         if not pre_repair.is_recoverable():
240             self.objects_unrecoverable += 1
241         self.corrupt_shares.extend(pre_repair.get_corrupt_shares())
242         if r.get_repair_attempted():
243             self.repairs_attempted += 1
244             if r.get_repair_successful():
245                 self.repairs_successful += 1
246             else:
247                 self.repairs_unsuccessful += 1
248         if post_repair.is_healthy():
249             self.objects_healthy_post_repair += 1
250         else:
251             self.objects_unhealthy_post_repair += 1
252         if not post_repair.is_recoverable():
253             self.objects_unrecoverable_post_repair += 1
254         self.all_results[tuple(path)] = r
255         self.all_results_by_storage_index[r.get_storage_index()] = r
256         self.corrupt_shares_post_repair.extend(post_repair.get_corrupt_shares())
257
258     def get_counters(self):
259         return {"count-objects-checked": self.objects_checked,
260                 "count-objects-healthy-pre-repair": self.objects_healthy,
261                 "count-objects-unhealthy-pre-repair": self.objects_unhealthy,
262                 "count-objects-unrecoverable-pre-repair": self.objects_unrecoverable,
263                 "count-objects-healthy-post-repair": self.objects_healthy_post_repair,
264                 "count-objects-unhealthy-post-repair": self.objects_unhealthy_post_repair,
265                 "count-objects-unrecoverable-post-repair": self.objects_unrecoverable_post_repair,
266                 "count-repairs-attempted": self.repairs_attempted,
267                 "count-repairs-successful": self.repairs_successful,
268                 "count-repairs-unsuccessful": self.repairs_unsuccessful,
269                 "count-corrupt-shares-pre-repair": len(self.corrupt_shares),
270                 "count-corrupt-shares-post-repair": len(self.corrupt_shares_post_repair),
271                 }
272
273     def get_remaining_corrupt_shares(self):
274         return self.corrupt_shares_post_repair