Show More
@@ -71,11 +71,18 else: | |||||
71 | class OperationalError(Exception): |
|
71 | class OperationalError(Exception): | |
72 | "Dummy exception when sqlite could not be imported. Should never occur." |
|
72 | "Dummy exception when sqlite could not be imported. Should never occur." | |
73 |
|
73 | |||
|
74 | # use 16kB as threshold for whether a corrupt history db should be saved | |||
|
75 | # that should be at least 100 entries or so | |||
|
76 | _SAVE_DB_SIZE = 16384 | |||
|
77 | ||||
74 | @decorator |
|
78 | @decorator | |
75 | def catch_corrupt_db(f, self, *a, **kw): |
|
79 | def catch_corrupt_db(f, self, *a, **kw): | |
76 | """A decorator which wraps HistoryAccessor method calls to catch errors from |
|
80 | """A decorator which wraps HistoryAccessor method calls to catch errors from | |
77 | a corrupt SQLite database, move the old database out of the way, and create |
|
81 | a corrupt SQLite database, move the old database out of the way, and create | |
78 | a new one. |
|
82 | a new one. | |
|
83 | ||||
|
84 | We avoid clobbering larger databases because this may be triggered due to filesystem issues, | |||
|
85 | not just a corrupt file. | |||
79 | """ |
|
86 | """ | |
80 | try: |
|
87 | try: | |
81 | return f(self, *a, **kw) |
|
88 | return f(self, *a, **kw) | |
@@ -87,16 +94,23 def catch_corrupt_db(f, self, *a, **kw): | |||||
87 | self.hist_file = ':memory:' |
|
94 | self.hist_file = ':memory:' | |
88 | self.log.error("Failed to load history too many times, history will not be saved.") |
|
95 | self.log.error("Failed to load history too many times, history will not be saved.") | |
89 | elif os.path.isfile(self.hist_file): |
|
96 | elif os.path.isfile(self.hist_file): | |
90 |
# |
|
97 | # move the file out of the way | |
91 | base,ext = os.path.splitext(self.hist_file) |
|
98 | base, ext = os.path.splitext(self.hist_file) | |
92 | now = datetime.datetime.now().isoformat().replace(':', '.') |
|
99 | size = os.stat(self.hist_file).st_size | |
93 | newpath = base + '-corrupt-' + now + ext |
|
100 | if size >= _SAVE_DB_SIZE: | |
94 | # don't clobber previous corrupt backups |
|
101 | # if there's significant content, avoid clobbering | |
95 | for i in range(100): |
|
102 | now = datetime.datetime.now().isoformat().replace(':', '.') | |
96 | if not os.path.isfile(newpath): |
|
103 | newpath = base + '-corrupt-' + now + ext | |
97 |
b |
|
104 | # don't clobber previous corrupt backups | |
98 |
|
|
105 | for i in range(100): | |
99 | newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext |
|
106 | if not os.path.isfile(newpath): | |
|
107 | break | |||
|
108 | else: | |||
|
109 | newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext | |||
|
110 | else: | |||
|
111 | # not much content, possibly empty; don't worry about clobbering | |||
|
112 | # maybe we should just delete it? | |||
|
113 | newpath = base + '-corrupt' + ext | |||
100 | os.rename(self.hist_file, newpath) |
|
114 | os.rename(self.hist_file, newpath) | |
101 | self.log.error("History file was moved to %s and a new file created.", newpath) |
|
115 | self.log.error("History file was moved to %s and a new file created.", newpath) | |
102 | self.init_db() |
|
116 | self.init_db() |
General Comments 0
You need to be logged in to leave comments.
Login now