anchor.diff:  		       [Id, debugfriendly(TState)]),
   	    TState;
   	_ ->
  -	    TState#transactionstate{stateless_response_branches=lists:append(In, [Id])}
  -    end.
  -
  -delete_expired(TStateList) when record(TStateList, transactionstatelist) ->
  -    Now = util:timestamp(),
  -    #transactionstatelist{list=del_time(Now, TStateList#transactionstatelist.list)}.
  -
  -delete_using_pid(TState, TStateList) when record(TStateList, transactionstatelist) ->
  -    #transactionstatelist{list=del_pid(TState, TStateList#transactionstatelist.list)}.
  -
  -
  -
  -del_pid(Pid, []) ->
  -    [];
  -del_pid(Pid, [H | T]) when record(H, transactionstate), H#transactionstate.pid == Pid ->
  -    del_pid(Pid, T);
  -del_pid(Pid, [H | T]) when record(H, transactionstate) ->
  -    [H | del_pid(Pid, T)].
  -
  -del_time(Time, []) ->
  -    [];
  -del_time(Time, [H | T]) when record(H, transactionstate), H#transactionstate.expire =< Time, H#transactionstate.expire > 0 ->
  -    case util:safe_is_process_alive(H#transactionstate.pid) of
  -	{true, Pid} ->
  -	    %% Be nice and tell lingering processes it is time to go
  -	    logger:log(error, "Transaction layer: Had to tell lingering transaction that it is time to terminate :~n~p",
  -		       [debugfriendly(H)]),
  -	    gen_server:cast(Pid, {expired});
  -	_ ->
  -	    true
  -    end,
  -    del_time(Time, T);
  -del_time(Time, [H | T]) when record(H, transactionstate) ->
  -    [H | del_time(Time, T)].
  -
  -
  -
  -update_transactionstate(TState, TStateList) when record(TState, transactionstate), record(TStateList, transactionstatelist) ->
  +	    NewL = lists:append(In, [Id]),
  +	    TState#transactionstate{stateless_response_branches=NewL}
  +    end.
  +
  +%%--------------------------------------------------------------------
  +%% Function: delete_expired()
  +%% Descrip.: Delete entrys from a transactionstatelist record() that
  +%%           has a timestamp older than now. del_time() signals
  +%%           the transaction handlers for transactions it removes.
  +%% Returns : NewTStateList = transactionstatelist record()
  +%%--------------------------------------------------------------------
  +delete_expired() ->
  +%%    Now = util:timestamp(),
  +%%    L = TStateList#transactionstatelist.list,
  +%%    NewL = del_time(Now, L),
  +%%    TStateList#transactionstatelist{list=NewL}.
  +    %% XXX Not implemented
  +    ok.
  +
  +%%--------------------------------------------------------------------
  +%% Function: delete_using_entrylist(Pid, TStateList)
  +%%           EntryList  = list() of transactionstate record()
  +%%           TStateList = transactionstatelist record()
  +%% Descrip.: Delete entrys from a transactionstatelist record() that
  +%%           has a pid matching the supplied Pid.
  +%% Returns : {ok, NumDeleted}
  +%%           NumDeleted = integer(), number of records deleted
  +%%--------------------------------------------------------------------
  +delete_using_entrylist(EntryList) when is_list(EntryList) ->
  +    ok = del_entrys(EntryList),
  +    {ok, length(EntryList)}.
  +
  +%%--------------------------------------------------------------------
  +%% Function: update_transactionstate(TState)
  +%%           TState     = transcationstate record()
  +%% Descrip.: Look in TStateList for an entry matching (using the
  +%%           unique reference) the TState entry, and replace it with
  +%%           the (presumably) updated TState entry.
  +%% Returns : NewTStateList = transactionstatelist record()
  +%%--------------------------------------------------------------------
  +update_transactionstate(TState) when is_record(TState, transactionstate) ->
       Ref = TState#transactionstate.ref,
  -    #transactionstatelist{list=update_transactionstate(Ref, TState, TStateList#transactionstatelist.list, TStateList)}.
  -
  -update_transactionstate(Ref, _, [], TStateList) ->
  -    logger:log(error, "Transaction state list: Asked to update a transactionstate with ref=~p, but I can't find it", [Ref]),
  -    logger:log(debug, "Transaction state list: Asked to update a transactionstate with ref=~p, but I can't find it in list :~n~p",
  -	       [Ref, debugfriendly(TStateList)]),
  -    [];
  -update_transactionstate(Ref, NewT, [H | T], TStateList) when record(H, transactionstate), H#transactionstate.ref == Ref ->
  -    [NewT | T];
  -update_transactionstate(Ref, NewT, [H | T], TStateList) when record(H, transactionstate) ->
  -    lists:append([H], update_transactionstate(Ref, NewT, T, TStateList)).
  -
  -%% Function: get_length/1
  -%% Description: Returns the length of the list record element of a
  -%%              transactionstatelist.
  -%% Returns: Length
  -%%--------------------------------------------------------------------
  -get_length(T) when record(T, transactionstatelist) ->
  -    length(T#transactionstatelist.list).
  -
  -%% Function: debugfriendly/1
  -%% Description: Returns a list, suitable for debug logging (using ~p),
  -%%              describing the contents of a transactionstatelist.
  -%% Returns: Blob
  -%%          []
  -%%--------------------------------------------------------------------
  +    true = ets:insert(transactionstate_ref_to_t, {Ref, TState}),
  +    ok.
  +
  +%%--------------------------------------------------------------------
  +%% Function: get_length()
  +%% Descrip.: Returns the length of the list record element of a
  +%%           transactionstatelist.
  +%% Returns : Length = integer()
  +%%--------------------------------------------------------------------
  +get_length() ->
  +    ets:info(transactionstate_ref_to_t, size).
  +
  +%%--------------------------------------------------------------------
  +%% Function: debugfriendly(TStateList)
  +%%           TStateList = transactionstatelist record()
  +%% Descrip.: Return information about the elements in an
  +%%           transactionstatelist record in a format that is suitable
  +%%           for logging using ~p.
  +%% Returns : Data = term()
  +%%--------------------------------------------------------------------
  +debugfriendly() ->
  +    %% no list supplied, request full dump
  +    L = get_all_entries(),
  +    debugfriendly2(L, []).
  +
   debugfriendly([]) ->
       [];
  -debugfriendly(TStateList) when record(TStateList, transactionstatelist) ->
  +debugfriendly(TStateList) when is_record(TStateList, transactionstatelist) ->
       debugfriendly2(TStateList#transactionstatelist.list, []);
  -debugfriendly(TState) when record(TState, transactionstate) ->
  -    debugfriendly2([TState], []).
  +debugfriendly(TState) when is_record(TState, transactionstate) ->
  +    debugfriendly2([TState], []);
  +debugfriendly([H|_] = TStateList) when is_list(TStateList), is_record(H, transactionstate) ->
  +    debugfriendly2(TStateList, []).
   
   debugfriendly2([], Res) ->
       lists:reverse(Res);
  -debugfriendly2([H | T], Res) when record(H, transactionstate) ->
  -    In = [{id, H#transactionstate.id}, {type, H#transactionstate.type}, {ref, H#transactionstate.ref}],
  -    Out = debugfriendly_non_empty([pid, ack_id, response_to_tag, appdata, branches], H, In),
  +debugfriendly2([H | T], Res) when is_record(H, transactionstate) ->
  +    %% The In elements are in the reverse order of what they will be
  +    %% after debugfriendly_non_empty()
  +    In = [{id, H#transactionstate.id}, {description, H#transactionstate.description},
  +	  {type, H#transactionstate.type}, {ref, H#transactionstate.ref}],
  +    %% These are NOT in reverse order
  +    Out = debugfriendly_non_empty([pid, ack_id, response_to_tag, appdata, branches, result], H, In),
       debugfriendly2(T, [Out | Res]).
   
  -debugfriendly_non_empty([], R, Res) ->
  +debugfriendly_non_empty([], _R, Res) ->
       lists:reverse(Res);
  +%% result, not empty
  +debugfriendly_non_empty([result | T], R, Res)
  +  when R#transactionstate.result /= undefined, R#transactionstate.result /= none ->
  +    debugfriendly_non_empty(T, R, [{result, R#transactionstate.result} | Res]);
   %% pid, not empty
  -debugfriendly_non_empty([pid | T], R, Res) when R#transactionstate.pid /= undefined, R#transactionstate.pid /= none ->
  +debugfriendly_non_empty([pid | T], R, Res)
  +  when R#transactionstate.pid /= undefined, R#transactionstate.pid /= none ->
       debugfriendly_non_empty(T, R, [{pid, R#transactionstate.pid} | Res]);
   %% response_to_tag, not empty
  -debugfriendly_non_empty([response_to_tag | T], R, Res) when R#transactionstate.response_to_tag /= undefined, R#transactionstate.response_to_tag /= none ->
  +debugfriendly_non_empty([response_to_tag | T], R, Res)
  +  when R#transactionstate.response_to_tag /= undefined, R#transactionstate.response_to_tag /= none ->
       debugfriendly_non_empty(T, R, [{response_to_tag, R#transactionstate.response_to_tag} | Res]);
   %% ack_id, not empty
  -debugfriendly_non_empty([ack_id | T], R, Res) when R#transactionstate.ack_id /= undefined, R#transactionstate.ack_id /= none ->
  +debugfriendly_non_empty([ack_id | T], R, Res)
  +  when R#transactionstate.ack_id /= undefined, R#transactionstate.ack_id /= none ->
       debugfriendly_non_empty(T, R, [{ack_id, R#transactionstate.ack_id} | Res]);
   %% appdata, not empty
  -debugfriendly_non_empty([appdata | T], R, Res) when R#transactionstate.appdata /= undefined, R#transactionstate.appdata /= none ->
  +debugfriendly_non_empty([appdata | T], R, Res)
  +  when R#transactionstate.appdata /= undefined, R#transactionstate.appdata /= none ->
       debugfriendly_non_empty(T, R, [{appdata, R#transactionstate.appdata} | Res]);
   %% branches (length), not zero
  -debugfriendly_non_empty([branches | T], R, Res) when length(R#transactionstate.stateless_response_branches) /= 0 ->
  +debugfriendly_non_empty([branches | T], R, Res)
  +  when length(R#transactionstate.stateless_response_branches) /= 0 ->
       debugfriendly_non_empty(T, R, [{stateless_response_branches, length(R#transactionstate.stateless_response_branches)} | Res]);
   %% empty, or unknown record field
   debugfriendly_non_empty([_ | T], R, Res) ->
       debugfriendly_non_empty(T, R, Res).
  +
  +monitor_format([]) ->
  +    [];
  +monitor_format(TStateList) when is_record(TStateList, transactionstatelist) ->
  +    monitor_format2(TStateList#transactionstatelist.list, []).
  +
  +monitor_format2([], Res) ->
  +    lists:reverse(Res);
  +monitor_format2([H|T], Res) when record(H, transactionstate) ->
  +    Str =
  +	case H#transactionstate.result of
  +	    none ->
  +		H#transactionstate.description;
  +	    _ ->
  +		lists:flatten(lists:concat([H#transactionstate.description,
  +					    " (result: ",
  +					    H#transactionstate.result, ")"]))
  +	end,
  +    monitor_format2(T, [Str | Res]).
  +
  +%%====================================================================
  +%% Internal functions
  +%%====================================================================
  +
  +%%--------------------------------------------------------------------
  +%% Function: add(Type, Id, AckId, Pid, Desc, TStateList)
  +%%           Type       = atom(), client | server
  +%%           Id         = term()
  +%%           AckId      = term() | none
  +%%           Pid        = pid() | none
  +%%           Desc       = string(),
  +%% Descrip.: Add a new transaction state entry to TStateList.
  +%% Returns : ok               |
  +%%           error            |
  +%%           {duplicate, Dup}
  +%%           Dup = transactionstate record()
  +%%--------------------------------------------------------------------
  +add(Type, Id, AckId, Pid, Desc) when is_pid(Pid); Pid == none, is_atom(Type),
  +				     Type == client; Type == server ->
  +    Ref = make_ref(),
  +    TId = {Type, Id},
  +    case ets:insert_new(transactionstate_typeid_to_ref, {TId, Ref}) of
  +	true ->
  +	    NewT = #transactionstate{ref=Ref, type=Type, id=Id, ack_id=AckId, pid=Pid,
  +	    			     description=Desc},
  +	    true = ets_insert_new(transactionstate_ref_to_t, {Ref, NewT}),
  +	    case Pid of
  +		none -> true;
  +		_ ->
  +		    true = ets:insert(transactionstate_pid_to_ref, {Pid, Ref})
  +	    end,
  +	    case AckId of
  +		none -> true;
  +		_ -> true = ets_insert_new(transactionstate_ack_to_ref, {AckId, Ref})
  +	    end,
  +	    ok;
  +	false ->
  +	    case get_elem(Type, Id) of
  +		Dup when is_record(Dup, transactionstate) ->
  +		    logger:log(debug, "transactionstatelist: Asked to add transaction (handled by ~p) with duplicate Id ~p, "
  +			       "existing entry :~n~p~nReturning {duplicate, ...}",
  +			       [Pid, Id, debugfriendly(Dup)]),
  +		    {duplicate, Dup};
  +		_ ->
  +		    logger:log(error, "transactionstatelist: Insert failed, but duplicate entry not found!~nId : ~p", [Id]),
  +		    error
  +	    end
  +    end.
  +
  +ets_insert_new(TName, Data) when is_atom(TName), is_tuple(Data) ->
  +    case ets:insert_new(TName, Data) of
  +	true ->
  +	    true;
  +	false ->
  +	    logger:log(error, "Transaction state list: Failed adding entry to ets table '~p'", [TName]),
  +	    logger:log(debig, "Transaction state list: Data that did not get added to ets table '~p' :~n~p",
  +		       [TName, Data]),
  +	    true
  +    end.
  +
  +%% Fetch the transaction state and then remove all references to it from all our ets tables
  +del_entrys([]) ->
  +    ok;
  +del_entrys([H|T]) when is_record(H, transactionstate) ->
  +    Type = H#transactionstate.type,
  +    Id = H#transactionstate.id,
  +    TId = {Type, Id},
  +    true = ets:delete(transactionstate_typeid_to_ref, TId),
  +    case H#transactionstate.ack_id of
  +	none -> true;
  +	AckId -> true = ets:delete(transactionstate_ack_to_ref, AckId)
  +    end,
  +    true = ets:delete(transactionstate_pid_to_ref, H#transactionstate.pid),
  +    true = ets:delete(transactionstate_ref_to_t, H#transactionstate.ref),
  +    del_entrys(T).
  +
  +fetch_using_ref_tuples(In) ->
  +    fetch_using_ref_tuples2(In, []).
  +
  +fetch_using_ref_tuples2([], Res) ->
  +    Res;
  +fetch_using_ref_tuples2([{_, Ref}|T], Res) ->
  +    case ets:lookup(transactionstate_ref_to_t, Ref) of
  +	[{Ref, Entry}] ->
  +	    fetch_using_ref_tuples2(T, [Entry | Res]);
  +	_ ->
  +	    fetch_using_ref_tuples2(T, Res)
  +    end.
  +
  +get_all_entries() ->
  +    F = fun(H, Acc) ->
  +		case H of
  +		    {_Ref, Entry} -> [Entry | Acc];
  +		    _ -> Acc
  +		end
  +	end,
  +    lists:foldl(F, [], ets:tab2list(transactionstate_ref_to_t)).
  
positive.code: -module(transactionstatelist).
  -export([add_client_transaction/4, add_server_transaction/3, 
  	 delete_using_pid/2, delete_expired/1,
  	 empty/0, extract/2, debugfriendly/1, get_client_transaction/3,
  	 get_server_transaction_using_request/2, get_server_transaction_using_response/2,
  	 get_elem_using_pid/2, get_list_using_pid/2,
  	 set_pid/2, set_appdata/2, set_response_to_tag/2,
  	 update_transactionstate/2, append_response_branch/3,
  	 get_server_transaction_using_stateless_response_branch/3,
  	 get_length/1]).
  
  -include("transactionstatelist.hrl").
  -include("siprecords.hrl").
  
  %%-record(transactionstate, {ref, id, ack_id, branch, pid, appdata,
  %%	request, response_to_tag, expire}).
  
  add(Type, Id, AckId, Pid, TStateList) when record(TStateList, transactionstatelist), pid(Pid) ->
      case get_elem(Type, Id, TStateList) of
  	none ->
  	    NewT = #transactionstate{ref=make_ref(), type=Type, id=Id, ack_id=AckId, pid=Pid,
  	    			     stateless_response_branches=[]},
  	    #transactionstatelist{list=lists:append(TStateList#transactionstatelist.list, [NewT])};
  	_ ->
  	    logger:log(error, "transactionstatelist: Asked to add transaction with duplicate Id ~p to list :~n~p",
  	    	       [Id, debugfriendly(TStateList)]),
  	    TStateList
      end.
  
  
  add_client_transaction(Method, Branch, Pid, TStateList) when record(TStateList, transactionstatelist), pid(Pid) ->
      Id = {Branch, Method},
      add(client, Id, none, Pid, TStateList).
  
  add_server_transaction(Request, Pid, TStateList) when record(Request, request), record(TStateList, transactionstatelist), pid(Pid) ->
      case sipheader:get_server_transaction_id(Request) of
  	error ->
  	    logger:log(error, "transactionstatelist: Could not get server transaction id for request"),
  	    TStateList;
  	Id ->
  	    AckId = case Request#request.method of
  		        "INVITE" ->
  
negative.code: 			_ ->
  			    none
  		    end,
  	    add(server, Id, AckId, Pid, Desc)
      end.
  
  %%--------------------------------------------------------------------
  %% Function: empty()
  %% Descrip.: Get an empty transactionstatelist.
  %% Returns : TStateList = transactionstatelist record()
  %%--------------------------------------------------------------------
  empty() ->
      Ref2t = ets:new(transactionstate_ref_to_t, [protected, set, named_table]),
      Pid2ref = ets:new(transactionstate_pid_to_ref, [protected, bag, named_table]),
      Ack2ref = ets:new(transactionstate_ack_to_ref, [protected, set, named_table]),
      TypeId2ref = ets:new(transactionstate_typeid_to_ref, [protected, set, named_table]),
      Tables = #tables{ref_to_t=Ref2t, pid_to_ref=Pid2ref, ack_to_ref=Ack2ref, typeid_to_ref=TypeId2ref},
      #transactionstatelist{tables=Tables}.
  
  
  %%--------------------------------------------------------------------
  %% Function: get_server_transaction_using_request(Request)
  %%           Request    = request record()
  %% Descrip.: Given a (newly received) request (resend or ACK), try to
  %%           locate an already existing server transaction handler.
  %% Returns : Entry |
  %%           error |
  %%           none
  %%           Entry = transactionstate record()
  %%--------------------------------------------------------------------
  get_server_transaction_using_request(Request) when is_record(Request, request) ->
      case sipheader:get_server_transaction_id(Request) of
  	is_2543_ack ->
  	    get_server_transaction_ack_2543(Request);
  	error ->
  	    logger:log(error, "Transaction state list: Could not get server transaction for request"),
  	    error;
  	Id ->
  	    case get_elem(server, Id) of
  		none when Request#request.method == "ACK" ->
  		    %% If the UAC is 2543 compliant, but there is a 3261 compliant proxy between UAC and us,
  		    %% the 3261 proxy will possibly generate another branch for the ACK than the INVITE
  