Ship a Rust bookmark merger on Desktop
Categories
(Firefox :: Sync, enhancement, P1)
Tracking
()
Tracking | Status | |
---|---|---|
firefox68 | --- | fixed |
People
(Reporter: lina, Assigned: lina)
References
(Blocks 2 open bugs)
Details
Attachments
(6 files, 8 obsolete files)
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review |
Assignee | ||
Comment 1•6 years ago
|
||
Assignee | ||
Comment 2•6 years ago
|
||
Assignee | ||
Comment 3•6 years ago
|
||
Assignee | ||
Comment 4•6 years ago
|
||
Comment 5•6 years ago
|
||
Assignee | ||
Comment 6•6 years ago
|
||
Comment 7•6 years ago
|
||
Assignee | ||
Comment 8•6 years ago
|
||
Assignee | ||
Comment 9•6 years ago
|
||
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 10•6 years ago
|
||
Comment 11•6 years ago
|
||
Comment 12•6 years ago
|
||
Assignee | ||
Comment 13•6 years ago
|
||
Assignee | ||
Comment 14•6 years ago
|
||
Assignee | ||
Comment 15•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Comment 16•6 years ago
|
||
Updated•6 years ago
|
Assignee | ||
Comment 17•6 years ago
|
||
Whew, time flies! ⏰🦋 A few things changed in the last few months, to where I think it's feasible to push on this:
- Dogear (the Rust merger) has tests for the merge algorithm, but no integration tests that apply the merged tree to Places.
- We're planning to use Dogear for bookmark syncing on mobile.
- We're working on a Rust Places port that mostly uses the same schema, meaning we can also reuse many of Desktop's existing tests.
- Dogear has changed significantly to fix up diverging structure (https://github.com/linacambridge/dogear/pull/19), and backporting those changes to the JS merger is impractical.
- Myk added thread-safe task runnables over in bug 1490496. 🎉
The trickiest part of this patch was creating and managing the mirror DB connection from Rust...so what if we kept all that in JS? We can still fetch the local and remote trees, build our merged tree, and populate mergeStates
(https://searchfox.org/mozilla-central/rev/c07aaf12f13037c1f5a343d31f8291549e57373f/toolkit/components/places/SyncedBookmarksMirror.jsm#535-604,1342-1356,1374-1387) in Rust (and off the main thread!), then call back into JS to record telemetry, apply the tree, stage items for upload, and so on.
With this approach, the Rust code wouldn't clone the Places DB connection or initialize the schema; it'd just take a handle to the connection that the JS code has already set up.
This would mean two transactions per merge: one in Rust to insert everything into mergeStates
, and one in JS to apply. I'm not too worried about that, though...most syncs won't make any changes at all, so we can skip merging entirely; the old bookmarks engine runs several transactions per item; and we still have our totalSyncChanges
check to ensure we can safely merge outside of a transaction.
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Assignee | ||
Comment 18•6 years ago
|
||
Assignee | ||
Comment 19•6 years ago
|
||
Depends on D18008
Assignee | ||
Comment 20•6 years ago
|
||
Storing a handle to the storage connection in mozISyncedBookmarkMerger.db
leaks strings. 😮 I instrumented nsStringBuffer
and nsStringStats
to record allocations and releases, and see something like this for a test run:
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
0:03.03 pid:35555 LEAKED: /var/folders/v7/bzb2q9rn56d2rykmwdxgs7z80000gn/T/firefox/xpcshellprofile/places.sqlite
0:03.03 pid:35555 LEAKED: places.sqlite
Nulling out merger
in SyncedBookmarksMirror#finalize
(where we also call this.db.close()
) fixes that, so I guess this has to do with the Rust merger keeping a reference to the connection alive after we've closed it from JS?
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 22•6 years ago
|
||
Depends on D18009
Assignee | ||
Comment 23•6 years ago
|
||
Depends on D18764
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Assignee | ||
Comment 24•6 years ago
|
||
This commit wraps just enough of the mozStorage API to support the
bookmarks mirror. It's not complete: for example, there's no way
to open, clone, or close a connection, because the mirror handles
that from JS. The wrapper also omits shutdown blocking and retrying on
SQLITE_BUSY
.
This commit also changes asyncClone
to propagate the parent's
mAsyncOnly
flag, so that asynchronously cloned sync connections
can still QI to mozIStorageConnection
.
Finally, we expose an OpenedConnection::storageConnection
getter
in Sqlite.jsm, for JS code to access the underlying connection.
Assignee | ||
Comment 25•6 years ago
|
||
This commit adds ThreadPtr{Handle, Holder}
to wrap an XpCom
object
with thread-safe refcounting. These are analagous to
nsMainThreadPtr{Handle, Holder}
, but can hold references to
objects from any thread, not just the main thread.
ThreadPtrHolder
is similar to ThreadBoundRefPtr
. However, it's
not possible to clone a ThreadBoundRefPtr
, so it can't be shared
among tasks. This is fine for objects that are only used once, like
callbacks. However, ThreadBoundRefPtr
doesn't work well for loggers
or event emitters, which might need to be called multiple times on
the owning thread.
Unlike a ThreadBoundRefPtr
, it's allowed and expected to
clone and drop a ThreadPtrHolder
on other threads. Internally,
the holder keeps an atomic refcount, and releases the wrapped object
on the owning thread once the count reaches zero.
This commit also changes TaskRunnable
to support dispatching from
threads other than the main thread.
Depends on D20073
Assignee | ||
Comment 26•6 years ago
|
||
Depends on D20074
Assignee | ||
Comment 27•6 years ago
|
||
This commit introduces a Rust XPCOM component,
mozISyncedBookmarksMerger
, that wraps the Dogear crate for
merging and applying synced bookmarks.
How this works: SyncedBookmarksMirror.jsm
manages opening
the connection, initializing the schema, and writing incoming
items into the mirror database. The new mozISyncedBookmarksMerger
holds a handle to the same connection. When JS code calls
mozISyncedBookmarksMerger::apply
, the merger builds local and
remote trees, produces a merged tree, applies the tree back to Places,
and stages outgoing items for upload in a temp table, all on the
storage thread. It then calls back in to JS, which inflates Sync
records for outgoing items, notifies Places observers, and cleans up.
Since Dogear has a more robust merging algorithm that attempts to fix
up invalid trees, test_bookmark_kinds.js
and
test_bookmark_corruption.js
intentionally fail. This is fixed in the
next commit, which changes the merger to handle invalid structure.
Depends on D20075
Assignee | ||
Comment 28•6 years ago
|
||
Depends on D20076
Assignee | ||
Comment 29•6 years ago
|
||
Depends on D20077
Updated•6 years ago
|
Updated•6 years ago
|
Comment 30•6 years ago
|
||
There are some r+ patches which didn't land and no activity in this bug for 2 weeks.
:lina, could you have a look please?
Assignee | ||
Comment 31•6 years ago
|
||
Full try run for linux64 here: https://treeherder.mozilla.org/#/jobs?repo=try&revision=14dfa19c786998e3db710031b7f4d0f08b9d454a&selectedJob=235744293
...And green for all platforms here, once I fixed the use-after-free 😂: https://treeherder.mozilla.org/#/jobs?repo=try&revision=35ea32896a12835b4143f319aa2d80b9683565b6
Let's land this thing!
Comment 32•6 years ago
|
||
Comment 33•6 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/cfd44c936a9b
https://hg.mozilla.org/mozilla-central/rev/e2042d55b76e
https://hg.mozilla.org/mozilla-central/rev/6e5efb9dbc99
https://hg.mozilla.org/mozilla-central/rev/4782957f96a4
https://hg.mozilla.org/mozilla-central/rev/e7282f4449c8
https://hg.mozilla.org/mozilla-central/rev/4a692c812a3f
Assignee | ||
Updated•6 years ago
|
Updated•6 years ago
|
Comment 35•6 years ago
|
||
Saw this in "These Weeks in Firefox: Issue 56" - https://blog.nightly.mozilla.org/2019/04/05/these-weeks-in-firefox-issue-56/ and looked for the services.sync.bookmarks.buffer.enabled pref in about:config.
Don't see it in build id 20190412093400 - do I need to add a new boolean pref for it?
Assignee | ||
Comment 36•6 years ago
|
||
Aaaah, sorry, thanks for catching that, and for testing! I just updated the post; the correct pref name is services.sync.engine.bookmarks.buffer
.
Description
•