anchor.diff:      prompt_fun,
       set_timeout_fun,
       stop_fun
  +}).
  +
  +-record(qserver, {
  +    langs, % Keyed by language name, value is {Mod,Func,Arg}
  +    pid_procs, % Keyed by PID, valus is a #proc record.
  +    lang_procs, % Keyed by language name, value is a #proc record
  +    lang_limits, % Keyed by language name, value is {Lang, Limit, Current}
  +    waitlist = [],
  +    config
   }).
   
   start_link() ->
  
positive.code:             supervisor:terminate_child(couch_secondary_services, query_servers),
              [supervisor:restart_child(couch_secondary_services, query_servers)]
          end),
  
      Langs = ets:new(couch_query_server_langs, [set, private]),
      PidProcs = ets:new(couch_query_server_pid_langs, [set, private]),
      LangProcs = ets:new(couch_query_server_procs, [set, private]),
      % 'query_servers' specifies an OS command-line to execute.
      lists:foreach(fun({Lang, Command}) ->
          true = ets:insert(Langs, {?l2b(Lang),
                            couch_os_process, start_link, [Command]})
      end, couch_config:get("query_servers")),
      % 'native_query_servers' specifies a {Module, Func, Arg} tuple.
      lists:foreach(fun({Lang, SpecStr}) ->
          {ok, {Mod, Fun, SpecArg}} = couch_util:parse_term(SpecStr),
          true = ets:insert(Langs, {?l2b(Lang),
                            Mod, Fun, SpecArg})
      end, couch_config:get("native_query_servers")),
      process_flag(trap_exit, true),
      {ok, {Langs, % Keyed by language name, value is {Mod,Func,Arg}
            PidProcs, % Keyed by PID, valus is a #proc record.
            LangProcs % Keyed by language name, value is a #proc record
            }}.
  
  terminate(_Reason, {_Langs, PidProcs, _LangProcs}) ->
      [couch_util:shutdown_sync(P) || {P,_} <- ets:tab2list(PidProcs)],
      ok.
  
  handle_call({get_proc, #doc{body={Props}}=DDoc, DDocKey}, _From, {Langs, PidProcs, LangProcs}=Server) ->
      % Note to future self. Add max process limit.
      Lang = couch_util:get_value(<<"language">>, Props, <<"javascript">>),
      case ets:lookup(LangProcs, Lang) of
      [{Lang, [P|Rest]}] ->
          % find a proc in the set that has the DDoc
          {ok, Proc} = proc_with_ddoc(DDoc, DDocKey, [P|Rest]),
          rem_from_list(LangProcs, Lang, Proc),
          {reply, {ok, Proc, get_query_server_config()}, Server};
      _ ->
          case (catch new_process(Langs, Lang)) of
          {ok, Proc} ->
              add_value(PidProcs, Proc#proc.pid, Proc),
              {ok, Proc2} = proc_with_ddoc(DDoc, DDocKey, [Proc]),
              {reply, {ok, Proc2, get_query_server_config()}, Server};
          Error ->
              {reply, Error, Server}
          end
      end;
  handle_call({get_proc, Lang}, _From, {Langs, PidProcs, LangProcs}=Server) ->
      % Note to future self. Add max process limit.
      case ets:lookup(LangProcs, Lang) of
      [{Lang, [Proc|_]}] ->
          rem_from_list(LangProcs, Lang, Proc),
          {reply, {ok, Proc, get_query_server_config()}, Server};
      _ ->
          case (catch new_process(Langs, Lang)) of
          {ok, Proc} ->
              add_value(PidProcs, Proc#proc.pid, Proc),
              {reply, {ok, Proc, get_query_server_config()}, Server};
          Error ->
              {reply, Error, Server}
          end
      end;
  handle_call({unlink_proc, Pid}, _From, {_, PidProcs, _}=Server) ->
      rem_value(PidProcs, Pid),
      unlink(Pid),
      {reply, ok, Server};
  handle_call({ret_proc, Proc}, _From, {_, PidProcs, LangProcs}=Server) ->
      % Along with max process limit, here we should check
      % if we're over the limit and discard when we are.
      add_value(PidProcs, Proc#proc.pid, Proc),
      add_to_list(LangProcs, Proc#proc.lang, Proc),
      link(Proc#proc.pid),
      {reply, true, Server}.
  
  handle_cast(_Whatever, Server) ->
      {noreply, Server}.
  
  handle_info({'EXIT', Pid, Status}, {_, PidProcs, LangProcs}=Server) ->
      case ets:lookup(PidProcs, Pid) of
      [{Pid, Proc}] ->
          case Status of
  
negative.code: get_ddoc_process(#doc{} = DDoc, DDocKey) ->
      % remove this case statement
      case gen_server:call(couch_query_servers, {get_proc, DDoc, DDocKey}) of
      {ok, Proc, {QueryConfig}} ->
          % process knows the ddoc
          case (catch proc_prompt(Proc, [<<"reset">>, {QueryConfig}])) of
          true ->
              proc_set_timeout(Proc, couch_util:get_value(<<"timeout">>, QueryConfig)),
              link(Proc#proc.pid),
              gen_server:call(couch_query_servers, {unlink_proc, Proc#proc.pid}),
              Proc;
  