anchor.diff:  		{aborted, Reason} ->
   			exit(Reason)
   	end.
  -
   -spec query_clients(Cont, Address, Identifier, Port, Protocol, Secret) -> Result
   	when
  -		Cont :: start | eof | any(),
  -		Address :: undefined | string(),
  -		Identifier :: undefined | string(),
  -		Port :: undefined | string(),
  -		Protocol :: undefined | string(),
  -		Secret :: undefined | string(),
  -		Result :: {Cont, [#client{}]} | {error, Reason},
  -		Reason :: term().
  +		Cont :: start | any(),
  +		Address :: Match,
  +		Identifier :: Match,
  +		Port :: Match,
  +		Protocol :: Match,
  +		Secret :: Match,
  +		Match :: {exact, string()} | {notexact, string()} | {like, string()} | '_',
  +		Result :: {Cont, [#client{}]} | eof | {error, Reason},
  +		Reason :: term().
  +%% @hidden
   query_clients(start, Address, Identifier, Port, Protocol, Secret) ->
   	MatchSpec = [{'_', [], ['$_']}],
  -	F = fun() ->
  -		mnesia:select(client, MatchSpec, read)
  -	end,
  -	case mnesia:transaction(F) of
  -		{atomic, Clients} ->
  -			query_clients1(Clients, Address, Identifier, Port, Protocol, Secret);
  -		{aborted, Reason} ->
  -			{error, Reason}
  -	end.
  -%% @hidden
  -query_clients1(Clients, Address, Identifier, Port, Protocol, undefined) ->
  -	query_clients2(Clients, Address, Identifier, Port, Protocol);
  -query_clients1(Clients, Address, Identifier, Port, Protocol, Secret) ->
  -	SecretBin = list_to_binary(Secret),
  -	SecretLen = size(SecretBin),
  -	Fun = fun(#client{secret = S}) ->
  -			case S of
  -				<<SecretBin:SecretLen/binary, _/binary>> ->
  -					true;
  -				_ ->
  -					false
  -			end
  -	end,
  -	FilteredClients = lists:filter(Fun, Clients),
  -	query_clients2(FilteredClients, Address, Identifier, Port, Protocol).
  -%% @hidden
  -query_clients2(Clients, Address, Identifier, Port, undefined) ->
  -	query_clients3(Clients, Address, Identifier, Port);
  -query_clients2(Clients, Address, Identifier, Port, Protocol) ->
  -	P1 = string:to_upper(Protocol),
  -	Fun = fun(#client{protocol = P}) ->
  -				P2 = string:to_upper(atom_to_list(P)),
  -				lists:prefix(P1, P2)
  -	end,
  -	FilteredClients = lists:filter(Fun, Clients),
  -	query_clients3(FilteredClients, Address, Identifier, Port).
  -%% @hidden
  -query_clients3(Clients, Address, Identifier, undefined) ->
  -	query_clients4(Clients, Address, Identifier);
  -query_clients3(Clients, Address, Identifier, Port) ->
  -	Fun = fun(#client{port = P}) -> lists:prefix(Port, integer_to_list(P)) end,
  -	FilteredClients = lists:filter(Fun, Clients),
  -	query_clients4(FilteredClients, Address, Identifier).
  -%% @hidden
  -query_clients4(Clients, Address, undefined) ->
  -	query_clients4(Clients, Address);
  -query_clients4(Clients, Address, Identifier) ->
  -	IdBin = list_to_binary(Identifier),
  -	IdLen = size(IdBin),
  -	Fun = fun(#client{identifier = I}) ->
  -			case I of
  -				<<IdBin:IdLen/binary, _/binary>> ->
  -					true;
  -				_ ->
  -					false
  -			end
  -	end,
  -	FilteredClients = lists:filter(Fun, Clients),
  -	query_clients4(FilteredClients, Address).
  -%% @hidden
  -query_clients4(Clients, undefined) ->
  -	{eof, Clients};
  -query_clients4(Clients, Address) ->
  -	Fun = fun(#client{address = A}) -> lists:prefix(Address, inet:ntoa(A)) end,
  -	{eof, lists:filter(Fun, Clients)}.
  +	F = fun() -> mnesia:select(client, MatchSpec, ?CHUNKSIZE, read) end,
  +	case catch mnesia:ets(F) of
  +		{'EXIT', Reason} ->
  +			{error, Reason};
  +		{Clients, Cont1} ->
  +			query_clients1(Cont1, Address, Identifier,
  +					Port, Protocol, Secret, Clients);
  +		'$end_of_table' ->
  +			eof
  +	end.
  +%% @hidden
  +query_clients1(Cont, '_', Identifier, Port, Protocol, Secret, Clients) ->
  +	query_clients2(Cont, Identifier, Port, Protocol, Secret, Clients);
  +query_clients1(Cont, {Operator, Address}, Identifier, Port, Protocol, Secret, Clients) ->
  +	F = fun(#client{address = Address1}) when is_tuple(Address1) ->
  +				match(Operator, Address, inet:ntoa(Address1));
  +		(_) ->
  +			false
  +	end,
  +	query_clients2(Cont, Identifier, Port, Protocol, Secret, lists:filter(F, Clients)).
  +%% @hidden
  +query_clients2(Cont, '_', Port, Protocol, Secret, Clients) ->
  +	query_clients3(Cont, Port, Protocol, Secret, Clients);
  +query_clients2(Cont, {Operator, Identifier}, Port, Protocol, Secret, Clients) ->
  +	F = fun(#client{identifier = Identifier1}) when is_binary(Identifier1) ->
  +				match(Operator, Identifier, binary_to_list(Identifier1));
  +			(_) ->
  +				false
  +	end,
  +	query_clients3(Cont, Port, Protocol, Secret, lists:filter(F, Clients)).
  +%% @hidden
  +query_clients3(Cont, '_', Protocol, Secret, Clients) ->
  +	query_clients4(Cont, Protocol, Secret, Clients);
  +query_clients3(Cont, {Operator, Port}, Protocol, Secret, Clients) ->
  +	F = fun(#client{port = Port1}) when is_integer(Port1) ->
  +				match(Operator, Port, integer_to_list(Port1));
  +			(_) ->
  +				false
  +	end,
  +	query_clients4(Cont, Protocol, Secret, lists:filter(F, Clients)).
  +%% @hidden
  +query_clients4(Cont, '_', Secret, Clients) ->
  +	query_clients5(Cont, Secret, Clients);
  +query_clients4(Cont, {Operator, Protocol}, Secret, Clients) ->
  +	F = fun(#client{protocol = Proto}) when Proto == radius; Proto == diameter ->
  +				match(Operator, Protocol, atom_to_list(Proto));
  +			(_) ->
  +				false
  +	end,
  +	query_clients5(Cont, Secret, lists:filter(F, Clients)).
  +%% @hidden
  +query_clients5(Cont, '_', Clients) ->
  +	{Cont, Clients};
  +query_clients5(Cont, {Operator, Secret}, Clients) ->
  +	F = fun(#client{secret = Secret1}) when is_binary(Secret1) ->
  +				match(Operator, Secret, binary_to_list(Secret1));
  +			(_) ->
  +				false
  +	end,
  +	{Cont, lists:filter(F, Clients)}.
   
   get_products()->
   	MatchSpec = [{'_', [], ['$_']}],
  
positive.code: 
  -spec query_bucket(Cont, Id, Product) -> Result
  	when
  		Cont :: start | eof | any(),
  		Id :: string() | undefined | '_',
  		Product :: string() | undefined | '_',
  		Result :: {Cont, [#bucket{}]} | {error, Reason},
  		Reason :: term().
  %% @doc Query bucket
  query_bucket(Cont, Id, undefined) ->
  	query_bucket(Cont, Id, '_');
  query_bucket(Cont, undefined, Product) ->
  	query_bucket(Cont, '_', Product);
  query_bucket(start, Id, Product) ->
  	MatchSpec = [{'_', [], ['$_']}],
  	F = fun F(start, Acc) ->
  				F(mnesia:select(bucket, MatchSpec,
  						?CHUNKSIZE, read), Acc);
  			F('$end_of_table', Acc) ->
  				lists:flatten(lists:reverse(Acc));
  			F({error, Reason}, _Acc) ->
  				{error, Reason};
  			F({Services, Cont}, Acc) ->
  				F(mnesia:select(Cont), [Services | Acc])
  	end,
  	case mnesia:transaction(F, [start, []]) of
  		{aborted, Reason} ->
  			{error, Reason};
  		{atomic, Buckets} ->
  			{eof, query_bucket1(Id, Product, Buckets)}
  	end.
  %% @hidden
  query_bucket1('_', Product, Buckets) ->
  	query_bucket2(Product, Buckets);
  query_bucket1(Id, Product, Buckets) ->
  	F = fun(#bucket{id = Id1}) -> lists:prefix(Id, Id1) end,
  	NewBuckets = lists:filter(F, Buckets),
  	query_bucket2(Product, NewBuckets).
  %% @hidden
  query_bucket2('_', Buckets) ->
  	Buckets;
  query_bucket2(Product, Buckets) ->
  	F1 = fun(#bucket{product = Products}) ->
  		F2 = fun(Product1) -> lists:prefix(Product, Product1) end,
  		lists:any(F2, Products)
  	end,
  	lists:filter(F1, Buckets).
  
  -spec delete_bucket(BucketId) -> ok
  	when
  
negative.code: match_condition(Var, {gte, Term}) ->
  	{'>=', Var, Term}.
  
  
  %% @hidden
  match(exact, String, String) ->
  	true;
  match(exact, _String1, _String2) ->
  	false;
  match(notexact, String, String) ->
  	false;
  match(notexact, _String1, _String2) ->
  	true;
  match(like, String1, String2) ->
  	case lists:last(String1) of
  		$% ->
  			Prefix = lists:droplast(String1),
  			lists:prefix(Prefix, String2);
  		_ ->
  			lists:prefix(String1, String2)
  	end.
  