]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/checker_results.py
immutable: new checker and verifier
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / checker_results.py
1
2 from zope.interface import implements
3 from allmydata.interfaces import ICheckerResults, ICheckAndRepairResults, \
4      IDeepCheckResults, IDeepCheckAndRepairResults, IURI
5 from allmydata.util import base32
6
7 class CheckerResults:
8     implements(ICheckerResults)
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.data = {"count-corrupt-shares": 0,
16                      "list-corrupt-shares": [],
17                      }
18         self.summary = ""
19         self.report = []
20
21     def set_healthy(self, healthy):
22         self.healthy = bool(healthy)
23         if self.healthy:
24             assert (not hasattr(self, 'recoverable')) or self.recoverable, hasattr(self, 'recoverable') and self.recoverable
25             self.recoverable = True
26             self.summary = "healthy"
27         else:
28             self.summary = "not healthy"
29     def set_recoverable(self, recoverable):
30         self.recoverable = recoverable
31         if not self.recoverable:
32             assert (not hasattr(self, 'healthy')) or not self.healthy
33             self.healthy = False
34     def set_needs_rebalancing(self, needs_rebalancing):
35         self.needs_rebalancing_p = bool(needs_rebalancing)
36     def set_data(self, data):
37         self.data.update(data)
38     def set_summary(self, summary):
39         assert isinstance(summary, str) # should be a single string
40         self.summary = summary
41     def set_report(self, report):
42         assert not isinstance(report, str) # should be list of strings
43         self.report = report
44
45     def set_servermap(self, smap):
46         # mutable only
47         self.servermap = smap
48
49
50     def get_storage_index(self):
51         return self.storage_index
52     def get_storage_index_string(self):
53         return base32.b2a(self.storage_index)
54     def get_uri(self):
55         return self.uri
56
57     def is_healthy(self):
58         return self.healthy
59     def is_recoverable(self):
60         return self.recoverable
61
62     def needs_rebalancing(self):
63         return self.needs_rebalancing_p
64     def get_data(self):
65         return self.data
66
67     def get_summary(self):
68         return self.summary
69     def get_report(self):
70         return self.report
71     def get_servermap(self):
72         return self.servermap
73
74 class CheckAndRepairResults:
75     implements(ICheckAndRepairResults)
76
77     def __init__(self, storage_index):
78         self.storage_index = storage_index
79         self.repair_attempted = False
80
81     def get_storage_index(self):
82         return self.storage_index
83     def get_storage_index_string(self):
84         return base32.b2a(self.storage_index)
85     def get_repair_attempted(self):
86         return self.repair_attempted
87     def get_repair_successful(self):
88         if not self.repair_attempted:
89             return False
90         return self.repair_successful
91     def get_pre_repair_results(self):
92         return self.pre_repair_results
93     def get_post_repair_results(self):
94         return self.post_repair_results
95
96
97 class DeepResultsBase:
98
99     def __init__(self, root_storage_index):
100         self.root_storage_index = root_storage_index
101         if root_storage_index is None:
102             self.root_storage_index_s = "<none>"
103         else:
104             self.root_storage_index_s = base32.b2a(root_storage_index)
105
106         self.objects_checked = 0
107         self.objects_healthy = 0
108         self.objects_unhealthy = 0
109         self.objects_unrecoverable = 0
110         self.corrupt_shares = []
111         self.all_results = {}
112         self.all_results_by_storage_index = {}
113         self.stats = {}
114
115     def update_stats(self, new_stats):
116         self.stats.update(new_stats)
117
118     def get_root_storage_index_string(self):
119         return self.root_storage_index_s
120
121     def get_corrupt_shares(self):
122         return self.corrupt_shares
123
124     def get_all_results(self):
125         return self.all_results
126
127     def get_results_for_storage_index(self, storage_index):
128         return self.all_results_by_storage_index[storage_index]
129
130     def get_stats(self):
131         return self.stats
132
133
134 class DeepCheckResults(DeepResultsBase):
135     implements(IDeepCheckResults)
136
137     def add_check(self, r, path):
138         if not r:
139             return # non-distributed object, i.e. LIT file
140         r = ICheckerResults(r)
141         assert isinstance(path, (list, tuple))
142         self.objects_checked += 1
143         if r.is_healthy():
144             self.objects_healthy += 1
145         else:
146             self.objects_unhealthy += 1
147         if not r.is_recoverable():
148             self.objects_unrecoverable += 1
149         self.all_results[tuple(path)] = r
150         self.all_results_by_storage_index[r.get_storage_index()] = r
151         self.corrupt_shares.extend(r.get_data()["list-corrupt-shares"])
152
153     def get_counters(self):
154         return {"count-objects-checked": self.objects_checked,
155                 "count-objects-healthy": self.objects_healthy,
156                 "count-objects-unhealthy": self.objects_unhealthy,
157                 "count-objects-unrecoverable": self.objects_unrecoverable,
158                 "count-corrupt-shares": len(self.corrupt_shares),
159                 }
160
161
162 class DeepCheckAndRepairResults(DeepResultsBase):
163     implements(IDeepCheckAndRepairResults)
164
165     def __init__(self, root_storage_index):
166         DeepResultsBase.__init__(self, root_storage_index)
167         self.objects_healthy_post_repair = 0
168         self.objects_unhealthy_post_repair = 0
169         self.objects_unrecoverable_post_repair = 0
170         self.repairs_attempted = 0
171         self.repairs_successful = 0
172         self.repairs_unsuccessful = 0
173         self.corrupt_shares_post_repair = []
174
175     def add_check_and_repair(self, r, path):
176         if not r:
177             return # non-distributed object, i.e. LIT file
178         r = ICheckAndRepairResults(r)
179         assert isinstance(path, (list, tuple))
180         pre_repair = r.get_pre_repair_results()
181         post_repair = r.get_post_repair_results()
182         self.objects_checked += 1
183         if pre_repair.is_healthy():
184             self.objects_healthy += 1
185         else:
186             self.objects_unhealthy += 1
187         if not pre_repair.is_recoverable():
188             self.objects_unrecoverable += 1
189         self.corrupt_shares.extend(pre_repair.get_data()["list-corrupt-shares"])
190         if r.get_repair_attempted():
191             self.repairs_attempted += 1
192             if r.get_repair_successful():
193                 self.repairs_successful += 1
194             else:
195                 self.repairs_unsuccessful += 1
196         if post_repair.is_healthy():
197             self.objects_healthy_post_repair += 1
198         else:
199             self.objects_unhealthy_post_repair += 1
200         if not post_repair.is_recoverable():
201             self.objects_unrecoverable_post_repair += 1
202         self.all_results[tuple(path)] = r
203         self.all_results_by_storage_index[r.get_storage_index()] = r
204         self.corrupt_shares_post_repair.extend(post_repair.get_data()["list-corrupt-shares"])
205
206     def get_counters(self):
207         return {"count-objects-checked": self.objects_checked,
208                 "count-objects-healthy-pre-repair": self.objects_healthy,
209                 "count-objects-unhealthy-pre-repair": self.objects_unhealthy,
210                 "count-objects-unrecoverable-pre-repair": self.objects_unrecoverable,
211                 "count-objects-healthy-post-repair": self.objects_healthy_post_repair,
212                 "count-objects-unhealthy-post-repair": self.objects_unhealthy_post_repair,
213                 "count-objects-unrecoverable-post-repair": self.objects_unrecoverable_post_repair,
214                 "count-repairs-attempted": self.repairs_attempted,
215                 "count-repairs-successful": self.repairs_successful,
216                 "count-repairs-unsuccessful": self.repairs_unsuccessful,
217                 "count-corrupt-shares-pre-repair": len(self.corrupt_shares),
218                 "count-corrupt-shares-post-repair": len(self.corrupt_shares_post_repair),
219                 }
220
221     def get_remaining_corrupt_shares(self):
222         return self.corrupt_shares_post_repair