From 714a7de84aeae3b5e6867afacb0a4aeb0f4f93e0 Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone Date: Mon, 18 Feb 2019 11:47:24 -0500 Subject: [PATCH] Associate an Eliot action with magicfolder database updates --- src/allmydata/magicfolderdb.py | 122 ++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 17 deletions(-) diff --git a/src/allmydata/magicfolderdb.py b/src/allmydata/magicfolderdb.py index f9158862e..8a93f9ddb 100644 --- a/src/allmydata/magicfolderdb.py +++ b/src/allmydata/magicfolderdb.py @@ -4,6 +4,86 @@ from collections import namedtuple from allmydata.util.dbutil import get_db, DBError +from eliot._validation import ( + ValidationError, +) +from eliot import ( + Field, + ActionType, +) + +def _validateInstanceOf(t): + """ + Return an Eliot validator that requires values to be instances of ``t``. + """ + def validator(v): + if not isinstance(v, t): + raise ValidationError("{} not an instance of {}".format(v, t)) + return validator + +def _validateSetMembership(s): + """ + Return an Eliot validator that requires values to be elements of ``s``. + """ + def validator(v): + if v not in s: + raise ValidationError("{} not in {}".format(v, s)) + return validator + +PathEntry = namedtuple('PathEntry', 'size mtime_ns ctime_ns version last_uploaded_uri ' + 'last_downloaded_uri last_downloaded_timestamp') + +_RELPATH = Field.for_types( + u"relpath", + [unicode], + u"The relative path of a file in a magic-folder.", +) + +_VERSION = Field.for_types( + u"version", + [int, long], + u"The version of the file.", +) + +_UPLOADED_URI = Field.for_types( + u"last-uploaded-uri", + [unicode], + u"The filecap to which this version of this file was uploaded.", +) + +_DOWNLOADED_URI = Field.for_types( + u"last-downloaded-uri", + [unicode], + u"The filecap from which the previous version of this file was downloaded.", +) + +_DOWNLOADED_TIMESTAMP = Field.for_types( + u"last-downloaded-timestamp", + [unicode], + u"(XXX probably not really, don't trust this) The timestamp of the last download of this file.", +) + +_PATHINFO = Field( + u"pathinfo", + lambda v: tuple(v), + u"The metadata for this version of this file.", + _validateInstanceOf(PathEntry), +) + +_INSERT_OR_UPDATE = Field.for_types( + u"inserted-or-updated", + [unicode], + u"An indication of whether the record for this upload was new or an update to a previous entry.", + _validateSetMembership({u"insert", u"update"}), +) + +DID_UPLOAD_VERSION = ActionType( + u"magic-folder-db:did-upload-version", + [_RELPATH, _VERSION, _UPLOADED_URI, _DOWNLOADED_URI, _DOWNLOADED_TIMESTAMP, _PATHINFO], + [_INSERT_OR_UPDATE], + u"An file upload is being recorded in the database.", +) + # magic-folder db schema version 1 SCHEMA_v1 = """ @@ -42,9 +122,6 @@ def get_magicfolderdb(dbfile, stderr=sys.stderr, print >>stderr, e return None -PathEntry = namedtuple('PathEntry', 'size mtime_ns ctime_ns version last_uploaded_uri ' - 'last_downloaded_uri last_downloaded_timestamp') - class MagicFolderDB(object): VERSION = 1 @@ -88,17 +165,28 @@ class MagicFolderDB(object): return set([r[0] for r in rows]) def did_upload_version(self, relpath_u, version, last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, pathinfo): - try: - self.cursor.execute("INSERT INTO local_files VALUES (?,?,?,?,?,?,?,?)", - (relpath_u, pathinfo.size, pathinfo.mtime_ns, pathinfo.ctime_ns, - version, last_uploaded_uri, last_downloaded_uri, - last_downloaded_timestamp)) - except (self.sqlite_module.IntegrityError, self.sqlite_module.OperationalError): - self.cursor.execute("UPDATE local_files" - " SET size=?, mtime_ns=?, ctime_ns=?, version=?, last_uploaded_uri=?," - " last_downloaded_uri=?, last_downloaded_timestamp=?" - " WHERE path=?", - (pathinfo.size, pathinfo.mtime_ns, pathinfo.ctime_ns, version, - last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, - relpath_u)) - self.connection.commit() + action = DID_UPLOAD_VERSION( + relpath=relpath_u, + version=version, + uploaded_uri=last_uploaded_uri, + downloaded_uri=last_downloaded_uri, + downloaded_timestamp=last_downloaded_timestamp, + pathinfo=pathinfo, + ) + with action: + try: + self.cursor.execute("INSERT INTO local_files VALUES (?,?,?,?,?,?,?,?)", + (relpath_u, pathinfo.size, pathinfo.mtime_ns, pathinfo.ctime_ns, + version, last_uploaded_uri, last_downloaded_uri, + last_downloaded_timestamp)) + action.add_success_fields(insert_or_update=u"insert") + except (self.sqlite_module.IntegrityError, self.sqlite_module.OperationalError): + self.cursor.execute("UPDATE local_files" + " SET size=?, mtime_ns=?, ctime_ns=?, version=?, last_uploaded_uri=?," + " last_downloaded_uri=?, last_downloaded_timestamp=?" + " WHERE path=?", + (pathinfo.size, pathinfo.mtime_ns, pathinfo.ctime_ns, version, + last_uploaded_uri, last_downloaded_uri, last_downloaded_timestamp, + relpath_u)) + action.add_success_fields(inserted_or_updated=u"update") + self.connection.commit()