'Trigger a backfill request to `dest` for the given `room_id`
This will attempt to get more events from the remote. This may return
be successfull and still return no events if the other side has no new
events to offer.'

@log_function
@defer.inlineCallbacks
def backfill(self, dest, room_id, limit, extremities):

    if (dest == self.server_name):
        raise SynapseError(400, "Can't    backfill    from    self.")
    events = (yield self.replication_layer.backfill(dest, room_id, limit=limit, extremities=extremities))
    seen_events = (yield self.store.have_events_in_timeline(set((e.event_id for e in events))))
    events = [e for e in events if (e.event_id not in seen_events)]
    if (not events):
        defer.returnValue([])
    event_map = {e.event_id: e for e in events}
    event_ids = set((e.event_id for e in events))
    edges = [ev.event_id for ev in events if (set((e_id for (e_id, _) in ev.prev_events)) - event_ids)]
    logger.info('backfill:    Got    %d    events    with    %d    edges', len(events), len(edges))
    auth_events = {}
    state_events = {}
    events_to_state = {}
    for e_id in edges:
        (state, auth) = (yield self.replication_layer.get_state_for_room(destination=dest, room_id=room_id, event_id=e_id))
        auth_events.update({a.event_id: a for a in auth})
        auth_events.update({s.event_id: s for s in state})
        state_events.update({s.event_id: s for s in state})
        events_to_state[e_id] = state
    required_auth = set((a_id for event in ((events + state_events.values()) + auth_events.values()) for (a_id, _) in event.auth_events))
    auth_events.update({e_id: event_map[e_id] for e_id in required_auth if (e_id in event_map)})
    missing_auth = (required_auth - set(auth_events))
    failed_to_fetch = set()
    while (missing_auth - failed_to_fetch):
        logger.info('Missing    auth    for    backfill:    %r', missing_auth)
        ret_events = (yield self.store.get_events((missing_auth - failed_to_fetch)))
        auth_events.update(ret_events)
        required_auth.update((a_id for event in ret_events.values() for (a_id, _) in event.auth_events))
        missing_auth = (required_auth - set(auth_events))
        if (missing_auth - failed_to_fetch):
            logger.info('Fetching    missing    auth    for    backfill:    %r', (missing_auth - failed_to_fetch))
            results = (yield preserve_context_over_deferred(defer.gatherResults([preserve_fn(self.replication_layer.get_pdu)([dest], event_id, outlier=True, timeout=10000) for event_id in (missing_auth - failed_to_fetch)], consumeErrors=True)).addErrback(unwrapFirstError))
            auth_events.update({a.event_id: a for a in results if a})
            required_auth.update((a_id for event in results if event for (a_id, _) in event.auth_events))
            missing_auth = (required_auth - set(auth_events))
            failed_to_fetch = (missing_auth - set(auth_events))
    seen_events = (yield self.store.have_events((set(auth_events.keys()) | set(state_events.keys()))))
    ev_infos = []
    for a in auth_events.values():
        if (a.event_id in seen_events):
            continue
        a.internal_metadata.outlier = True
        ev_infos.append({'event': a, 'auth_events': {(auth_events[a_id].type, auth_events[a_id].state_key): auth_events[a_id] for (a_id, _) in a.auth_events if (a_id in auth_events)}})
    for e_id in events_to_state:
        ev_infos.append({'event': event_map[e_id], 'state': events_to_state[e_id], 'auth_events': {(auth_events[a_id].type, auth_events[a_id].state_key): auth_events[a_id] for (a_id, _) in event_map[e_id].auth_events if (a_id in auth_events)}})
    (yield self._handle_new_events(dest, ev_infos, backfilled=True))
    events.sort(key=(lambda e: e.depth))
    for event in events:
        if (event in events_to_state):
            continue
        (yield self._handle_new_event(dest, event, backfilled=True))
    defer.returnValue(events)
