]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - src/allmydata/magicfolderdb.py
0c76a7b012a6cbc3ffd38c32d93032010599bf4b
[tahoe-lafs/tahoe-lafs.git] / src / allmydata / magicfolderdb.py
1
2 import sys
3
4 from allmydata.util.dbutil import get_db, DBError
5
6
7 # magic-folder db schema version 1
8 SCHEMA_v1 = """
9 CREATE TABLE version
10 (
11  version INTEGER  -- contains one row, set to 1
12 );
13
14 CREATE TABLE local_files
15 (
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
21  version             INTEGER,
22  last_uploaded_uri   VARCHAR(256) UNIQUE,       -- URI:CHK:...
23  last_downloaded_uri VARCHAR(256) UNIQUE,       -- URI:CHK:...
24  last_downloaded_timestamp TIMESTAMP
25 );
26 """
27
28
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
32     # exist.
33     try:
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)
38         else:
39             print >>stderr, "invalid magicfolderdb schema version specified"
40             return None
41     except DBError, e:
42         print >>stderr, e
43         return None
44
45
46 class MagicFolderDB(object):
47     VERSION = 1
48
49     def __init__(self, sqlite_module, connection):
50         self.sqlite_module = sqlite_module
51         self.connection = connection
52         self.cursor = connection.cursor()
53
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.
57         """
58         c = self.cursor
59         c.execute("SELECT size,mtime,ctime"
60                   " FROM local_files"
61                   " WHERE path=?",
62                   (path,))
63         row = self.cursor.fetchone()
64         if not row:
65             return False
66         else:
67             return True
68
69     def get_all_relpaths(self):
70         """
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).
73         """
74         self.cursor.execute("SELECT path FROM local_files")
75         rows = self.cursor.fetchall()
76         return set([r[0] for r in rows])
77
78     def get_last_downloaded_uri(self, relpath_u):
79         """
80         Return the last downloaded uri recorded in the magic folder db.
81         If none are found then return None.
82         """
83         c = self.cursor
84         c.execute("SELECT last_downloaded_uri"
85                   " FROM local_files"
86                   " WHERE path=?",
87                   (relpath_u,))
88         row = self.cursor.fetchone()
89         if not row:
90             return None
91         else:
92             return row[0]
93
94     def get_local_file_version(self, relpath_u):
95         """
96         Return the version of a local file tracked by our magic folder db.
97         If no db entry is found then return None.
98         """
99         c = self.cursor
100         c.execute("SELECT version"
101                   " FROM local_files"
102                   " WHERE path=?",
103                   (relpath_u,))
104         row = self.cursor.fetchone()
105         if not row:
106             return None
107         else:
108             return row[0]
109
110     def did_upload_version(self, relpath_u, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, pathinfo):
111         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)
112         try:
113             print "insert"
114             self.cursor.execute("INSERT INTO local_files VALUES (?,?,?,?,?,?,?,?)",
115                                 (relpath_u, pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp))
116         except (self.sqlite_module.IntegrityError, self.sqlite_module.OperationalError):
117             print "err... update"
118             self.cursor.execute("UPDATE local_files"
119                                 " SET size=?, mtime=?, ctime=?, version=?, last_uploaded_uri=?, last_downloaded_uri=?, last_downloaded_timestamp=?"
120                                 " WHERE path=?",
121                                 (pathinfo.size, pathinfo.mtime, pathinfo.ctime, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, relpath_u))
122         self.connection.commit()
123         print "committed"
124
125     def is_new_file(self, pathinfo, relpath_u):
126         """
127         Returns true if the file's current pathinfo (size, mtime, and ctime) has
128         changed from the pathinfo previously stored in the db.
129         """
130         c = self.cursor
131         c.execute("SELECT size, mtime, ctime"
132                   " FROM local_files"
133                   " WHERE path=?",
134                   (relpath_u,))
135         row = self.cursor.fetchone()
136         if not row:
137             return True
138         if not pathinfo.exists and row[0] is None:
139             return False
140         return (pathinfo.size, pathinfo.mtime, pathinfo.ctime) != row