4 from allmydata.util.dbutil import get_db, DBError
7 # magic-folder db schema version 1
11 version INTEGER -- contains one row, set to 1
14 CREATE TABLE local_files
16 path VARCHAR(1024) PRIMARY KEY, -- UTF-8 filename relative to local magic folder dir
17 -- note that size is before mtime and ctime here, but after in function parameters
18 size INTEGER, -- ST_SIZE, or NULL if the file has been deleted
19 mtime NUMBER, -- ST_MTIME
20 ctime NUMBER, -- ST_CTIME
22 last_uploaded_uri VARCHAR(256) UNIQUE, -- URI:CHK:...
23 last_downloaded_uri VARCHAR(256) UNIQUE, -- URI:CHK:...
24 last_downloaded_timestamp TIMESTAMP
29 def get_magicfolderdb(dbfile, stderr=sys.stderr,
30 create_version=(SCHEMA_v1, 1), just_create=False):
31 # Open or create the given backupdb file. The parent directory must
34 (sqlite3, db) = get_db(dbfile, stderr, create_version,
35 just_create=just_create, dbname="magicfolderdb")
36 if create_version[1] in (1, 2):
37 return MagicFolderDB(sqlite3, db)
39 print >>stderr, "invalid magicfolderdb schema version specified"
46 class MagicFolderDB(object):
49 def __init__(self, sqlite_module, connection):
50 self.sqlite_module = sqlite_module
51 self.connection = connection
52 self.cursor = connection.cursor()
54 def check_file_db_exists(self, path):
55 """I will tell you if a given file has an entry in my database or not
56 by returning True or False.
59 c.execute("SELECT size,mtime,ctime"
63 row = self.cursor.fetchone()
69 def get_all_relpaths(self):
71 Retrieve a set of all relpaths of files that have had an entry in magic folder db
72 (i.e. that have been downloaded at least once).
74 self.cursor.execute("SELECT path FROM local_files")
75 rows = self.cursor.fetchall()
76 return set([r[0] for r in rows])
78 def get_last_downloaded_uri(self, relpath_u):
80 Return the last downloaded uri recorded in the magic folder db.
81 If none are found then return None.
84 c.execute("SELECT last_downloaded_uri"
88 row = self.cursor.fetchone()
94 def get_last_uploaded_uri(self, relpath_u):
96 Return the last downloaded uri recorded in the magic folder db.
97 If none are found then return None.
100 c.execute("SELECT last_uploaded_uri"
104 row = self.cursor.fetchone()
110 def get_local_file_version(self, relpath_u):
112 Return the version of a local file tracked by our magic folder db.
113 If no db entry is found then return None.
116 c.execute("SELECT version"
120 row = self.cursor.fetchone()
126 def did_upload_version(self, relpath_u, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, pathinfo):
127 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)
130 self.cursor.execute("INSERT INTO local_files VALUES (?,?,?,?,?,?,?,?)",
131 (relpath_u, pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp))
132 except (self.sqlite_module.IntegrityError, self.sqlite_module.OperationalError):
133 print "err... update"
134 self.cursor.execute("UPDATE local_files"
135 " SET size=?, mtime=?, ctime=?, version=?, last_uploaded_uri=?, last_downloaded_uri=?, last_downloaded_timestamp=?"
137 (pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, relpath_u))
138 self.connection.commit()
141 def is_new_file(self, pathinfo, relpath_u):
143 Returns true if the file's current pathinfo (size, mtime, and ctime) has
144 changed from the pathinfo previously stored in the db.
147 c.execute("SELECT size, mtime, ctime"
151 row = self.cursor.fetchone()
154 if not pathinfo.exists and row[0] is None:
156 return (pathinfo.size, pathinfo.mtime, pathinfo.ctime) != row