]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/check_results.py
9fc7a86356b8a9a017ec7d69d4eeda9fdb30f0a5
[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.report = []
24         self.healthy = bool(healthy)
25         if self.healthy:
26             assert recoverable
27             if not summary:
28                 summary = "healthy"
29         else:
30             if not summary:
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,
52                 "sharemap": sharemap,
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,
58                 }
59         self._data = data
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
63         self.report = report
64         if servermap:
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
69
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)
74     def get_uri(self):
75         return self.uri
76
77     def is_healthy(self):
78         return self.healthy
79     def is_recoverable(self):
80         return self.recoverable
81
82     def needs_rebalancing(self):
83         return self.needs_rebalancing_p
84
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"]
89
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"]
94
95     def get_corrupt_shares(self):
96         return self._data["list-corrupt-shares"]
97
98     def get_incompatible_shares(self):
99         return self._data["list-incompatible-shares"]
100
101     def get_servers_responding(self):
102         return self._data["servers-responding"]
103
104     def get_host_counter_good_shares(self):
105         return self._data["count-good-share-hosts"]
106
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"]
111
112     def get_sharemap(self):
113         return self._data["sharemap"]
114
115     def as_dict(self):
116         return self._data
117
118     def get_summary(self):
119         return self.summary
120     def get_report(self):
121         return self.report
122     def get_share_problems(self):
123         return self._share_problems
124     def get_servermap(self):
125         return self.servermap
126
127 class CheckAndRepairResults:
128     implements(ICheckAndRepairResults)
129
130     def __init__(self, storage_index):
131         self.storage_index = storage_index
132         self.repair_attempted = False
133
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:
142             return False
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
148
149
150 class DeepResultsBase:
151
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?
156         else:
157             self.root_storage_index_s = base32.b2a(root_storage_index)
158
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 = {}
166         self.stats = {}
167
168     def update_stats(self, new_stats):
169         self.stats.update(new_stats)
170
171     def get_root_storage_index_string(self):
172         return self.root_storage_index_s
173
174     def get_corrupt_shares(self):
175         return self.corrupt_shares
176
177     def get_all_results(self):
178         return self.all_results
179
180     def get_results_for_storage_index(self, storage_index):
181         return self.all_results_by_storage_index[storage_index]
182
183     def get_stats(self):
184         return self.stats
185
186
187 class DeepCheckResults(DeepResultsBase):
188     implements(IDeepCheckResults)
189
190     def add_check(self, r, path):
191         if not r:
192             return # non-distributed object, i.e. LIT file
193         r = ICheckResults(r)
194         assert isinstance(path, (list, tuple))
195         self.objects_checked += 1
196         if r.is_healthy():
197             self.objects_healthy += 1
198         else:
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())
205
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),
212                 }
213
214
215 class DeepCheckAndRepairResults(DeepResultsBase):
216     implements(IDeepCheckAndRepairResults)
217
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 = []
227
228     def add_check_and_repair(self, r, path):
229         if not r:
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
238         else:
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
247             else:
248                 self.repairs_unsuccessful += 1
249         if post_repair.is_healthy():
250             self.objects_healthy_post_repair += 1
251         else:
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())
258
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),
272                 }
273
274     def get_remaining_corrupt_shares(self):
275         return self.corrupt_shares_post_repair