anchor.diff:  %%           time we have been idle for 2 seconds
   %% Returns : {noreply, NewState, ?TIMEOUT}
   %%--------------------------------------------------------------------
  +handle_info(timeout, #state{handle = none} = State) ->
  +    %% short-circuit the reconnection-on-timeout when no LDAP server has been configured
  +    {noreply, State};
   handle_info(timeout, State) ->
       Server = State#state.server,
       case should_reopen_connection(State) of
   	true ->
   	    case catch ldap_connect(Server) of
  -		H when is_record(H, ldaphandle) ->
  +		NewHandle when is_record(NewHandle, ldaphandle) ->
   		    logger:log(debug, "LDAP client: Opened new connection to server ~s, closing old", [Server]),
   		    ldap_close(State#state.handle),
  -		    {noreply, State#state{handle=H, querycount=0}, ?TIMEOUT};
  +		    NewState =
  +			State#state{handle     = NewHandle,
  +				    querycount = 0,
  +				    timeout    = ?TIMEOUT
  +				   },
  +		    {noreply, NewState, ?TIMEOUT};
   		E ->
  -		    logger:log(error, "LDAP client: Could not reconnect to LDAP server ~p : ~p", [Server, E]),
  +		    OldTimeout = State#state.timeout,
  +		    NewTimeout = lists:min([?TIMEOUT_MAX, OldTimeout * 2]),	%% exponential backoff
  +		    logger:log(error, "LDAP client: Could not reconnect to LDAP server ~p : ~p",
  +			       [Server, E]),
   		    %% Keep using old handle in hope that it is still working.
  -		    {noreply, State, ?TIMEOUT}
  +		    NewState = State#state{timeout = NewTimeout},
  +		    {noreply, NewState, NewTimeout}
   	    end;
  -	_ ->
  +	false ->
   	    {noreply, State, ?TIMEOUT}
       end.
   
  
positive.code: handle_call({search, Server, Type, In, Attributes}, _From, State) ->
      case State#state.server of
  	Server ->
  	    {NewHandle, Res} = ldapsearch_wrapper(full, [Type, In, Attributes], State),
  	    NewQC = State#state.querycount + 1,
  	    NewState = State#state{handle=NewHandle, querycount=NewQC},
  	    {reply, {ok, Res}, NewState, ?TIMEOUT};
  	_ ->
  	    {reply, {error, "Different LDAP server"}, State, ?TIMEOUT}
      end.
  
negative.code: %% Descrip.: Perform an LDAP search (using exec_ldapsearch()) and, if
  %%           the search results in 'error', close the connection, try
  %%           to open a new one and repeat the search.
  %% Returns : {ok, NewState, Res}
  %%           NewHandle = ldaphandle record()
  %%           Res       = {ok, SearchRes} |
  %%                       {error, Reason}
  %%--------------------------------------------------------------------
  ldapsearch_wrapper(Mode, Args, State) when Mode == simple orelse Mode == full, is_record(State, state) ->
      case ensure_connected(State) of
  	{ok, NewState1} ->
  	    case exec_ldapsearch(Mode, NewState1#state.handle, Args) of
  		error ->
  		    ldap_close(NewState1#state.handle),
  		    NewState2 = NewState1#state{handle = not_connected},
  		    ldapsearch_wrapper_retry(Mode, Args, NewState2);
  		Res ->
  		    QC = NewState1#state.querycount,
  		    NewState = NewState1#state{querycount = QC + 1},
  		    {ok, NewState, {ok, Res}}
  	    end;
  	{error, Reason} ->
  	    {ok, State, {error, Reason}}
      end.
  
  %% part of ldapsearch_wrapper/3, retry a failed query once
  %% Returns : same as ldapsearch_wrapper/3
  ldapsearch_wrapper_retry(Mode, Args, State) ->
      case ensure_connected(State) of
  	{ok, NewState1} ->
  	    logger:log(debug, "LDAP client: Retrying query using new LDAP handle ~p",
  		       [NewState1#state.handle]),
  	    Res = exec_ldapsearch(Mode, NewState1#state.handle, Args),
  	    NewState = NewState1#state{querycount = 1},
  	    case Res of
  		error ->
  		    %% if the same query fails twice, it might be a problem with the
  		    %% query and not the server
  		    {ok, NewState, {error, "query failed"}};
  		_ ->
  		    {ok, NewState, {ok, Res}}
  	    end;
  	{error, Reason} ->
  	    {ok, State, {error, Reason}}
      end.
  
  %% part of ldapsearch_wrapper/3
  %% Returns : {ok, NewState} | {error, Reason}
  ensure_connected(State) when is_record(State, state) ->
      case State#state.handle of
  	H when is_record(H, ldaphandle) ->
  	    {ok, State};
  	none ->
  	    {error, "LDAP client disabled"};
  	not_connected ->
  	    case catch ldap_connect(State#state.server) of
  		NewHandle when is_record(NewHandle, ldaphandle) ->
  		    NewState =
  			State#state{handle     = NewHandle,
  				    querycount = 0
  				   },
  		    {ok, NewState};
  		{error, "eldap:open failed"} ->
  		    {error, "server unavailable"};
  		Unknown ->
  		    logger:log(debug, "LDAP client: Could not connect to LDAP server ~p, ldap_connect() returned ~p",
  			       [State#state.server, Unknown]),
  		    {error, "server unavailable"}
  	    end
      end.
  
  %%--------------------------------------------------------------------
  