anchor.diff:          dir = Dir,
           since = Since
       } = Args1,
  -    {FilterFun, FilterArgs} = make_filter_fun(FilterName, Style, Req, Db0),
  -    Args = Args1#changes_args{filter_fun = FilterFun, filter_args = FilterArgs},
  +    Filter = configure_filter(FilterName, Style, Req, Db0),
  +    Args = Args1#changes_args{filter_fun = Filter},
       Start = fun() ->
           {ok, Db} = couch_db:reopen(Db0),
           StartSeq = case Dir of
  
positive.code:     get_changes_timeout/2,
      wait_db_updated/3,
      get_rest_db_updated/1,
      make_filter_fun/4,
      main_only_filter/1,
      all_docs_filter/1
  ]).
  
  % For the builtin filter _docs_ids, this is the maximum number
  % of documents for which we trigger the optimized code path.
  
negative.code: 
  send_changes(Args, Acc0, FirstRound) ->
      #changes_args{
          dir = Dir
      } = Args,
      #changes_acc{
          db = Db,
          seq = StartSeq,
          filter = Filter
      } = Acc0,
      EnumFun = fun ?MODULE:changes_enumerator/2,
      case can_optimize(FirstRound, Filter) of
          {true, Fun} ->
              Fun(Db, StartSeq, Dir, EnumFun, Acc0, Filter);
          _ ->
              couch_db:changes_since(Db, StartSeq, EnumFun, [{dir, Dir}], Acc0)
      end.
  
  
  can_optimize(true, {doc_ids, _Style, DocIds})
          when length(DocIds) =< ?MAX_DOC_IDS ->
      {true, fun send_changes_doc_ids/6};
  can_optimize(true, {design_docs, _Style}) ->
      {true, fun send_changes_design_docs/6};
  can_optimize(_, _) ->
      false.
  
  
  send_changes_doc_ids(Db, StartSeq, Dir, Fun, Acc0, {doc_ids, _Style, DocIds}) ->
      Lookups = couch_btree:lookup(Db#db.id_tree, DocIds),
      FullInfos = lists:foldl(fun
          ({ok, FDI}, Acc) -> [FDI | Acc];
          (not_found, Acc) -> Acc
      end, [], Lookups),
      send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
  
  
  send_changes_design_docs(Db, StartSeq, Dir, Fun, Acc0, {design_docs, _Style}) ->
      FoldFun = fun(FullDocInfo, _, Acc) ->
          {ok, [FullDocInfo | Acc]}
      end,
      KeyOpts = [{start_key, <<"_design/">>}, {end_key_gt, <<"_design0">>}],
      {ok, _, FullInfos} = couch_btree:fold(Db#db.id_tree, FoldFun, [], KeyOpts),
      send_lookup_changes(FullInfos, StartSeq, Dir, Db, Fun, Acc0).
  
  
  send_lookup_changes(FullDocInfos, StartSeq, Dir, Db, Fun, Acc0) ->
      FoldFun = case Dir of
          fwd -> fun lists:foldl/3;
          rev -> fun lists:foldr/3
      end,
      GreaterFun = case Dir of
          fwd -> fun(A, B) -> A > B end;
          rev -> fun(A, B) -> A =< B end
      end,
      DocInfos = lists:foldl(fun(FDI, Acc) ->
          DI = couch_doc:to_doc_info(FDI),
          case GreaterFun(DI#doc_info.high_seq, StartSeq) of
              true -> [DI | Acc];
              false -> Acc
          end
      end, [], FullDocInfos),
      SortedDocInfos = lists:keysort(#doc_info.high_seq, DocInfos),
      FinalAcc = try
          FoldFun(fun(DocInfo, Acc) ->
              case Fun(DocInfo, Acc) of
                  {ok, NewAcc} ->
                      NewAcc;
                  {stop, NewAcc} ->
                      throw({stop, NewAcc})
              end
          end, Acc0, SortedDocInfos)
      catch
          {stop, Acc} -> Acc
      end,
      case Dir of
          fwd -> {ok, FinalAcc#changes_acc{seq = couch_db:get_update_seq(Db)}};
          rev -> {ok, FinalAcc}
      end.
  
  
  