anchor.diff:  			remove_session(SessionAttributes, T, [H | T])
   	end;
   remove_session(SessionAttributes, [], Acc) ->
  +erlang:display({?MODULE, ?LINE, SessionAttributes, lists:reverse(Acc)}),
   	lists:reverse(Acc).
   
  --spec update_session(SessionAttributes, SessionList) ->NewSessionList
  +-spec add_session(SessionAttributes, SessionList) -> SessionList
   	when
   		SessionAttributes :: [tuple()],
  -		SessionList :: [tuple()],
  -		NewSessionList :: [tuple()].
  +		SessionList :: [{pos_integer(), [tuple()]}].
   %% @doc Add new session identification attributes set to active sessions list.
   %% @private
  -update_session(SessionAttributes, SessionList) ->
  -	update_session(SessionAttributes, SessionList, []).
  -%% @hidden
  -update_session(SessionAttributes, [], Acc) ->
  -	Now = erlang:system_time(?MILLISECOND),
  -	[{Now, SessionAttributes} | Acc];
  -update_session(SessionAttributes, [{_, Attributes} = H | T] = S, Acc) ->
  -	case update_session1(SessionAttributes, Attributes) of
  -		true ->
  -			S ++ Acc;
  -		false ->
  -			update_session(SessionAttributes, T, [H | Acc])
  +add_session(SessionAttributes, SessionList) ->
  +	[{erlang:system_time(?MILLISECOND), SessionAttributes} | SessionList].
  +
  +-spec get_session_id(SessionAttributes) -> SessionId
  +	when
  +		SessionAttributes :: [tuple()],
  +		SessionId :: [tuple()].
  +%% @doc Get the session identifier value.
  +%% 	Returns a list of DIAMETER/RADIUS attributes.
  +%% @private
  +get_session_id(SessionAttributes) ->
  +	case lists:keyfind('Session-Id', 1, SessionAttributes) of
  +		false ->
  +			get_session_id1(SessionAttributes, []);
  +		SessionId ->
  +			[SessionId]
   	end.
   %% @hidden
  -update_session1([], _Attributes) ->
  -	false;
  -update_session1([Identifier | T], Attributes) ->
  -	case lists:member(Identifier, Attributes) of
  -		true ->
  +get_session_id1([], Acc) ->
  +	lists:keysort(1, Acc);
  +get_session_id1(_, Acc) when length(Acc) =:= 3 ->
  +	lists:keysort(1, Acc);
  +get_session_id1([{?AcctSessionId, _} = AcctSessionId | T], Acc) ->
  +	get_session_id1(T, [AcctSessionId | Acc]);
  +get_session_id1([{?NasIdentifier, _} = NasIdentifier | T], Acc) ->
  +	get_session_id1(T, [NasIdentifier | Acc]);
  +get_session_id1([{?NasIpAddress, _} = NasIpAddress | T], Acc) ->
  +	get_session_id1(T, [NasIpAddress | Acc]);
  +get_session_id1([_ | T], Acc) ->
  +	get_session_id1(T, Acc).
  +
  +-spec sort(Buckets) -> Buckets
  +	when
  +		Buckets :: [#bucket{}].
  +%% @doc Sort `Buckets' oldest first.
  +%% @private
  +sort(Buckets) ->
  +	F = fun(#bucket{termination_date = T1},
  +				#bucket{termination_date = T2}) when T1 =< T2 ->
   			true;
  -		false ->
  -			update_session1(T, Attributes)
  +		(_, _)->
  +			false
  +	end,
  +	lists:sort(F, Buckets).
  +
  +-spec price_units(Amount, UnitSize, UnitPrice) -> {TotalUnits, TotalPrice}
  +	when
  +		Amount :: non_neg_integer(),
  +		UnitSize :: pos_integer(),
  +		UnitPrice :: pos_integer(),
  +		TotalUnits :: pos_integer(),
  +		TotalPrice :: pos_integer().
  +%% @doc Calculate total size and price.
  +price_units(0, _UnitSize, _UnitPrice) ->
  +	{0, 0};
  +price_units(Amount, UnitSize, UnitPrice) when (Amount rem UnitSize) == 0 ->
  +	{Amount, UnitPrice * (Amount div UnitSize)};
  +price_units(Amount, UnitSize, UnitPrice) ->
  +	Units = (Amount div UnitSize + 1),
  +	{Units * UnitSize, UnitPrice * Units}.
  +
  +-spec get_reserve(Price) -> ReserveAmount
  +	when
  +		Price :: #price{},
  +		ReserveAmount :: pos_integer().
  +%% @doc Get the reserve amount.
  +get_reserve(#price{units = seconds,
  +		char_value_use = CharValueUse} = _Price) ->
  +	case lists:keyfind("radiusReserveTime",
  +			#char_value_use.name, CharValueUse) of
  +		#char_value_use{values = [#char_value{value = Value}]} ->
  +			Value;
  +		false ->
  +			0
  +	end;
  +get_reserve(#price{units = octets,
  +		char_value_use = CharValueUse} = _Price) ->
  +	case lists:keyfind("radiusReserveBytes",
  +			#char_value_use.name, CharValueUse) of
  +		#char_value_use{values = [#char_value{value = Value}]} ->
  +			Value;
  +		false ->
  +			0
   	end.
   
  
positive.code: 	end.
  %% @hidden
  rate1(Protocol, Subscriber, Destination, #product{specification = "3", char_value_use = CharValueUse,
  		price = Prices}, Validity, Flag, DebitAmount, ReserveAmount, SessionAttributes) ->
  	case lists:keyfind("destPrefixPriceTable", #char_value_use.name, CharValueUse) of
  		#char_value_use{values = [#char_value{value = PriceTable}]} ->
  			rate2(Protocol, PriceTable, Subscriber, Destination, Prices,
  					Validity, Flag, DebitAmount, ReserveAmount, SessionAttributes);
  		false ->
  			 case lists:keyfind("destPrefixTariffTable", #char_value_use.name, CharValueUse) of
  				#char_value_use{values = [#char_value{value = TariffTable}]} ->
  					rate3(Protocol, TariffTable, Subscriber, Destination, Prices,
  							Validity, Flag, DebitAmount, ReserveAmount, SessionAttributes);
  				_ ->
  					throw(table_prefix_not_found)
  			end
  	end;
  rate1(Protocol, Subscriber, _Destiations, #product{price = Prices}, Validity,
  		Flag, DebitAmount, ReserveAmount, SessionAttributes) ->
  	case lists:keyfind(usage, #price.type, Prices) of
  		#price{} = Price ->
  			rate4(Protocol, Subscriber, Price, Validity,
  				Flag, DebitAmount, ReserveAmount, SessionAttributes);
  		false ->
  			throw(price_not_found)
  	end.
  %% @hidden
  rate2(Protocol, PriceTable, Subscriber, Destination, Prices,
  		Validity, Flag, DebitAmount, ReserveAmount, SessionAttributes) ->
  	case catch ocs_gtt:lookup_last(PriceTable, Destination) of
  		PriceKey when is_list(PriceKey) ->
  			F = fun(#price{char_value_use = CharValueUse}) ->
  
negative.code: 			throw(rating_failed)
  	end.
  %% @hidden
  rate4(_Protocol, #subscriber{enabled = false} = Subscriber, _Price,
  		_Validity, initial, _DebitAmounts, _ReserveAmounts,
  		SessionAttributes) ->
  erlang:display({?MODULE, ?LINE, disabled}),
  	rate6(Subscriber, initial, 0, 0, 0, 0, SessionAttributes);
  rate4(radius, Subscriber, Price, Validity,
  		initial, [], [], SessionAttributes) ->
  erlang:display({?MODULE, ?LINE, SessionAttributes}),
  	rate5(Subscriber, Price, Validity, initial,
  			0, get_reserve(Price), SessionAttributes);
  rate4(radius, Subscriber, #price{units = Units} = Price, Validity,
  		interim, [], ReserveAmounts, SessionAttributes) ->
  	ReserveAmount = case lists:keyfind(Units, 1, ReserveAmounts) of
  		{_, ReserveUnits} ->
  			ReserveUnits + get_reserve(Price);
  		false ->
  			get_reserve(Price)
  	end,
  	rate5(Subscriber, Price, Validity, interim,
  			0, ReserveAmount, SessionAttributes);
  rate4(_Protocol, Subscriber, #price{units = Units} = Price, Validity,
  		Flag, DebitAmounts, ReserveAmounts, SessionAttributes) ->
  	DebitAmount = case lists:keyfind(Units, 1, DebitAmounts) of
  		{_, DebitUnits} ->
  			DebitUnits;
  		false ->
  			0
  	end,
  	ReserveAmount = case lists:keyfind(Units, 1, ReserveAmounts) of
  		{_, ReserveUnits} ->
  			ReserveUnits;
  		false ->
  			0
  	end,
  erlang:display({?MODULE, ?LINE, Subscriber, DebitAmount, ReserveAmount, Units}),
  	rate5(Subscriber, Price, Validity, Flag,
  			DebitAmount, ReserveAmount, SessionAttributes).
  %% @hidden
  rate5(#subscriber{buckets = Buckets1} = Subscriber,
  		#price{units = Units, size = UnitSize, amount = UnitPrice},
  		_Validity, initial, 0, ReserveAmount, SessionAttributes) ->
  	SessionId = get_session_id(SessionAttributes),
  	case reserve_session(Units, ReserveAmount, SessionId, Buckets1) of
  		{ReserveAmount, Buckets2} ->
  			rate6(Subscriber#subscriber{buckets = Buckets2},
  					initial, 0, 0, ReserveAmount, ReserveAmount,
  					SessionAttributes);
  		{UnitsReserved, Buckets2} ->
  			PriceReserveUnits = (ReserveAmount - UnitsReserved),
  			{UnitReserve, PriceReserve} = price_units(PriceReserveUnits,
  					UnitSize, UnitPrice),
  			case reserve_session(cents, PriceReserve, SessionId, Buckets2) of
  				{PriceReserve, Buckets3} ->
  					rate6(Subscriber#subscriber{buckets = Buckets3},
  							initial, 0, 0, ReserveAmount,
  							UnitsReserved + UnitReserve, SessionAttributes);
  				{PriceReserved, Buckets3} ->
  					rate6(Subscriber#subscriber{buckets = Buckets3},
  							initial, 0, 0, ReserveAmount,
  							UnitsReserved + (PriceReserved div UnitPrice),
  							SessionAttributes)
  			end
  	end;
  rate5(#subscriber{enabled = false, buckets = Buckets1} = Subscriber,
  		#price{units = Units, size = UnitSize, amount = UnitPrice},
  		_Validity, interim, DebitAmount, _ReserveAmount, SessionAttributes) ->
  	SessionId = get_session_id(SessionAttributes),
  	case update_session(Units, DebitAmount, 0, SessionId, Buckets1) of
  		{DebitAmount, 0, Buckets2} ->
  			rate6(Subscriber#subscriber{buckets = Buckets2}, interim,
  					DebitAmount, DebitAmount, 0, 0, SessionAttributes);
  		{UnitsCharged, 0, Buckets2} ->
  			PriceChargeUnits = DebitAmount - UnitsCharged,
  			{UnitCharge, PriceCharge} = price_units(PriceChargeUnits,
  					UnitSize, UnitPrice),
  			case update_session(cents, PriceCharge, 0, SessionId, Buckets2) of
  				{PriceCharge, 0, Buckets3} ->
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, DebitAmount + UnitCharge,
  							0, 0, SessionAttributes);
  				{PriceCharged, 0, Buckets3} ->
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, UnitsCharged + (PriceCharged div UnitPrice),
  							0, 0, SessionAttributes)
  ; Other -> erlang:display({?MODULE, ?LINE, Other})
  			end
  ; Other -> erlang:display({?MODULE, ?LINE, Other})
  	end;
  rate5(#subscriber{buckets = Buckets1} = Subscriber,
  		#price{units = Units, size = UnitSize, amount = UnitPrice},
  		_Validity, interim, DebitAmount, ReserveAmount, SessionAttributes) ->
  	SessionId = get_session_id(SessionAttributes),
  erlang:display({?MODULE, ?LINE, DebitAmount, ReserveAmount, Units}),
  	case update_session(Units, DebitAmount, ReserveAmount,
  			SessionId, Buckets1) of
  		{DebitAmount, ReserveAmount, Buckets2} ->
  erlang:display({?MODULE, ?LINE, DebitAmount, ReserveAmount, Buckets2}),
  			rate6(Subscriber#subscriber{buckets = Buckets2}, interim,
  					DebitAmount, DebitAmount, ReserveAmount, ReserveAmount,
  					SessionAttributes);
  		{DebitAmount, UnitsReserved, Buckets2} ->
  erlang:display({?MODULE, ?LINE, DebitAmount, UnitsReserved, Buckets2}),
  			PriceReserveUnits = ReserveAmount - UnitsReserved,
  			{UnitReserve, PriceReserve} = price_units(PriceReserveUnits,
  					UnitSize, UnitPrice),
  			case update_session(cents, 0, PriceReserve, SessionId, Buckets2) of
  				{0, PriceReserve, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceReserve, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, DebitAmount, ReserveAmount,
  							UnitReserve, SessionAttributes);
  				{0, PriceReserved, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceReserve, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, DebitAmount, ReserveAmount,
  							UnitsReserved + PriceReserved div UnitPrice,
  							SessionAttributes)
  			end;
  		{UnitsCharged, 0, Buckets2} ->
  erlang:display({?MODULE, ?LINE, UnitsCharged, Buckets2}),
  			PriceChargeUnits = DebitAmount - UnitsCharged,
  			{UnitCharge, PriceCharge} = price_units(PriceChargeUnits,
  					UnitSize, UnitPrice),
  			{UnitReserve, PriceReserve} = price_units(ReserveAmount,
  					UnitSize, UnitPrice),
  			case update_session(cents,
  					PriceCharge, PriceReserve, SessionId, Buckets2) of
  				{PriceCharge, PriceReserve, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceCharge, PriceReserve, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, UnitsCharged + UnitCharge, ReserveAmount,
  							UnitReserve, SessionAttributes);
  				{PriceCharge, PriceReserved, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceCharge, PriceReserved, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, UnitsCharged + UnitCharge, ReserveAmount,
  							PriceReserved div UnitPrice, SessionAttributes);
  				{PriceCharged, 0, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceCharged, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, interim,
  							DebitAmount, UnitsCharged + (PriceCharged div UnitPrice),
  							ReserveAmount, 0, SessionAttributes)
  ; Other -> erlang:display({?MODULE, ?LINE, Other})
  			end
  	end;
  rate5(#subscriber{buckets = Buckets1} = Subscriber,
  		#price{units = Units, size = UnitSize, amount = UnitPrice},
  		_Validity, final, DebitAmount, 0, SessionAttributes) ->
  	SessionId = get_session_id(SessionAttributes),
  erlang:display({?MODULE, ?LINE, DebitAmount, Buckets1}),
  	case charge_session(Units, DebitAmount, SessionId, Buckets1) of
  		{DebitAmount, Buckets2} ->
  erlang:display({?MODULE, ?LINE, DebitAmount, Buckets2}),
  			rate6(Subscriber#subscriber{buckets = Buckets2}, final,
  					DebitAmount, DebitAmount, 0, 0, SessionAttributes);
  		{UnitsCharged, Buckets2} ->
  erlang:display({?MODULE, ?LINE, UnitsCharged, Buckets2}),
  			PriceChargeUnits = DebitAmount - UnitsCharged,
  			{UnitCharge, PriceCharge} = price_units(PriceChargeUnits,
  					UnitSize, UnitPrice),
  			case charge_session(cents, PriceCharge, SessionId, Buckets2) of
  				{PriceCharge, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceCharge, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, final,
  							DebitAmount, UnitsCharged + UnitCharge,
  							0, 0, SessionAttributes);
  				{PriceCharged, Buckets3} ->
  erlang:display({?MODULE, ?LINE, PriceCharged, Buckets3}),
  					rate6(Subscriber#subscriber{buckets = Buckets3}, final,
  					DebitAmount, UnitsCharged + (PriceCharged div UnitPrice),
  					0, 0, SessionAttributes)
  			end
  	end.
  %% @hidden
  rate6(#subscriber{session_attributes = SessionList} = Subscriber1,
  		final, Charge, Charged, 0, 0, SessionAttributes)
  		when Charged >= Charge ->
  	NewSessionList = remove_session(SessionAttributes, SessionList),
  	Subscriber2 = Subscriber1#subscriber{session_attributes = NewSessionList},
  	ok = mnesia:write(Subscriber2),
  erlang:display({?MODULE, ?LINE, grant, Subscriber2, Charged}),
  	{grant, Subscriber2, Charged};
  rate6(#subscriber{session_attributes = SessionList} = Subscriber1,
  		final, _Charge, _Charged, 0, 0, _SessionAttributes) ->
  	Subscriber2 = Subscriber1#subscriber{session_attributes = []},
  	ok = mnesia:write(Subscriber2),
  erlang:display({?MODULE, ?LINE, out_of_credit, Subscriber2, SessionList}),
  	{out_of_credit, SessionList};
  rate6(#subscriber{enabled = false,
  		session_attributes = SessionList} = Subscriber1, _Flag,
  		_Charge, _Charged, _Reserve, _Reserved, _SessionAttributes) ->
  	Subscriber2 = Subscriber1#subscriber{session_attributes = []},
  	ok = mnesia:write(Subscriber2),
  erlang:display({?MODULE, ?LINE, disabled, SessionList}),
  	{disabled, SessionList};
  rate6(#subscriber{session_attributes = SessionList} = Subscriber1, _Flag,
  		Charge, Charged, Reserve, Reserved, _SessionAttributes)
  		when Charged < Charge; Reserved <  Reserve ->
  	Subscriber2 = Subscriber1#subscriber{session_attributes = []},
  	ok = mnesia:write(Subscriber2),
  erlang:display({?MODULE, ?LINE, out_of_credit, Subscriber2, SessionList}),
  	{out_of_credit, SessionList};
  rate6(#subscriber{session_attributes = SessionList} = Subscriber1,
  		initial, 0, 0, _Reserve, Reserved, SessionAttributes) ->
  	NewSessionList = add_session(SessionAttributes, SessionList),
  	Subscriber2 = Subscriber1#subscriber{session_attributes = NewSessionList},
  	ok = mnesia:write(Subscriber2),
  erlang:display({?MODULE, ?LINE, grant, Subscriber2, Reserved}),
  	{grant, Subscriber2, Reserved};
  rate6(Subscriber, interim, _Charge, _Charged, _Reserve, Reserved, _SessionAttributes) ->
  	ok = mnesia:write(Subscriber),
  erlang:display({?MODULE, ?LINE, grant, Subscriber, Reserved}),
  	{grant, Subscriber, Reserved}.
  
  %%----------------------------------------------------------------------
  %%  internal functions
  %%----------------------------------------------------------------------
  
  -spec reserve_session(Type, Amount, SessionId, Buckets) -> Result
  	when
  		Type :: octets | seconds | cents,
  		Amount :: non_neg_integer(),
  		SessionId :: string() | binary(),
  		Buckets :: [#bucket{}],
  		Result :: {Reserved, NewBuckets},
  		Reserved :: non_neg_integer(),
  		NewBuckets :: [#bucket{}].
  %% @doc Perform reservation for a session.
  %%
  %% 	Creates a reservation within bucket(s) of `Type' and
  %% 	decrements remaing balance by the same amount(s).
  %%
  %% 	Expired buckets are removed when no session
  %% 	reservations remain.
  %%
  %% 	Returns `{Reserved, NewBuckets}' where
  %% 	`Reserved' is the total amount of reservation(s) made
  %% 	and `NewBuckets' is the updated bucket list.
  %%
  %% @private
  reserve_session(Type, Amount, SessionId, Buckets) ->
  	Now = erlang:system_time(?MILLISECOND),
  	reserve_session(Type, Amount, Now, SessionId, sort(Buckets), [], 0).
  %% @hidden
  reserve_session(Type, Amount, Now, SessionId,
  		[#bucket{termination_date = Expires, reservations = []} | T],
  		Acc, Reserved) when Expires /= undefined, Expires =< Now->
  	reserve_session(Type, Amount, Now, SessionId, T, Acc, Reserved);
  reserve_session(Type, Amount, Now, SessionId,
  		[#bucket{units = Type, remain_amount = Remain,
  		reservations = Reservations, termination_date = Expires} = B | T],
  		Acc, Reserved) when Remain >= Amount,
  		((Expires == undefined) or (Now < Expires)) ->
  	NewReservation = {Now, Amount, SessionId},
  	NewBuckets = lists:reverse(Acc)
  			++ [B#bucket{remain_amount = Remain - Amount,
  			reservations = [NewReservation | Reservations]} | T],
  	{Reserved + Amount, NewBuckets};
  reserve_session(Type, Amount, Now, SessionId,
  		[#bucket{units = Type, remain_amount = Remain,
  		reservations = Reservations, termination_date = Expires} = B | T],
  		Acc, Reserved) when Remain < Amount,
  		((Expires == undefined) or (Now < Expires)) ->
  	NewReserve = Amount - Remain,
  	NewReservation = {Now, NewReserve, SessionId},
  	NewAcc = [B#bucket{remain_amount = 0,
  			reservations = [NewReservation | Reservations]} | Acc],
  	reserve_session(Type, Amount - NewReserve, Now,
  			SessionId, T, NewAcc, Reserved + NewReserve);
  reserve_session(Type, Amount, Now, SessionId, [H | T], Acc, Reserved) ->
  	reserve_session(Type, Amount, Now, SessionId, T, [H | Acc], Reserved);
  reserve_session(_, _, _, _, [], Acc, Reserved) ->
  	{Reserved, lists:reverse(Acc)}.
  
  -spec update_session(Type, Charge, Reserve, SessionId, Buckets) -> Result
  	when
  		Type :: octets | seconds | cents,
  		Charge :: non_neg_integer(),
  		Reserve :: non_neg_integer(),
  		SessionId :: string() | binary(),
  		Buckets :: [#bucket{}],
  		Result :: {Charged, Reserved, NewBuckets},
  		Charged :: non_neg_integer(),
  		Reserved :: non_neg_integer(),
  		NewBuckets :: [#bucket{}].
  %% @doc Perform debit and reservation for a session.
  %%
  %% 	Finds reservations matching `SessionId'.
  %%
  %% 	Empty or expired buckets are removed when no session
  %% 	reservations remain.
  %%
  %% 	Returns `{Charged, Reserved, NewBuckets}' where
  %% 	`Charged' is the total amount debited from bucket(s),
  %% 	`Reserved' is the total amount of reservation(s) made,
  %% 	and `NewBuckets' is the updated bucket list.
  %%
  %% @private
  update_session(Type, Charge, Reserve, SessionId, Buckets) ->
  	Now = erlang:system_time(?MILLISECOND),
  	update_session(Type, Charge, Reserve, Now, SessionId,
  			sort(Buckets), [], 0, 0).
  %% @hidden
  update_session(Type, Charge, Reserve, Now, SessionId,
  		[#bucket{termination_date = Expires, reservations = []} | T],
  		Acc, Charged, Reserved) when Expires /= undefined, Expires =< Now ->
  	update_session(Type, Charge, Reserve,
  			Now, SessionId, T, Acc, Charged, Reserved);
  update_session(Type, Charge, Reserve, Now, SessionId,
  		[#bucket{units = Type, remain_amount = Remain,
  		termination_date = Expires, reservations = Reservations} = B | T],
  		Acc, Charged, Reserved) ->
  	case lists:keytake(SessionId, 3, Reservations) of
  		{value, {_, Amount, _}, NewReservations}
  				when Remain >= (Reserve - (Amount - Charge)),
  				((Expires == undefined) or (Now < Expires)) ->
  			NewReservation = {Now, Reserve, SessionId},
  			NewBuckets = lists:reverse(Acc)
  					++ [B#bucket{remain_amount = Remain
  					- (Reserve - (Amount - Charge)),
  					reservations = [NewReservation | NewReservations]} | T],
  			{Charged + Charge, Reserved + Reserve, NewBuckets};
  		{value, {_, Amount, _}, []}
  				when (Remain + Amount) =< Charge,
  				((Expires == undefined) or (Now < Expires)) ->
  			update_session(Type, Charge - (Remain + Amount), Reserve,
  					Now, SessionId, T, Acc, Charged + Remain + Amount, Reserved);
  		{value, {_, Amount, _}, []}
  				when Amount >= Charge, Expires /= undefined, Expires =< Now ->
  			update_session(Type, 0, Reserve, Now,
  					SessionId, T, Acc, Charge, Reserved);
  		{value, {_, Amount, _}, NewReservations}
  				when Amount >= Charge, Expires /= undefined, Expires =< Now ->
  			NewAcc = [B#bucket{reservations = NewReservations} | Acc],
  			update_session(Type, 0, Reserve, Now,
  					SessionId, T, NewAcc, Charge, Reserved);
  		{value, {_, Amount, _}, []}
  				when Amount < Charge, Expires /= undefined, Expires =< Now ->
  			update_session(Type, Charge - Amount, Reserve, Now,
  					SessionId, T, Acc, Charge, Reserved);
  		{value, {_, Amount, _}, NewReservations}
  				when Amount < Charge, Expires /= undefined, Expires =< Now ->
  			NewAcc = [B#bucket{reservations = NewReservations} | Acc],
  			update_session(Type, Charge - Amount, Reserve, Now,
  					SessionId, T, NewAcc, Charge, Reserved);
  		{value, {_, Amount, _}, NewReservations}
  				when (Remain + Amount) =< Charge,
  				((Expires == undefined) or (Now < Expires)) ->
  			NewAcc = [B#bucket{remain_amount = 0, reservations = NewReservations} | Acc],
  			update_session(Type, Charge - (Remain + Amount), Reserve,
  					Now, SessionId, T, NewAcc, Charged + Remain + Amount, Reserved);
  		{value, {_, Amount, _}, NewReservations}
  				when Remain >= (Charge - Amount),
  				((Expires == undefined) or (Now < Expires)) ->
  			NewReserve = Remain - (Charge - Amount),
  			NewReservation = {Now, NewReserve, SessionId},
  			NewAcc = [B#bucket{remain_amount = 0,
  					reservations = [NewReservation | NewReservations]} | Acc],
  			update_session(Type, 0, Reserve - NewReserve, Now, SessionId,
  					T, NewAcc, Charged + Charge, Reserved + NewReserve);
  		_ when Reservations == [], Expires /= undefined, Expires =< Now ->
  			update_session(Type, Charge, Reserve, Now, SessionId,
  					T, Acc, Charged, Reserved);
  		false ->
  			update_session(Type, Charge, Reserve, Now, SessionId,
  					T, [B | Acc], Charged, Reserved)
  	end;
  update_session(_, _, _, _, _, [], Acc, Charged, Reserved) ->
  	{Charged, Reserved, lists:reverse(Acc)}.
  
  -spec charge_session(Type, Charge, SessionId, Buckets) -> Result
  	when
  		Type :: octets | seconds | cents,
  		Charge :: non_neg_integer(),
  		SessionId :: string() | binary(),
  		Buckets :: [#bucket{}],
  		Result :: {Charged, NewBuckets},
  		Charged :: non_neg_integer(),
  		NewBuckets :: [#bucket{}].
  %% @doc Peform final charging for a session.
  %%
  %% 	Finds and removes all reservations matching `SessionId'.
  %% 	If the total reservation amounts are less than `Charge'
  %% 	the deficit is debited. Any surplus is refunded within
  %% 	the bucket containing the reservation.
  %%
  %% 	Empty buckets are removed. Expired buckets are removed
  %% 	when no session reservations remain.
  %%
  %% 	Returns `{Charged, NewBuckets}' where
  %% 	`Charged' is the total amount debited from the buckets
  %% 	and `NewBuckets' is the updated bucket list.
  %%
  %% @private
  charge_session(Type, Charge, SessionId, Buckets) ->
  	Now = erlang:system_time(?MILLISECOND),
  	charge_session(Type, Charge, Now, SessionId, sort(Buckets), 0, []).
  %% @hidden
  charge_session(Type, Charge, Now, SessionId,
  		[#bucket{units = Type, termination_date = Expires,
  		remain_amount = Remain, reservations = Reservations} = B | T],
  		Charged, Acc) ->
  erlang:display({?MODULE, ?LINE, Acc}),
  	case lists:keytake(SessionId, 3, Reservations) of
  		{value, {_, Amount, _}, NewReservations} when Amount >= Charge,
  				((Expires == undefined) or (Now < Expires)) ->
  			NewAcc = [B#bucket{remain_amount = Remain + (Amount - Charge),
  					reservations = NewReservations} | Acc],
  			charge_session(Type, 0, Now, SessionId, T, Charged + Charge, NewAcc);
  		{value, {_, Amount, _}, []} when Amount >= Charge,
  				Expires /= undefined, Expires =< Now ->
  			charge_session(Type, 0, Now, SessionId, T, Charged + Charge, Acc);
  		{value, {_, Amount, _}, NewReservations} when Amount >= Charge,
  				Expires /= undefined, Expires =< Now ->
  			NewAcc = [B#bucket{reservations = NewReservations} | Acc],
  			charge_session(Type, 0, Now, SessionId, T, Charged + Charge, NewAcc);
  		{value, {_, Amount, _}, NewReservations}
  				when Amount < Charge, Remain > (Charge - Amount),
  				((Expires == undefined) or (Now < Expires)) ->
  			NewAcc = [B#bucket{remain_amount = Remain - (Charge - Amount),
  					reservations = NewReservations} | Acc],
  			charge_session(Type, 0, Now, SessionId, T, Charged + Charge, NewAcc);
  		{value, {_, Amount, _}, []} when Amount < Charge,
  				Expires /= undefined, Expires =< Now ->
  			charge_session(Type, Charge - Amount, Now, SessionId, T, Charged + Charge, Acc);
  		{value, {_, Amount, _}, NewReservations} when Amount < Charge,
  				Expires /= undefined, Expires =< Now ->
  			NewAcc = [B#bucket{reservations = NewReservations} | Acc],
  			charge_session(Type, Charged + Charge, Now, SessionId, T, Charge - Amount, NewAcc);
  		{value, {_, Amount, _}, []}
  				when Amount < Charge, Remain =< (Charge - Amount),
  				((Expires == undefined) or (Now < Expires)) ->
  			charge_session(Type, Charge - Amount - Remain, Now, SessionId, T, Amount + Remain, Acc);
  		{value, {_, Amount, _}, NewReservations}
  				when Amount < Charge, Remain =< (Charge - Amount),
  				((Expires == undefined) or (Now < Expires)) ->
  			NewAcc = [B#bucket{reservations = NewReservations} | Acc],
  			charge_session(Type, Charge - Amount - Remain, Now, SessionId, T, Amount + Remain, NewAcc);
  		{value, {_, Amount, _}, NewReservations} when Charge =:= 0,
  				((Expires == undefined) or (Now < Expires)) ->
  			NewAcc = [B#bucket{remain_amount = Remain + Amount,
  					reservations = NewReservations} | Acc],
  			charge_session(Type, 0, Now, SessionId, T, Charged, NewAcc);
  		_ when Reservations == [], Expires /= undefined, Expires =< Now ->
  			charge_session(Type, Charge, Now, SessionId, T, Charged, Acc);
  		false ->
  			charge_session(Type, Charge, Now, SessionId, T, Charged, [B | Acc])
  	end;
  charge_session(Type, Charge, Now, SessionId, [H | T], Charged, Acc) ->
  	charge_session(Type, Charge, Now, SessionId, T, Charged, [H | Acc]);
  charge_session(_, Charge, _, _, [], Charge, Acc) ->
  	{Charge, lists:reverse(Acc)};
  charge_session(Type, Charge, Now, _, [], Charged, Acc) ->
  	charge(Type, Charge, Now, lists:reverse(Acc), [], Charged).
  
  %% @hidden
  charge(Type, Charge, Now,
  		[#bucket{termination_date = Expires, reservations = []} | T],
  		Acc, Charged) when Expires /= undefined, Expires =< Now ->
  	charge(Type, Charge, Now, T, Acc, Charged);
  charge(Type, Charge, Now, [#bucket{units = Type,
  		remain_amount = R, termination_date = Expires} = B | T],
  		Acc, Charged) when R > Charge,
  		((Expires == undefined) or (Now < Expires)) ->
  	NewBuckets = [B#bucket{remain_amount = R - Charge} | T],
  	{Charged + Charge, lists:reverse(Acc) ++ NewBuckets};
  charge(Type, Charge, Now, [#bucket{units = Type,
  		remain_amount = R, reservations = [],
  		termination_date = Expires} | T], Acc, Charged)
  		when R =< Charge, ((Expires == undefined) or (Now < Expires)) ->
  	charge(Type, Charge - R, Now, T, Acc, Charged + R);
  charge(Type, Charge, Now, [#bucket{units = Type,
  		remain_amount = R, termination_date = Expires} = B | T], Acc, Charged)
  		when R =< Charge, ((Expires == undefined) or (Now < Expires)) ->
  	NewAcc = [B#bucket{remain_amount = 0} | Acc],
  	charge(Type, Charge - R, Now, T, NewAcc, Charged + R);
  charge(_Type, 0, _Now, Buckets, Acc, Charged) ->
  	{Charged, lists:reverse(Acc) ++ Buckets};
  charge(Type, Charge, Now, [H | T], Acc, Charged) ->
  	charge(Type, Charge, Now, T, [H | Acc], Charged);
  charge(_, _, _, [], Acc, Charged) ->
  	{Charged, lists:reverse(Acc)}.
  
  -spec remove_session(SessionAttributes, SessionList) -> NewSessionList
  	when
  		SessionAttributes :: [tuple()],
  		SessionList :: [{pos_integer(), [tuple()]}],
  		NewSessionList :: [{pos_integer(), [tuple()]}].
  %% @doc Remove session identification attributes set from active sessions list.
  %% @private
  remove_session(SessionAttributes, SessionList) ->
  