2021-11-01 01:58:26 +00:00
|
|
|
|
2020-08-26 11:15:52 -04:00
|
|
|
/// Builds a StateMap by iterating over all keys that start
|
|
|
|
/// with state_hash, this gives the full state for the given state_hash.
|
2021-08-19 11:01:18 +02:00
|
|
|
#[tracing::instrument(skip(self))]
|
2022-06-18 16:38:41 +02:00
|
|
|
pub async fn state_full_ids(&self, shortstatehash: u64) -> Result<BTreeMap<u64, Arc<EventId>>> {
|
2021-08-12 23:04:00 +02:00
|
|
|
let full_state = self
|
|
|
|
.load_shortstatehash_info(shortstatehash)?
|
|
|
|
.pop()
|
|
|
|
.expect("there is always one layer")
|
|
|
|
.1;
|
2022-06-18 16:38:41 +02:00
|
|
|
let mut result = BTreeMap::new();
|
|
|
|
let mut i = 0;
|
|
|
|
for compressed in full_state.into_iter() {
|
|
|
|
let parsed = self.parse_compressed_state_event(compressed)?;
|
|
|
|
result.insert(parsed.0, parsed.1);
|
|
|
|
|
|
|
|
i += 1;
|
|
|
|
if i % 100 == 0 {
|
|
|
|
tokio::task::yield_now().await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(result)
|
2021-03-17 22:30:25 +01:00
|
|
|
}
|
|
|
|
|
2021-08-19 11:01:18 +02:00
|
|
|
#[tracing::instrument(skip(self))]
|
2022-06-18 16:38:41 +02:00
|
|
|
pub async fn state_full(
|
2021-03-17 22:30:25 +01:00
|
|
|
&self,
|
|
|
|
shortstatehash: u64,
|
2022-04-06 21:31:29 +02:00
|
|
|
) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
2021-08-12 23:04:00 +02:00
|
|
|
let full_state = self
|
|
|
|
.load_shortstatehash_info(shortstatehash)?
|
|
|
|
.pop()
|
|
|
|
.expect("there is always one layer")
|
|
|
|
.1;
|
2022-06-18 16:38:41 +02:00
|
|
|
|
|
|
|
let mut result = HashMap::new();
|
|
|
|
let mut i = 0;
|
|
|
|
for compressed in full_state {
|
|
|
|
let (_, eventid) = self.parse_compressed_state_event(compressed)?;
|
|
|
|
if let Some(pdu) = self.get_pdu(&eventid)? {
|
|
|
|
result.insert(
|
2020-09-17 14:44:47 +02:00
|
|
|
(
|
2022-04-06 21:31:29 +02:00
|
|
|
pdu.kind.to_string().into(),
|
2020-09-17 14:44:47 +02:00
|
|
|
pdu.state_key
|
|
|
|
.as_ref()
|
|
|
|
.ok_or_else(|| Error::bad_database("State event has no state key."))?
|
|
|
|
.clone(),
|
|
|
|
),
|
|
|
|
pdu,
|
2022-06-18 16:38:41 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
i += 1;
|
|
|
|
if i % 100 == 0 {
|
|
|
|
tokio::task::yield_now().await;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(result)
|
2020-08-06 08:29:59 -04:00
|
|
|
}
|
|
|
|
|
2020-09-17 14:44:47 +02:00
|
|
|
/// Returns a single PDU from `room_id` with key (`event_type`, `state_key`).
|
2021-02-28 12:41:03 +01:00
|
|
|
#[tracing::instrument(skip(self))]
|
2021-04-11 21:01:27 +02:00
|
|
|
pub fn state_get_id(
|
2020-09-17 14:44:47 +02:00
|
|
|
&self,
|
2021-03-17 22:30:25 +01:00
|
|
|
shortstatehash: u64,
|
2022-04-06 21:31:29 +02:00
|
|
|
event_type: &StateEventType,
|
2020-09-17 14:44:47 +02:00
|
|
|
state_key: &str,
|
2021-08-26 17:58:32 -04:00
|
|
|
) -> Result<Option<Arc<EventId>>> {
|
2021-08-12 23:04:00 +02:00
|
|
|
let shortstatekey = match self.get_shortstatekey(event_type, state_key)? {
|
|
|
|
Some(s) => s,
|
|
|
|
None => return Ok(None),
|
|
|
|
};
|
|
|
|
let full_state = self
|
|
|
|
.load_shortstatehash_info(shortstatehash)?
|
|
|
|
.pop()
|
|
|
|
.expect("there is always one layer")
|
|
|
|
.1;
|
|
|
|
Ok(full_state
|
|
|
|
.into_iter()
|
|
|
|
.find(|bytes| bytes.starts_with(&shortstatekey.to_be_bytes()))
|
2021-08-24 19:10:31 +02:00
|
|
|
.and_then(|compressed| {
|
|
|
|
self.parse_compressed_state_event(compressed)
|
|
|
|
.ok()
|
|
|
|
.map(|(_, id)| id)
|
|
|
|
}))
|
2020-08-06 08:29:59 -04:00
|
|
|
}
|
|
|
|
|
2021-04-11 21:01:27 +02:00
|
|
|
/// Returns a single PDU from `room_id` with key (`event_type`, `state_key`).
|
|
|
|
#[tracing::instrument(skip(self))]
|
|
|
|
pub fn state_get(
|
|
|
|
&self,
|
|
|
|
shortstatehash: u64,
|
2022-04-06 21:31:29 +02:00
|
|
|
event_type: &StateEventType,
|
2021-04-11 21:01:27 +02:00
|
|
|
state_key: &str,
|
2021-06-30 09:52:01 +02:00
|
|
|
) -> Result<Option<Arc<PduEvent>>> {
|
2021-04-11 21:01:27 +02:00
|
|
|
self.state_get_id(shortstatehash, event_type, state_key)?
|
|
|
|
.map_or(Ok(None), |event_id| self.get_pdu(&event_id))
|
|
|
|
}
|
|
|
|
|
2021-01-16 16:37:20 -05:00
|
|
|
/// Returns the state hash for this pdu.
|
2021-03-17 22:30:25 +01:00
|
|
|
pub fn pdu_shortstatehash(&self, event_id: &EventId) -> Result<Option<u64>> {
|
|
|
|
self.eventid_shorteventid
|
|
|
|
.get(event_id.as_bytes())?
|
|
|
|
.map_or(Ok(None), |shorteventid| {
|
2021-10-13 11:51:30 +02:00
|
|
|
self.shorteventid_shortstatehash
|
|
|
|
.get(&shorteventid)?
|
|
|
|
.map(|bytes| {
|
|
|
|
utils::u64_from_bytes(&bytes).map_err(|_| {
|
2021-03-17 22:30:25 +01:00
|
|
|
Error::bad_database(
|
|
|
|
"Invalid shortstatehash bytes in shorteventid_shortstatehash",
|
|
|
|
)
|
2021-10-13 11:51:30 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
.transpose()
|
2021-03-17 22:30:25 +01:00
|
|
|
})
|
2020-09-17 14:44:47 +02:00
|
|
|
}
|
2020-08-06 08:29:59 -04:00
|
|
|
|
2020-10-27 19:10:09 -04:00
|
|
|
/// Returns the last state hash key added to the db for the given room.
|
2021-02-28 12:41:03 +01:00
|
|
|
#[tracing::instrument(skip(self))]
|
2021-03-17 22:30:25 +01:00
|
|
|
pub fn current_shortstatehash(&self, room_id: &RoomId) -> Result<Option<u64>> {
|
|
|
|
self.roomid_shortstatehash
|
|
|
|
.get(room_id.as_bytes())?
|
|
|
|
.map_or(Ok(None), |bytes| {
|
|
|
|
Ok(Some(utils::u64_from_bytes(&bytes).map_err(|_| {
|
|
|
|
Error::bad_database("Invalid shortstatehash in roomid_shortstatehash")
|
|
|
|
})?))
|
|
|
|
})
|
2020-08-06 08:29:59 -04:00
|
|
|
}
|
|
|
|
|
2020-10-27 19:10:09 -04:00
|
|
|
/// Force the creation of a new StateHash and insert it into the db.
|
2020-11-15 16:48:43 -05:00
|
|
|
///
|
2021-08-12 23:04:00 +02:00
|
|
|
/// Whatever `state` is supplied to `force_state` becomes the new current room state snapshot.
|
2021-08-24 19:10:31 +02:00
|
|
|
#[tracing::instrument(skip(self, new_state_ids_compressed, db))]
|
2020-09-13 22:24:36 +02:00
|
|
|
pub fn force_state(
|
|
|
|
&self,
|
|
|
|
room_id: &RoomId,
|
2021-08-24 19:10:31 +02:00
|
|
|
new_state_ids_compressed: HashSet<CompressedStateEvent>,
|
2021-04-16 18:18:29 +02:00
|
|
|
db: &Database,
|
2020-09-13 22:24:36 +02:00
|
|
|
) -> Result<()> {
|
2021-09-13 19:45:56 +02:00
|
|
|
let previous_shortstatehash = self.current_shortstatehash(room_id)?;
|
2021-08-12 23:04:00 +02:00
|
|
|
|
2021-03-17 22:30:25 +01:00
|
|
|
let state_hash = self.calculate_hash(
|
2021-08-24 19:10:31 +02:00
|
|
|
&new_state_ids_compressed
|
|
|
|
.iter()
|
|
|
|
.map(|bytes| &bytes[..])
|
2021-03-17 22:30:25 +01:00
|
|
|
.collect::<Vec<_>>(),
|
2021-03-24 11:52:10 +01:00
|
|
|
);
|
2020-09-13 22:24:36 +02:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let (new_shortstatehash, already_existed) =
|
2021-08-11 19:15:38 +02:00
|
|
|
self.get_or_create_shortstatehash(&state_hash, &db.globals)?;
|
2021-03-17 22:30:25 +01:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
if Some(new_shortstatehash) == previous_shortstatehash {
|
|
|
|
return Ok(());
|
|
|
|
}
|
2021-04-16 18:18:29 +02:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let states_parents = previous_shortstatehash
|
|
|
|
.map_or_else(|| Ok(Vec::new()), |p| self.load_shortstatehash_info(p))?;
|
2021-04-16 18:18:29 +02:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let (statediffnew, statediffremoved) = if let Some(parent_stateinfo) = states_parents.last()
|
|
|
|
{
|
2021-10-13 11:51:30 +02:00
|
|
|
let statediffnew: HashSet<_> = new_state_ids_compressed
|
2021-08-12 23:04:00 +02:00
|
|
|
.difference(&parent_stateinfo.1)
|
2021-10-13 10:24:39 +02:00
|
|
|
.copied()
|
2021-10-13 11:51:30 +02:00
|
|
|
.collect();
|
2021-08-12 23:04:00 +02:00
|
|
|
|
2021-10-13 11:51:30 +02:00
|
|
|
let statediffremoved: HashSet<_> = parent_stateinfo
|
2021-08-12 23:04:00 +02:00
|
|
|
.1
|
|
|
|
.difference(&new_state_ids_compressed)
|
2021-10-13 10:24:39 +02:00
|
|
|
.copied()
|
2021-10-13 11:51:30 +02:00
|
|
|
.collect();
|
2021-08-12 23:04:00 +02:00
|
|
|
|
|
|
|
(statediffnew, statediffremoved)
|
2021-04-16 18:18:29 +02:00
|
|
|
} else {
|
2021-08-12 23:04:00 +02:00
|
|
|
(new_state_ids_compressed, HashSet::new())
|
2021-04-16 18:18:29 +02:00
|
|
|
};
|
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
if !already_existed {
|
|
|
|
self.save_state_from_diff(
|
|
|
|
new_shortstatehash,
|
|
|
|
statediffnew.clone(),
|
2021-08-31 21:20:03 +02:00
|
|
|
statediffremoved,
|
2021-08-12 23:04:00 +02:00
|
|
|
2, // every state change is 2 event changes on average
|
|
|
|
states_parents,
|
|
|
|
)?;
|
|
|
|
};
|
2021-04-16 18:18:29 +02:00
|
|
|
|
2021-08-24 19:10:31 +02:00
|
|
|
for event_id in statediffnew.into_iter().filter_map(|new| {
|
|
|
|
self.parse_compressed_state_event(new)
|
|
|
|
.ok()
|
|
|
|
.map(|(_, id)| id)
|
|
|
|
}) {
|
2021-10-13 10:16:45 +02:00
|
|
|
let pdu = match self.get_pdu_json(&event_id)? {
|
|
|
|
Some(pdu) => pdu,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
if pdu.get("type").and_then(|val| val.as_str()) != Some("m.room.member") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-10-13 11:51:30 +02:00
|
|
|
let pdu: PduEvent = match serde_json::from_str(
|
2021-10-13 10:16:45 +02:00
|
|
|
&serde_json::to_string(&pdu).expect("CanonicalJsonObj can be serialized to JSON"),
|
|
|
|
) {
|
|
|
|
Ok(pdu) => pdu,
|
|
|
|
Err(_) => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct ExtractMembership {
|
|
|
|
membership: MembershipState,
|
2021-04-16 18:18:29 +02:00
|
|
|
}
|
2021-10-13 10:16:45 +02:00
|
|
|
|
|
|
|
let membership = match serde_json::from_str::<ExtractMembership>(pdu.content.get()) {
|
|
|
|
Ok(e) => e.membership,
|
|
|
|
Err(_) => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
let state_key = match pdu.state_key {
|
|
|
|
Some(k) => k,
|
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
|
2021-11-27 00:30:28 +01:00
|
|
|
let user_id = match UserId::parse(state_key) {
|
2021-10-13 10:16:45 +02:00
|
|
|
Ok(id) => id,
|
|
|
|
Err(_) => continue,
|
|
|
|
};
|
|
|
|
|
|
|
|
self.update_membership(room_id, &user_id, membership, &pdu.sender, None, db, false)?;
|
2020-09-13 22:24:36 +02:00
|
|
|
}
|
|
|
|
|
2021-09-13 19:45:56 +02:00
|
|
|
self.update_joined_count(room_id, db)?;
|
2021-08-17 00:22:52 +02:00
|
|
|
|
2021-03-17 22:30:25 +01:00
|
|
|
self.roomid_shortstatehash
|
2021-08-12 23:04:00 +02:00
|
|
|
.insert(room_id.as_bytes(), &new_shortstatehash.to_be_bytes())?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-05-03 17:25:31 +02:00
|
|
|
/// Returns the full room state.
|
2021-02-28 12:41:03 +01:00
|
|
|
#[tracing::instrument(skip(self))]
|
2022-06-18 16:38:41 +02:00
|
|
|
pub async fn room_state_full(
|
2020-12-31 08:40:49 -05:00
|
|
|
&self,
|
|
|
|
room_id: &RoomId,
|
2022-04-06 21:31:29 +02:00
|
|
|
) -> Result<HashMap<(StateEventType, String), Arc<PduEvent>>> {
|
2021-03-17 22:30:25 +01:00
|
|
|
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
2022-06-18 16:38:41 +02:00
|
|
|
self.state_full(current_shortstatehash).await
|
2020-09-12 21:30:07 +02:00
|
|
|
} else {
|
2021-07-18 20:43:39 +02:00
|
|
|
Ok(HashMap::new())
|
2020-05-03 17:25:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-11 21:01:27 +02:00
|
|
|
/// Returns a single PDU from `room_id` with key (`event_type`, `state_key`).
|
|
|
|
#[tracing::instrument(skip(self))]
|
|
|
|
pub fn room_state_get_id(
|
|
|
|
&self,
|
|
|
|
room_id: &RoomId,
|
2022-04-06 21:31:29 +02:00
|
|
|
event_type: &StateEventType,
|
2021-04-11 21:01:27 +02:00
|
|
|
state_key: &str,
|
2021-08-26 17:58:32 -04:00
|
|
|
) -> Result<Option<Arc<EventId>>> {
|
2021-04-11 21:01:27 +02:00
|
|
|
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
|
|
|
self.state_get_id(current_shortstatehash, event_type, state_key)
|
|
|
|
} else {
|
|
|
|
Ok(None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-26 11:15:52 -04:00
|
|
|
/// Returns a single PDU from `room_id` with key (`event_type`, `state_key`).
|
2021-02-28 12:41:03 +01:00
|
|
|
#[tracing::instrument(skip(self))]
|
2020-06-12 13:18:25 +02:00
|
|
|
pub fn room_state_get(
|
|
|
|
&self,
|
|
|
|
room_id: &RoomId,
|
2022-04-06 21:31:29 +02:00
|
|
|
event_type: &StateEventType,
|
2020-06-12 13:18:25 +02:00
|
|
|
state_key: &str,
|
2021-06-30 09:52:01 +02:00
|
|
|
) -> Result<Option<Arc<PduEvent>>> {
|
2021-03-17 22:30:25 +01:00
|
|
|
if let Some(current_shortstatehash) = self.current_shortstatehash(room_id)? {
|
2021-03-24 11:52:10 +01:00
|
|
|
self.state_get(current_shortstatehash, event_type, state_key)
|
2020-09-12 21:30:07 +02:00
|
|
|
} else {
|
|
|
|
Ok(None)
|
|
|
|
}
|
2020-06-12 13:18:25 +02:00
|
|
|
}
|
|
|
|
|
2020-05-03 17:25:31 +02:00
|
|
|
/// Returns the leaf pdus of a room.
|
2021-07-29 08:36:01 +02:00
|
|
|
#[tracing::instrument(skip(self))]
|
2021-11-27 17:44:52 +01:00
|
|
|
pub fn get_pdu_leaves(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>> {
|
2020-08-26 11:15:52 -04:00
|
|
|
let mut prefix = room_id.as_bytes().to_vec();
|
2020-05-03 17:25:31 +02:00
|
|
|
prefix.push(0xff);
|
|
|
|
|
2021-03-25 23:55:40 +01:00
|
|
|
self.roomid_pduleaves
|
2021-06-12 18:40:33 +02:00
|
|
|
.scan_prefix(prefix)
|
|
|
|
.map(|(_, bytes)| {
|
2021-11-27 17:44:52 +01:00
|
|
|
EventId::parse_arc(utils::string_from_bytes(&bytes).map_err(|_| {
|
2021-06-17 20:34:14 +02:00
|
|
|
Error::bad_database("EventID in roomid_pduleaves is invalid unicode.")
|
|
|
|
})?)
|
|
|
|
.map_err(|_| Error::bad_database("EventId in roomid_pduleaves is invalid."))
|
2020-06-09 15:13:17 +02:00
|
|
|
})
|
2021-03-25 23:55:40 +01:00
|
|
|
.collect()
|
2020-05-03 17:25:31 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 19:41:38 -05:00
|
|
|
/// Replace the leaves of a room.
|
|
|
|
///
|
2021-02-03 20:00:01 -05:00
|
|
|
/// The provided `event_ids` become the new leaves, this allows a room to have multiple
|
2021-01-18 19:41:38 -05:00
|
|
|
/// `prev_events`.
|
2021-07-29 08:36:01 +02:00
|
|
|
#[tracing::instrument(skip(self))]
|
2021-11-27 16:35:59 +01:00
|
|
|
pub fn replace_pdu_leaves<'a>(
|
|
|
|
&self,
|
|
|
|
room_id: &RoomId,
|
|
|
|
event_ids: impl IntoIterator<Item = &'a EventId> + Debug,
|
|
|
|
) -> Result<()> {
|
2021-01-18 19:08:59 -05:00
|
|
|
let mut prefix = room_id.as_bytes().to_vec();
|
|
|
|
prefix.push(0xff);
|
|
|
|
|
2021-06-08 18:10:00 +02:00
|
|
|
for (key, _) in self.roomid_pduleaves.scan_prefix(prefix.clone()) {
|
|
|
|
self.roomid_pduleaves.remove(&key)?;
|
2021-01-18 19:08:59 -05:00
|
|
|
}
|
|
|
|
|
2021-04-05 21:46:10 +02:00
|
|
|
for event_id in event_ids {
|
2021-01-18 19:08:59 -05:00
|
|
|
let mut key = prefix.to_owned();
|
|
|
|
key.extend_from_slice(event_id.as_bytes());
|
|
|
|
self.roomid_pduleaves.insert(&key, event_id.as_bytes())?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-06-19 22:56:14 +02:00
|
|
|
/// Generates a new StateHash and associates it with the incoming event.
|
2021-03-25 23:55:40 +01:00
|
|
|
///
|
|
|
|
/// This adds all current state events (not including the incoming event)
|
|
|
|
/// to `stateid_pduid` and adds the incoming event to `eventid_statehash`.
|
2021-08-24 19:10:31 +02:00
|
|
|
#[tracing::instrument(skip(self, state_ids_compressed, globals))]
|
2021-03-25 23:55:40 +01:00
|
|
|
pub fn set_event_state(
|
|
|
|
&self,
|
|
|
|
event_id: &EventId,
|
2021-08-12 23:04:00 +02:00
|
|
|
room_id: &RoomId,
|
2021-08-24 19:10:31 +02:00
|
|
|
state_ids_compressed: HashSet<CompressedStateEvent>,
|
2021-03-25 23:55:40 +01:00
|
|
|
globals: &super::globals::Globals,
|
|
|
|
) -> Result<()> {
|
2021-09-13 19:45:56 +02:00
|
|
|
let shorteventid = self.get_or_create_shorteventid(event_id, globals)?;
|
2021-03-25 23:55:40 +01:00
|
|
|
|
2021-09-13 19:45:56 +02:00
|
|
|
let previous_shortstatehash = self.current_shortstatehash(room_id)?;
|
2021-08-12 23:04:00 +02:00
|
|
|
|
2021-03-25 23:55:40 +01:00
|
|
|
let state_hash = self.calculate_hash(
|
2021-08-24 19:10:31 +02:00
|
|
|
&state_ids_compressed
|
|
|
|
.iter()
|
|
|
|
.map(|s| &s[..])
|
2021-03-25 23:55:40 +01:00
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
);
|
|
|
|
|
2021-08-11 19:15:38 +02:00
|
|
|
let (shortstatehash, already_existed) =
|
|
|
|
self.get_or_create_shortstatehash(&state_hash, globals)?;
|
2021-03-25 23:55:40 +01:00
|
|
|
|
2021-08-11 19:15:38 +02:00
|
|
|
if !already_existed {
|
2021-08-12 23:04:00 +02:00
|
|
|
let states_parents = previous_shortstatehash
|
|
|
|
.map_or_else(|| Ok(Vec::new()), |p| self.load_shortstatehash_info(p))?;
|
|
|
|
|
|
|
|
let (statediffnew, statediffremoved) =
|
|
|
|
if let Some(parent_stateinfo) = states_parents.last() {
|
2021-10-13 11:51:30 +02:00
|
|
|
let statediffnew: HashSet<_> = state_ids_compressed
|
2021-08-12 23:04:00 +02:00
|
|
|
.difference(&parent_stateinfo.1)
|
2021-10-13 10:24:39 +02:00
|
|
|
.copied()
|
2021-10-13 11:51:30 +02:00
|
|
|
.collect();
|
2021-08-12 23:04:00 +02:00
|
|
|
|
2021-10-13 11:51:30 +02:00
|
|
|
let statediffremoved: HashSet<_> = parent_stateinfo
|
2021-08-12 23:04:00 +02:00
|
|
|
.1
|
|
|
|
.difference(&state_ids_compressed)
|
2021-10-13 10:24:39 +02:00
|
|
|
.copied()
|
2021-10-13 11:51:30 +02:00
|
|
|
.collect();
|
2021-08-12 23:04:00 +02:00
|
|
|
|
|
|
|
(statediffnew, statediffremoved)
|
|
|
|
} else {
|
|
|
|
(state_ids_compressed, HashSet::new())
|
|
|
|
};
|
|
|
|
self.save_state_from_diff(
|
|
|
|
shortstatehash,
|
2021-08-31 21:20:03 +02:00
|
|
|
statediffnew,
|
|
|
|
statediffremoved,
|
2021-08-12 23:04:00 +02:00
|
|
|
1_000_000, // high number because no state will be based on this one
|
|
|
|
states_parents,
|
|
|
|
)?;
|
2021-08-11 19:15:38 +02:00
|
|
|
}
|
2021-03-25 23:55:40 +01:00
|
|
|
|
|
|
|
self.shorteventid_shortstatehash
|
2021-08-11 19:15:38 +02:00
|
|
|
.insert(&shorteventid.to_be_bytes(), &shortstatehash.to_be_bytes())?;
|
2021-03-25 23:55:40 +01:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2020-08-19 17:27:24 -04:00
|
|
|
/// Generates a new StateHash and associates it with the incoming event.
|
|
|
|
///
|
|
|
|
/// This adds all current state events (not including the incoming event)
|
2021-03-17 22:30:25 +01:00
|
|
|
/// to `stateid_pduid` and adds the incoming event to `eventid_statehash`.
|
2021-07-29 08:36:01 +02:00
|
|
|
#[tracing::instrument(skip(self, new_pdu, globals))]
|
2020-12-19 16:00:11 +01:00
|
|
|
pub fn append_to_state(
|
|
|
|
&self,
|
|
|
|
new_pdu: &PduEvent,
|
|
|
|
globals: &super::globals::Globals,
|
2021-03-17 22:30:25 +01:00
|
|
|
) -> Result<u64> {
|
2021-08-11 19:15:38 +02:00
|
|
|
let shorteventid = self.get_or_create_shorteventid(&new_pdu.event_id, globals)?;
|
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let previous_shortstatehash = self.current_shortstatehash(&new_pdu.room_id)?;
|
2021-08-11 19:15:38 +02:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
if let Some(p) = previous_shortstatehash {
|
|
|
|
self.shorteventid_shortstatehash
|
|
|
|
.insert(&shorteventid.to_be_bytes(), &p.to_be_bytes())?;
|
|
|
|
}
|
2021-03-17 22:30:25 +01:00
|
|
|
|
2020-09-12 21:30:07 +02:00
|
|
|
if let Some(state_key) = &new_pdu.state_key {
|
2021-08-12 23:04:00 +02:00
|
|
|
let states_parents = previous_shortstatehash
|
|
|
|
.map_or_else(|| Ok(Vec::new()), |p| self.load_shortstatehash_info(p))?;
|
2020-12-19 16:00:11 +01:00
|
|
|
|
2022-04-06 21:31:29 +02:00
|
|
|
let shortstatekey = self.get_or_create_shortstatekey(
|
|
|
|
&new_pdu.kind.to_string().into(),
|
|
|
|
state_key,
|
|
|
|
globals,
|
|
|
|
)?;
|
2020-09-12 21:30:07 +02:00
|
|
|
|
2021-08-16 23:24:52 +02:00
|
|
|
let new = self.compress_state_event(shortstatekey, &new_pdu.event_id, globals)?;
|
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let replaces = states_parents
|
|
|
|
.last()
|
|
|
|
.map(|info| {
|
|
|
|
info.1
|
|
|
|
.iter()
|
|
|
|
.find(|bytes| bytes.starts_with(&shortstatekey.to_be_bytes()))
|
|
|
|
})
|
|
|
|
.unwrap_or_default();
|
2020-08-19 17:27:24 -04:00
|
|
|
|
2021-08-16 23:24:52 +02:00
|
|
|
if Some(&new) == replaces {
|
|
|
|
return Ok(previous_shortstatehash.expect("must exist"));
|
|
|
|
}
|
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
// TODO: statehash with deterministic inputs
|
|
|
|
let shortstatehash = globals.next_count()?;
|
2020-08-19 17:27:24 -04:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
let mut statediffnew = HashSet::new();
|
|
|
|
statediffnew.insert(new);
|
|
|
|
|
|
|
|
let mut statediffremoved = HashSet::new();
|
|
|
|
if let Some(replaces) = replaces {
|
2021-09-13 19:45:56 +02:00
|
|
|
statediffremoved.insert(*replaces);
|
2021-08-12 23:04:00 +02:00
|
|
|
}
|
2021-08-03 16:14:07 +02:00
|
|
|
|
2021-08-12 23:04:00 +02:00
|
|
|
self.save_state_from_diff(
|
|
|
|
shortstatehash,
|
|
|
|
statediffnew,
|
|
|
|
statediffremoved,
|
|
|
|
2,
|
|
|
|
states_parents,
|
|
|
|
)?;
|
2020-08-19 17:27:24 -04:00
|
|
|
|
2021-03-17 22:30:25 +01:00
|
|
|
Ok(shortstatehash)
|
2020-09-12 21:30:07 +02:00
|
|
|
} else {
|
2021-08-12 23:04:00 +02:00
|
|
|
Ok(previous_shortstatehash.expect("first event in room must be a state event"))
|
2020-09-12 21:30:07 +02:00
|
|
|
}
|
2020-08-19 17:27:24 -04:00
|
|
|
}
|
|
|
|
|
2021-07-29 08:36:01 +02:00
|
|
|
#[tracing::instrument(skip(self, invite_event))]
|
2021-04-25 14:10:07 +02:00
|
|
|
pub fn calculate_invite_state(
|
|
|
|
&self,
|
|
|
|
invite_event: &PduEvent,
|
|
|
|
) -> Result<Vec<Raw<AnyStrippedStateEvent>>> {
|
|
|
|
let mut state = Vec::new();
|
|
|
|
// Add recommended events
|
|
|
|
if let Some(e) =
|
2022-04-06 21:31:29 +02:00
|
|
|
self.room_state_get(&invite_event.room_id, &StateEventType::RoomCreate, "")?
|
2021-04-25 14:10:07 +02:00
|
|
|
{
|
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
|
|
|
if let Some(e) =
|
2022-04-06 21:31:29 +02:00
|
|
|
self.room_state_get(&invite_event.room_id, &StateEventType::RoomJoinRules, "")?
|
2021-04-25 14:10:07 +02:00
|
|
|
{
|
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
2022-04-06 21:31:29 +02:00
|
|
|
if let Some(e) = self.room_state_get(
|
|
|
|
&invite_event.room_id,
|
|
|
|
&StateEventType::RoomCanonicalAlias,
|
|
|
|
"",
|
|
|
|
)? {
|
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
|
|
|
if let Some(e) =
|
|
|
|
self.room_state_get(&invite_event.room_id, &StateEventType::RoomAvatar, "")?
|
|
|
|
{
|
2021-04-25 14:10:07 +02:00
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
2022-04-06 21:31:29 +02:00
|
|
|
if let Some(e) =
|
|
|
|
self.room_state_get(&invite_event.room_id, &StateEventType::RoomName, "")?
|
|
|
|
{
|
2021-04-25 14:10:07 +02:00
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
|
|
|
if let Some(e) = self.room_state_get(
|
|
|
|
&invite_event.room_id,
|
2022-04-06 21:31:29 +02:00
|
|
|
&StateEventType::RoomMember,
|
2021-04-25 14:10:07 +02:00
|
|
|
invite_event.sender.as_str(),
|
|
|
|
)? {
|
|
|
|
state.push(e.to_stripped_state_event());
|
|
|
|
}
|
|
|
|
|
|
|
|
state.push(invite_event.to_stripped_state_event());
|
|
|
|
Ok(state)
|
|
|
|
}
|
|
|
|
|
2021-07-29 08:36:01 +02:00
|
|
|
#[tracing::instrument(skip(self))]
|
2021-03-17 22:30:25 +01:00
|
|
|
pub fn set_room_state(&self, room_id: &RoomId, shortstatehash: u64) -> Result<()> {
|
|
|
|
self.roomid_shortstatehash
|
|
|
|
.insert(room_id.as_bytes(), &shortstatehash.to_be_bytes())?;
|
2020-12-31 14:52:08 +01:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|