:- module(graph_search, [ graph_search/3, % +Query, -RDFState, +Options flush_graph_search_cache/0 ]). :- use_module(library(semweb/rdf_db)). % util modules :- use_module(rdf_search). :- use_module(rdf_backward_search). :- use_module(cs_filter). :- use_module(library(cluster_search/settings)). %% graph_search(+Keyword, -RDFState, +Options) is det. % % Start search from Keyword. Options is a list of: % % * steps(+Integer) % Max number of nodes to expand from the agenda % % * prune(+Boolean) % If =true= (default), prune all failed paths from % the graph. % % * threshold(+Threshold) % Search cut-off threshold % % @tbd restore different types of search in do_graph_search :- dynamic graph_search_cache/4, % +Hash, +Kwd, +Options, -State cache_generation/1. :- rdf_meta graph_search(+, -, t). graph_search(Keyword, State, Options) :- setting(cluster_search:graphSearchCache, false), !, do_graph_search(Keyword, State, Options). graph_search(Keyword, State, Options) :- check_cache_validity, term_hash(Keyword+Options, Key), ( graph_search_cache(Key, Keyword, Options, State) -> true ; do_graph_search(Keyword, State, Options), push_graph_search_cache(Key, Keyword, Options, State) ). do_graph_search(Keyword, State, Options) :- option(target(SearchTarget), Options), filter_to_goal([type(SearchTarget)], R, Goal, Options), TargetCond = target_goal(Goal, R), rdf_backward_search(Keyword, TargetCond, State, Options), prune(State, []). prune(State, Options) :- rdf_prune_search(State, Options), rdf_search_property(State, graph_size(Nodes)), debug(rdf_search, 'After prune: ~D nodes in graph', [Nodes]). /*************************************************** * caching ***************************************************/ %% check_cache_validity is det. % % Remove the cache if it is not valid. We use rdf_generation/1 for % this. This means any change to the RDF database invalidates the % cache. Ideally we should restrict this to named graphs used in % the search, but that is not easy to define. check_cache_validity :- cache_generation(CacheGen), rdf_generation(CacheGen), !. check_cache_validity :- rdf_generation(CacheGen), retractall(cache_generation(_)), assert(cache_generation(CacheGen)), flush_graph_search_cache. %% flush_graph_search_cache is det. % % Flushes the cache for graph_search/3. flush_graph_search_cache :- retractall(graph_search_cache(_,_,_,_)). %% push_graph_search_cache(+Key, +Keyword, +Options, -State) is det. % % Add a result to the search cache. Note that we first check % whether the result was added to avoid the not so % uncommon case that two threads compute the same result % concurrently. push_graph_search_cache(Key, Kwd, Options, State) :- graph_search_cache(Key, Kwd, Options, State), !. push_graph_search_cache(Key, Kwd, Options, State) :- setting(cluster_search:graphSearchCacheSize, Max), ( Max == 0 -> true ; predicate_property(graph_search_cache(_,_,_,_), number_of_clauses(Size)), Size > Max -> once(retract(graph_search_cache(_,_,_,_))) ; true ), assertz(graph_search_cache(Key, Kwd, Options, State)).