from allmydata.util import base32
from allmydata.util.fileutil import abspath_expanduser_unicode
from allmydata.util.encodingutil import to_str
+from allmydata.util.dbutil import get_db, DBError
+
DAY = 24*60*60
MONTH = 30*DAY
UPDATE version SET version=2;
"""
+UPDATERS = {
+ 2: UPDATE_v1_to_v2,
+}
def get_backupdb(dbfile, stderr=sys.stderr,
create_version=(SCHEMA_v2, 2), just_create=False):
- # open or create the given backupdb file. The parent directory must
+ # Open or create the given backupdb file. The parent directory must
# exist.
- import sqlite3
-
- must_create = not os.path.exists(dbfile)
- try:
- db = sqlite3.connect(dbfile)
- except (EnvironmentError, sqlite3.OperationalError), e:
- print >>stderr, "Unable to create/open backupdb file %s: %s" % (dbfile, e)
- return None
-
- c = db.cursor()
- if must_create:
- schema, version = create_version
- c.executescript(schema)
- c.execute("INSERT INTO version (version) VALUES (?)", (version,))
- db.commit()
-
try:
- c.execute("SELECT version FROM version")
- version = c.fetchone()[0]
- except sqlite3.DatabaseError, e:
- # this indicates that the file is not a compatible database format.
- # Perhaps it was created with an old version, or it might be junk.
- print >>stderr, "backupdb file is unusable: %s" % e
+ (sqlite3, db) = get_db(dbfile, stderr, create_version, updaters=UPDATERS,
+ just_create=just_create, dbname="backupdb")
+ return BackupDB_v2(sqlite3, db)
+ except DBError, e:
+ print >>stderr, e
return None
- if just_create: # for tests
- return True
-
- if version == 1:
- c.executescript(UPDATE_v1_to_v2)
- db.commit()
- version = 2
- if version == 2:
- return BackupDB_v2(sqlite3, db)
- print >>stderr, "Unable to handle backupdb version %s" % version
- return None
class FileResult:
def __init__(self, bdb, filecap, should_check,
def did_check_healthy(self, results):
self.bdb.did_check_file_healthy(self.filecap, results)
+
class DirectoryResult:
def __init__(self, bdb, dirhash, dircap, should_check):
self.bdb = bdb
def did_check_healthy(self, results):
self.bdb.did_check_directory_healthy(self.dircap, results)
+
class BackupDB_v2:
VERSION = 2
NO_CHECK_BEFORE = 1*MONTH
is not healthy, please upload the file and call r.did_upload(filecap)
when you're done.
- I use_timestamps=True (the default), I will compare ctime and mtime
+ If use_timestamps=True (the default), I will compare ctime and mtime
of the local file against an entry in my database, and consider the
file to be unchanged if ctime, mtime, and filesize are all the same
as the earlier version. If use_timestamps=False, I will not trust the
STARTER_LEASE_DURATION = 2*MONTH
def __init__(self, dbfile):
+ # synchronous = OFF is necessary for leasedb to pass tests for the time being,
+ # since using synchronous = NORMAL causes failures that are apparently due to
+ # a file descriptor leak, and the default synchronous = FULL causes the tests
+ # to time out. For discussion see
+ # https://tahoe-lafs.org/pipermail/tahoe-dev/2012-December/007877.html
+
(self._sqlite,
- self._db) = dbutil.get_db(dbfile, create_version=(LEASE_SCHEMA_V1, 1))
+ self._db) = dbutil.get_db(dbfile, create_version=(LEASE_SCHEMA_V1, 1),
+ # journal_mode="WAL",
+ synchronous="OFF")
self._cursor = self._db.cursor()
self.debug = False
self.retained_history_entries = 10
def get_db(dbfile, stderr=sys.stderr,
- create_version=(None, None), updaters={}, just_create=False):
+ create_version=(None, None), updaters={}, just_create=False, dbname="db",
+ journal_mode=None, synchronous=None):
"""Open or create the given db file. The parent directory must exist.
create_version=(SCHEMA, VERNUM), and SCHEMA must have a 'version' table.
Updaters is a {newver: commands} mapping, where e.g. updaters[2] is used
try:
db = sqlite3.connect(dbfile)
except (EnvironmentError, sqlite3.OperationalError), e:
- raise DBError("Unable to create/open db file %s: %s" % (dbfile, e))
+ raise DBError("Unable to create/open %s file %s: %s" % (dbname, dbfile, e))
schema, target_version = create_version
c = db.cursor()
# The default is unspecified according to <http://www.sqlite.org/foreignkeys.html#fk_enable>.
c.execute("PRAGMA foreign_keys = ON;")
- # This is necessary to pass tests for the time being, since using
- # synchronous = NORMAL causes failures that are apparently due to a
- # file descriptor leak, and the default synchronous = FULL causes the
- # tests to time out. For discussion see
- # https://tahoe-lafs.org/pipermail/tahoe-dev/2012-December/007877.html
- #c.execute("PRAGMA journal_mode = WAL;")
- c.execute("PRAGMA synchronous = OFF;")
+ if journal_mode is not None:
+ c.execute("PRAGMA journal_mode = %s;" % (journal_mode,))
+
+ if synchronous is not None:
+ c.execute("PRAGMA synchronous = %s;" % (synchronous,))
if must_create:
c.executescript(schema)
except sqlite3.DatabaseError, e:
# this indicates that the file is not a compatible database format.
# Perhaps it was created with an old version, or it might be junk.
- raise DBError("db file is unusable: %s" % e)
+ raise DBError("%s file is unusable: %s" % (dbname, e))
if just_create: # for tests
return (sqlite3, db)
- while version < target_version:
+ while version < target_version and version+1 in updaters:
c.executescript(updaters[version+1])
db.commit()
version = version+1
if version != target_version:
- raise DBError("Unable to handle db version %s" % version)
+ raise DBError("Unable to handle %s version %s" % (dbname, version))
return (sqlite3, db)