diff --git a/src/Room.c b/src/Room.c index fc21f9b..b6bcfa2 100644 --- a/src/Room.c +++ b/src/Room.c @@ -437,26 +437,69 @@ RoomStateGet(Room * room) /* TODO: Consider caching the deserialised result, as doing that on a * large state would probably eat up a lot of time! */ + + /* TODO: Update the cached state */ database_state = DbJson(room->state_ref); return StateDeserialise(database_state); } HashMap * -RoomStateGetID(Room * room, char *event_id) +RoomStateGetID(Room * room, char *event_id, HashMap *e) { HashMap *event, *state; - if (!room || !event_id) + if (!room) { return NULL; } - - event = RoomEventFetch(room, event_id); - if (!event) + if (!e && !event_id) { return NULL; } + if (!event_id) + { + event_id = JsonValueAsString(HashMapGet(e, "event_id")); + } + + if (DbExists(room->db, 4, "rooms", room->id, "state", event_id)) + { + DbRef *ref = DbLock(room->db, 4, + "rooms", room->id, "state", event_id + ); + state = StateDeserialise(DbJson(ref)); + DbUnlock(room->db, ref); + if (state) + { + return state; + } + + /* If a DB error stops us from getting an existing state, + * recompute it. */ + } + + event = e; + if (!event) + { + event = RoomEventFetch(room, event_id); + if (!event) + { + return NULL; + } + } state = StateResolve(room, event); - JsonFree(event); + if (state) + { + HashMap *json = StateSerialise(state); + char *id = room->id; + DbRef *ref = DbCreate(room->db, 4, "rooms", id, "state", event_id); + DbJsonSet(ref, json); + JsonFree(json); + DbUnlock(room->db, ref); + + } + if (!e) + { + JsonFree(event); + } return state; } @@ -1555,8 +1598,7 @@ RoomEventSendV1(Room * room, HashMap * event) client_event = !PopulateEventV1(room, event, &pdu, RoomGetCreator(room)); pdu_object = PduV1ToJson(&pdu); - state = StateResolve(room, pdu_object); /* Compute the state - * at that point for later. */ + state = RoomStateGetID(room, NULL, pdu_object); if (client_event) { char *ev_id; diff --git a/src/State.c b/src/State.c index c16dfe2..7ec2701 100644 --- a/src/State.c +++ b/src/State.c @@ -408,3 +408,23 @@ StateDeserialise(HashMap *json_state) return raw_state; } +HashMap * +StateSerialise(HashMap *rawState) +{ + HashMap *returned; + char *type, *key, *event; + if (!rawState) + { + return NULL; + } + + returned = HashMapCreate(); + while (StateIterate(rawState, &type, &key, (void **) &event)) + { + JsonSet(returned, JsonValueString(event), 2, type, key); + Free(type); + Free(key); + } + + return returned; +} diff --git a/src/include/Room.h b/src/include/Room.h index 0544020..7c546af 100644 --- a/src/include/Room.h +++ b/src/include/Room.h @@ -102,10 +102,11 @@ extern int RoomVersionGet(Room *); extern HashMap * RoomStateGet(Room *); /** * Resolves the room's state before a specific point, + * (with the event hashmap taking priority), * like * .Fn RoomStateGet . */ -extern HashMap * RoomStateGetID(Room *, char *); +extern HashMap * RoomStateGetID(Room *, char *, HashMap *); /** * Get a list of the most recent events in the