'Deletes old room state'

def _delete_old_state_txn(self, txn, room_id, topological_ordering):

    txn.execute('SELECT    e.event_id,    e.depth    FROM    events    as    e    INNER    JOIN    event_forward_extremities    as    f    ON    e.event_id    =    f.event_id    AND    e.room_id    =    f.room_id    WHERE    f.room_id    =    ?', (room_id,))
    rows = txn.fetchall()
    max_depth = max((row[0] for row in rows))
    if (max_depth <= topological_ordering):
        raise SynapseError(400, 'topological_ordering    is    greater    than    forward    extremeties')
    logger.debug('[purge]    looking    for    events    to    delete')
    txn.execute('SELECT    event_id,    state_key    FROM    events    LEFT    JOIN    state_events    USING    (room_id,    event_id)    WHERE    room_id    =    ?    AND    topological_ordering    <    ?', (room_id, topological_ordering))
    event_rows = txn.fetchall()
    to_delete = [(event_id,) for (event_id, state_key) in event_rows if ((state_key is None) and (not self.hs.is_mine_id(event_id)))]
    logger.info('[purge]    found    %i    events    before    cutoff,    of    which    %i    are    remote    non-state    events    to    delete', len(event_rows), len(to_delete))
    for (event_id, state_key) in event_rows:
        txn.call_after(self._get_state_group_for_event.invalidate, (event_id,))
    logger.debug('[purge]    Finding    new    backward    extremities')
    txn.execute('SELECT    DISTINCT    e.event_id    FROM    events    as    e    INNER    JOIN    event_edges    as    ed    ON    e.event_id    =    ed.prev_event_id    INNER    JOIN    events    as    e2    ON    e2.event_id    =    ed.event_id    WHERE    e.room_id    =    ?    AND    e.topological_ordering    <    ?    AND    e2.topological_ordering    >=    ?', (room_id, topological_ordering, topological_ordering))
    new_backwards_extrems = txn.fetchall()
    logger.debug('[purge]    replacing    backward    extremities:    %r', new_backwards_extrems)
    txn.execute('DELETE    FROM    event_backward_extremities    WHERE    room_id    =    ?', (room_id,))
    txn.executemany('INSERT    INTO    event_backward_extremities    (room_id,    event_id)    VALUES    (?,    ?)', [(room_id, event_id) for (event_id,) in new_backwards_extrems])
    logger.debug('[purge]    finding    redundant    state    groups')
    txn.execute('SELECT    state_group    FROM    event_to_state_groups    INNER    JOIN    events    USING    (event_id)    WHERE    state_group    IN    (            SELECT    DISTINCT    state_group    FROM    events            INNER    JOIN    event_to_state_groups    USING    (event_id)            WHERE    room_id    =    ?    AND    topological_ordering    <    ?    )    GROUP    BY    state_group    HAVING    MAX(topological_ordering)    <    ?', (room_id, topological_ordering, topological_ordering))
    state_rows = txn.fetchall()
    logger.debug('[purge]    found    %i    redundant    state    groups', len(state_rows))
    state_groups_to_delete = set([sg for (sg,) in state_rows])
    logger.debug('[purge]    finding    state    groups    which    depend    on    redundant    state    groups')
    remaining_state_groups = []
    for i in xrange(0, len(state_rows), 100):
        chunk = [sg for (sg,) in state_rows[i:(i + 100)]]
        rows = self._simple_select_many_txn(txn, table='state_group_edges', column='prev_state_group', iterable=chunk, retcols=['state_group'], keyvalues={})
        remaining_state_groups.extend((row['state_group'] for row in rows if (row['state_group'] not in state_groups_to_delete)))
    for sg in remaining_state_groups:
        logger.debug('[purge]    de-delta-ing    remaining    state    group    %s', sg)
        curr_state = self._get_state_groups_from_groups_txn(txn, [sg], types=None)
        curr_state = curr_state[sg]
        self._simple_delete_txn(txn, table='state_groups_state', keyvalues={'state_group': sg})
        self._simple_delete_txn(txn, table='state_group_edges', keyvalues={'state_group': sg})
        self._simple_insert_many_txn(txn, table='state_groups_state', values=[{'state_group': sg, 'room_id': room_id, 'type': key[0], 'state_key': key[1], 'event_id': state_id} for (key, state_id) in curr_state.iteritems()])
    logger.debug('[purge]    removing    redundant    state    groups')
    txn.executemany('DELETE    FROM    state_groups_state    WHERE    state_group    =    ?', state_rows)
    txn.executemany('DELETE    FROM    state_groups    WHERE    id    =    ?', state_rows)
    logger.debug('[purge]    removing    events    from    event_to_state_groups')
    txn.executemany('DELETE    FROM    event_to_state_groups    WHERE    event_id    =    ?', [(event_id,) for (event_id, _) in event_rows])
    logger.debug('[purge]    updating    room_depth')
    txn.execute('UPDATE    room_depth    SET    min_depth    =    ?    WHERE    room_id    =    ?', (topological_ordering, room_id))
    for table in ('events', 'event_json', 'event_auth', 'event_content_hashes', 'event_destinations', 'event_edge_hashes', 'event_edges', 'event_forward_extremities', 'event_push_actions', 'event_reference_hashes', 'event_search', 'event_signatures', 'rejections'):
        logger.debug('[purge]    removing    remote    non-state    events    from    %s', table)
        txn.executemany(('DELETE    FROM    %s    WHERE    event_id    =    ?' % (table,)), to_delete)
    logger.debug('[purge]    marking    remaining    events    as    outliers')
    txn.executemany('UPDATE    events    SET    outlier    =    ?    WHERE    event_id    =    ?', [(True, event_id) for (event_id, state_key) in event_rows if ((state_key is not None) or self.hs.is_mine_id(event_id))])
    logger.info('[purge]    done')
