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