summavy/indexer/
merge_operation.rs

1use std::collections::HashSet;
2use std::ops::Deref;
3
4use crate::{Inventory, Opstamp, SegmentId, TrackedObject};
5
6#[derive(Default)]
7pub(crate) struct MergeOperationInventory(Inventory<InnerMergeOperation>);
8
9impl Deref for MergeOperationInventory {
10    type Target = Inventory<InnerMergeOperation>;
11
12    fn deref(&self) -> &Self::Target {
13        &self.0
14    }
15}
16
17impl MergeOperationInventory {
18    pub fn segment_in_merge(&self) -> HashSet<SegmentId> {
19        let mut segment_in_merge = HashSet::default();
20        for merge_op in self.list() {
21            for &segment_id in &merge_op.segment_ids {
22                segment_in_merge.insert(segment_id);
23            }
24        }
25        segment_in_merge
26    }
27}
28
29/// A `MergeOperation` has two roles.
30/// It carries all of the information required to describe a merge:
31/// - `target_opstamp` is the opstamp up to which we want to consume the
32/// delete queue and reflect their deletes.
33/// - `segment_ids` is the list of segment to be merged.
34///
35/// The second role is to ensure keep track of the fact that these
36/// segments are in merge and avoid starting a merge operation that
37/// may conflict with this one.
38///
39/// This works by tracking merge operations. When considering computing
40/// merge candidates, we simply list tracked merge operations and remove
41/// their segments from possible merge candidates.
42pub struct MergeOperation {
43    inner: TrackedObject<InnerMergeOperation>,
44}
45
46pub(crate) struct InnerMergeOperation {
47    target_opstamp: Opstamp,
48    segment_ids: Vec<SegmentId>,
49    merged_segment_attributes: Option<serde_json::Value>,
50}
51
52impl MergeOperation {
53    pub(crate) fn new(
54        inventory: &MergeOperationInventory,
55        target_opstamp: Opstamp,
56        segment_ids: Vec<SegmentId>,
57        segment_attributes: Option<serde_json::Value>,
58    ) -> MergeOperation {
59        let inner_merge_operation = InnerMergeOperation {
60            target_opstamp,
61            segment_ids,
62            merged_segment_attributes: segment_attributes,
63        };
64        MergeOperation {
65            inner: inventory.track(inner_merge_operation),
66        }
67    }
68
69    pub fn target_opstamp(&self) -> Opstamp {
70        self.inner.target_opstamp
71    }
72
73    pub fn segment_ids(&self) -> &[SegmentId] {
74        &self.inner.segment_ids[..]
75    }
76
77    pub fn segment_attributes(&self) -> &Option<serde_json::Value> {
78        &self.inner.merged_segment_attributes
79    }
80}