uqa_storage/catalog/graph_observations/
labels.rs1mod projection;
10
11use sha2::{Digest, Sha256};
12
13use super::{GraphDefinitionKey, GraphDefinitionKind, GraphIdentifierNamespace};
14use crate::mvcc::{SerializableKeySpace, SerializablePredicate};
15use crate::{read_control::StorageReadControl, KeyValueBatch, StorageBackendResult};
16
17#[derive(Clone, Copy)]
18pub enum GraphLabelName<'a> {
19 Named(&'a str),
20 Reserved(u32),
21}
22
23pub struct GraphLabelDefinitionKey {
25 object: [u8; 16],
26 key: Option<[u8; 33]>,
27}
28
29impl GraphLabelDefinitionKey {
30 pub fn new(
31 namespace: GraphIdentifierNamespace,
32 graph: &str,
33 label: Option<GraphLabelName<'_>>,
34 ) -> Self {
35 let mut digest = Sha256::new();
36 digest.update(namespace.serializable_scope_object());
37 digest.update(b"graph-labels");
38 digest.update(graph.as_bytes());
39 let mut object = [0; 16];
40 object.copy_from_slice(&digest.finalize()[..16]);
41 if object == [0; 16] {
42 object[15] = 1;
43 }
44 let key = label.map(|label| {
45 let mut key = [0; 33];
46 match label {
47 GraphLabelName::Named(name) => {
48 key[0] = b'n';
49 key[1..].copy_from_slice(&Sha256::digest(name.as_bytes()));
50 }
51 GraphLabelName::Reserved(id) => {
52 key[0] = b'd';
53 key[1..5].copy_from_slice(&id.to_be_bytes());
54 }
55 }
56 key
57 });
58 Self { object, key }
59 }
60
61 pub fn predicate(&self) -> SerializablePredicate<'_> {
62 self.key.as_ref().map_or_else(
63 || SerializablePredicate::object(self.object),
64 |key| SerializablePredicate::point(self.object, SerializableKeySpace::Graph, key),
65 )
66 }
67}
68
69pub fn observe_label_registry_change(
71 namespace: GraphIdentifierNamespace,
72 graph: &str,
73 old: Option<&str>,
74 new: Option<&str>,
75 batch: &mut dyn KeyValueBatch,
76 control: &StorageReadControl,
77) -> StorageBackendResult<()> {
78 if batch.serializable_participant().is_none() || old == new {
79 return Ok(());
80 }
81 control.check()?;
82 batch.observe_serializable_write(
83 GraphDefinitionKey::new(namespace, GraphDefinitionKind::LabelRegistry, Some(graph))
84 .predicate(),
85 )?;
86 let key = GraphLabelDefinitionKey::new(namespace, graph, None);
87 let (Some(old), Some(new)) = (
88 projection::Registry::decode(old, control)?,
89 projection::Registry::decode(new, control)?,
90 ) else {
91 return batch.observe_serializable_write(key.predicate());
92 };
93 for id in [1_u32, 2] {
94 if old.dropped(id) != new.dropped(id) || old.reserved_alias(id) != new.reserved_alias(id) {
95 batch.observe_serializable_write(
96 GraphLabelDefinitionKey::new(namespace, graph, Some(GraphLabelName::Reserved(id)))
97 .predicate(),
98 )?;
99 }
100 }
101 old.visit_changes(&new, control, |name| {
102 let mut bytes = [b'n'; 33];
103 bytes[1..].copy_from_slice(name);
104 batch.observe_serializable_write(SerializablePredicate::point(
105 key.object,
106 SerializableKeySpace::Graph,
107 &bytes,
108 ))
109 })
110}