##// END OF EJS Templates
Fallback to :memory: on repeated failure to load history...
Min RK -
Show More
@@ -16,7 +16,6 b' except ImportError:'
16 16 from pysqlite2 import dbapi2 as sqlite3
17 17 except ImportError:
18 18 sqlite3 = None
19 import sys
20 19 import threading
21 20
22 21 from traitlets.config.configurable import LoggingConfigurable
@@ -81,18 +80,29 b' def catch_corrupt_db(f, self, *a, **kw):'
81 80 try:
82 81 return f(self, *a, **kw)
83 82 except (DatabaseError, OperationalError) as e:
84 if os.path.isfile(self.hist_file):
85 # Try to move the file out of the way
86 base,ext = os.path.splitext(self.hist_file)
87 newpath = base + '-corrupt' + ext
88 os.rename(self.hist_file, newpath)
89 print("ERROR! History file wasn't a valid SQLite database (%s)." % e,
90 "It was moved to %s" % newpath, "and a new file created.", file=sys.stderr)
83 self._corrupt_db_counter += 1
84 self.log.error("Failed to open SQLite history %s (%s).", self.hist_file, e)
85 if self.hist_file != ':memory:':
86 if self._corrupt_db_counter > self._corrupt_db_limit:
87 self.hist_file = ':memory:'
88 self.log.error("Failed to load history too many times, history will not be saved.")
89 elif os.path.isfile(self.hist_file):
90 # Try to move the file out of the way
91 base,ext = os.path.splitext(self.hist_file)
92 now = datetime.datetime.now().isoformat().replace(':', '.')
93 newpath = base + '-corrupt-' + now + ext
94 # don't clobber previous corrupt backups
95 for i in range(100):
96 if not os.path.isfile(newpath):
97 break
98 else:
99 newpath = base + '-corrupt-' + now + (u'-%i' % i) + ext
100 os.rename(self.hist_file, newpath)
101 self.log.error("History file was moved to %s and a new file created.", newpath)
91 102 self.init_db()
92 103 return []
93
94 104 else:
95 # The hist_file is probably :memory: or something else.
105 # Failed with :memory:, something serious is wrong
96 106 raise
97 107
98 108 class HistoryAccessorBase(LoggingConfigurable):
@@ -118,6 +128,11 b' class HistoryAccessor(HistoryAccessorBase):'
118 128 This is intended for use by standalone history tools. IPython shells use
119 129 HistoryManager, below, which is a subclass of this."""
120 130
131 # counter for init_db retries, so we don't keep trying over and over
132 _corrupt_db_counter = 0
133 # after two failures, fallback on :memory:
134 _corrupt_db_limit = 2
135
121 136 # String holding the path to the history file
122 137 hist_file = Unicode(config=True,
123 138 help="""Path to file to use for SQLite history database.
@@ -231,6 +246,8 b' class HistoryAccessor(HistoryAccessorBase):'
231 246 (session integer, line integer, output text,
232 247 PRIMARY KEY (session, line))""")
233 248 self.db.commit()
249 # success! reset corrupt db count
250 self._corrupt_db_counter = 0
234 251
235 252 def writeout_cache(self):
236 253 """Overridden by HistoryManager to dump the cache before certain
General Comments 0
You need to be logged in to leave comments. Login now