diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/dogear/src/store.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/dogear/src/store.rs')
-rw-r--r-- | third_party/rust/dogear/src/store.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/third_party/rust/dogear/src/store.rs b/third_party/rust/dogear/src/store.rs new file mode 100644 index 0000000000..7ada8407fc --- /dev/null +++ b/third_party/rust/dogear/src/store.rs @@ -0,0 +1,117 @@ +// Copyright 2018-2019 Mozilla + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{time::Duration, time::Instant}; + +use crate::driver::{ + AbortSignal, DefaultAbortSignal, DefaultDriver, Driver, TelemetryEvent, TreeStats, +}; +use crate::error::Error; +use crate::guid::Guid; +use crate::merge::{MergedRoot, Merger}; +use crate::tree::Tree; + +/// A store is the main interface to Dogear. It implements methods for building +/// local and remote trees from a storage backend, fetching content info for +/// matching items with similar contents, and persisting the merged tree. +pub trait Store { + /// The type returned from a successful merge. + type Ok; + + /// The type returned in the event of a store error. + type Error: From<Error>; + + /// Builds a fully rooted, consistent tree from the items and tombstones in + /// the local store. + fn fetch_local_tree(&self) -> Result<Tree, Self::Error>; + + /// Builds a fully rooted, consistent tree from the items and tombstones in + /// the mirror. + fn fetch_remote_tree(&self) -> Result<Tree, Self::Error>; + + /// Applies the merged root to the local store, and stages items for + /// upload. On Desktop, this method inserts the merged tree into a temp + /// table, updates Places, and inserts outgoing items into another + /// temp table. + fn apply<'t>(&mut self, root: MergedRoot<'t>) -> Result<Self::Ok, Self::Error>; + + /// Builds and applies a merged tree using the default merge driver. + fn merge(&mut self) -> Result<Self::Ok, Self::Error> { + self.merge_with_driver(&DefaultDriver, &DefaultAbortSignal) + } + + /// Builds a complete merged tree from the local and remote trees, resolves + /// conflicts, dedupes local items, and applies the merged tree using the + /// given driver. + fn merge_with_driver( + &mut self, + driver: &impl Driver, + signal: &impl AbortSignal, + ) -> Result<Self::Ok, Self::Error> { + signal.err_if_aborted()?; + debug!(driver, "Building local tree"); + let (local_tree, time) = with_timing(|| self.fetch_local_tree())?; + driver.record_telemetry_event(TelemetryEvent::FetchLocalTree(TreeStats { + items: local_tree.size(), + deletions: local_tree.deletions().len(), + problems: local_tree.problems().counts(), + time, + })); + trace!(driver, "Built local tree from mirror\n{}", local_tree); + + signal.err_if_aborted()?; + debug!(driver, "Building remote tree"); + let (remote_tree, time) = with_timing(|| self.fetch_remote_tree())?; + driver.record_telemetry_event(TelemetryEvent::FetchRemoteTree(TreeStats { + items: remote_tree.size(), + deletions: local_tree.deletions().len(), + problems: remote_tree.problems().counts(), + time, + })); + trace!(driver, "Built remote tree from mirror\n{}", remote_tree); + + signal.err_if_aborted()?; + debug!(driver, "Building merged tree"); + let merger = Merger::with_driver(driver, signal, &local_tree, &remote_tree); + let (merged_root, time) = with_timing(|| merger.merge())?; + driver.record_telemetry_event(TelemetryEvent::Merge(time, *merged_root.counts())); + trace!( + driver, + "Built new merged tree\n{}\nDelete Locally: [{}]\nDelete Remotely: [{}]", + merged_root.node().to_ascii_string(), + merged_root + .local_deletions() + .map(Guid::as_str) + .collect::<Vec<_>>() + .join(", "), + merged_root + .remote_deletions() + .map(Guid::as_str) + .collect::<Vec<_>>() + .join(", ") + ); + + signal.err_if_aborted()?; + debug!(driver, "Applying merged tree"); + let (result, time) = with_timing(|| self.apply(merged_root))?; + driver.record_telemetry_event(TelemetryEvent::Apply(time)); + + Ok(result) + } +} + +fn with_timing<T, E>(run: impl FnOnce() -> Result<T, E>) -> Result<(T, Duration), E> { + let now = Instant::now(); + run().map(|value| (value, now.elapsed())) +} |