3 from collections import namedtuple
5 from allmydata.util.dbutil import get_db, DBError
8 # magic-folder db schema version 1
12 version INTEGER -- contains one row, set to 1
15 CREATE TABLE local_files
17 path VARCHAR(1024) PRIMARY KEY, -- UTF-8 filename relative to local magic folder dir
18 -- note that size is before mtime and ctime here, but after in function parameters
19 size INTEGER, -- ST_SIZE, or NULL if the file has been deleted
20 mtime NUMBER, -- ST_MTIME
21 ctime NUMBER, -- ST_CTIME
23 last_uploaded_uri VARCHAR(256), -- URI:CHK:...
24 last_downloaded_uri VARCHAR(256), -- URI:CHK:...
25 last_downloaded_timestamp TIMESTAMP
30 def get_magicfolderdb(dbfile, stderr=sys.stderr,
31 create_version=(SCHEMA_v1, 1), just_create=False):
32 # Open or create the given backupdb file. The parent directory must
35 (sqlite3, db) = get_db(dbfile, stderr, create_version,
36 just_create=just_create, dbname="magicfolderdb")
37 if create_version[1] in (1, 2):
38 return MagicFolderDB(sqlite3, db)
40 print >>stderr, "invalid magicfolderdb schema version specified"
46 PathEntry = namedtuple('PathEntry', 'size mtime ctime version last_uploaded_uri last_downloaded_uri last_downloaded_timestamp')
48 class MagicFolderDB(object):
51 def __init__(self, sqlite_module, connection):
52 self.sqlite_module = sqlite_module
53 self.connection = connection
54 self.cursor = connection.cursor()
56 def get_db_entry(self, relpath_u):
58 Retrieve the entry in the database for a given path, or return None
59 if there is no such entry.
62 c.execute("SELECT size, mtime, ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp"
66 row = self.cursor.fetchone()
70 (size, mtime, ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp) = row
71 return PathEntry(size=size, mtime=mtime, ctime=ctime, version=version,
72 last_uploaded_uri=last_uploaded_uri,
73 last_downloaded_uri=last_downloaded_uri,
74 last_downloaded_timestamp=last_downloaded_timestamp)
76 def get_all_relpaths(self):
78 Retrieve a set of all relpaths of files that have had an entry in magic folder db
79 (i.e. that have been downloaded at least once).
81 self.cursor.execute("SELECT path FROM local_files")
82 rows = self.cursor.fetchall()
83 return set([r[0] for r in rows])
85 def did_upload_version(self, relpath_u, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, pathinfo):
86 print "%r.did_upload_version(%r, %r, %r, %r, %r, %r)" % (self, relpath_u, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, pathinfo)
89 self.cursor.execute("INSERT INTO local_files VALUES (?,?,?,?,?,?,?,?)",
90 (relpath_u, pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp))
91 except (self.sqlite_module.IntegrityError, self.sqlite_module.OperationalError):
93 self.cursor.execute("UPDATE local_files"
94 " SET size=?, mtime=?, ctime=?, version=?, last_uploaded_uri=?, last_downloaded_uri=?, last_downloaded_timestamp=?"
96 (pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, relpath_u))
97 self.connection.commit()