diff options
| author | Zoltan Ujhelyi | 2017-06-22 11:47:19 +0000 |
|---|---|---|
| committer | Zoltan Ujhelyi | 2017-06-26 12:54:01 +0000 |
| commit | a03f56e68fbc784111b1606ef31389269380d7c6 (patch) | |
| tree | 902fb042accb42cf16bb4b82c78b638edca33a47 | |
| parent | 483086b4a63feb8a4e521fdf89c67c37e5a29bd9 (diff) | |
| download | org.eclipse.viatra-a03f56e68fbc784111b1606ef31389269380d7c6.tar.gz org.eclipse.viatra-a03f56e68fbc784111b1606ef31389269380d7c6.tar.xz org.eclipse.viatra-a03f56e68fbc784111b1606ef31389269380d7c6.zip | |
[441323] Added support for search operations to cache results
The proposed cache implementations are simple; one of them is bound to
the backend, while the other is reset after each pattern match process.
Change-Id: I177295cd26e0fbfa574936a7ed959bacb827b9ae
Signed-off-by: Zoltan Ujhelyi <ujhelyiz@incquerylabs.com>
6 files changed, 156 insertions, 9 deletions
diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters index 354f0882e..846be8c7d 100644 --- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters +++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/.settings/.api_filters @@ -1,5 +1,34 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <component id="org.eclipse.viatra.query.runtime.localsearch" version="2"> + <resource path="src/org/eclipse/viatra/query/runtime/localsearch/matcher/ISearchContext.java" type="org.eclipse.viatra.query.runtime.localsearch.matcher.ISearchContext$SearchContext"> + <filter id="338722907"> + <message_arguments> + <message_argument value="org.eclipse.viatra.query.runtime.localsearch.matcher.ISearchContext.SearchContext"/> + <message_argument value="SearchContext(IBaseIndex, IQueryResultProviderAccess, QueryEvaluationHint)"/> + </message_arguments> + </filter> + <filter comment="Internal API implementation" id="576725006"> + <message_arguments> + <message_argument value="ISearchContext"/> + <message_argument value="SearchContext"/> + </message_arguments> + </filter> + </resource> + <resource path="src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java" type="org.eclipse.viatra.query.runtime.localsearch.matcher.integration.LocalSearchBackend"> + <filter comment="Internal API usage" id="640708718"> + <message_arguments> + <message_argument value="PurgableCache()"/> + <message_argument value="LocalSearchBackend"/> + </message_arguments> + </filter> + <filter comment="Internal API usage" id="640712815"> + <message_arguments> + <message_argument value="PurgableCache"/> + <message_argument value="LocalSearchBackend"/> + <message_argument value="purge()"/> + </message_arguments> + </filter> + </resource> <resource path="src/org/eclipse/viatra/query/runtime/localsearch/operations/CallOperationHelper.java" type="org.eclipse.viatra.query.runtime.localsearch.operations.CallOperationHelper$PatternCall"> <filter id="643846161"> <message_arguments> diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/ISearchContext.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/ISearchContext.java index ddefd91d6..d8038c7b0 100644 --- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/ISearchContext.java +++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/ISearchContext.java @@ -32,15 +32,24 @@ import org.eclipse.viatra.query.runtime.matchers.context.IQueryResultProviderAcc import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException; import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; +import org.eclipse.viatra.query.runtime.matchers.util.PurgableCache; +import org.eclipse.viatra.query.runtime.matchers.util.ICache; +import org.eclipse.viatra.query.runtime.matchers.util.IProvider; /** * The {@link ISearchContext} interface allows search operations to reuse platform services such as the indexer. * * @author Zoltan Ujhelyi + * @noreference This interface is not intended to be referenced by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. * */ public interface ISearchContext{ + /** + * Provides access to the EMF-specific base index for search operation; do not use if not on EMF Scope + */ NavigationHelper getBaseIndex(); /** @@ -59,22 +68,36 @@ public interface ISearchContext{ */ IQueryResultProvider getMatcher(MatcherReference reference) throws LocalSearchException; + /** + * Allows search operations to cache values through the entire lifecycle of the local search backend. The values are + * calculated if not cached before using the given provider, or returned from the cache accordingly. + * + * @since 1.7 + */ + <T> T accessBackendLevelCache(Object key, Class<? extends T> clazz, IProvider<T> valueProvider); + + /** + * @noreference This class is not intended to be referenced by clients. + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ public class SearchContext implements ISearchContext { final NavigationHelper navigationHelper; final IQueryResultProviderAccess resultProviderAccess; final QueryEvaluationHint overrideHints; + final ICache backendLevelCache; + final Logger logger = Logger.getLogger(getClass()); - /** - * @since 1.5 - */ - public SearchContext(IBaseIndex baseIndex, IQueryResultProviderAccess resultProviderAccess, QueryEvaluationHint overrideHints) throws ViatraQueryException { //XXX this is a problematic (and in long-term unsupported) solution, see bug 456815 + public SearchContext(IBaseIndex baseIndex, IQueryResultProviderAccess resultProviderAccess, QueryEvaluationHint overrideHints, ICache backendLevelCache) throws ViatraQueryException { this.navigationHelper = ((EMFBaseIndexWrapper)baseIndex).getNavigationHelper(); this.resultProviderAccess = resultProviderAccess; this.overrideHints = overrideHints; + + this.backendLevelCache = backendLevelCache; } public void registerObservedTypes(Set<EClass> classes, Set<EDataType> dataTypes, Set<EStructuralFeature> features) { @@ -119,6 +142,11 @@ public interface ISearchContext{ throw new LocalSearchException("Could not access referenced query: "+reference, e); } } + + @Override + public <T> T accessBackendLevelCache(Object key, Class<? extends T> clazz, IProvider<T> valueProvider) { + return backendLevelCache.getValue(key, clazz, valueProvider); + } } } diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java index c7e7c46cc..0441b7f7b 100644 --- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java +++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchBackend.java @@ -29,6 +29,8 @@ import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext; import org.eclipse.viatra.query.runtime.matchers.planning.QueryProcessingException; import org.eclipse.viatra.query.runtime.matchers.psystem.analysis.QueryAnalyzer; import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; +import org.eclipse.viatra.query.runtime.matchers.util.ICache; +import org.eclipse.viatra.query.runtime.matchers.util.PurgableCache; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.HashBasedTable; @@ -48,7 +50,8 @@ public class LocalSearchBackend implements IQueryBackend { private final Set<ILocalSearchAdapter> adapters = Sets.newHashSet(); // Cache - Table<EDataType, EClass, Set<EAttribute>> eAttributesByTypeForEClass; + private final Table<EDataType, EClass, Set<EAttribute>> eAttributesByTypeForEClass; + private final PurgableCache generalCache; private final Multimap<PQuery, LocalSearchResultProvider> resultProviderCache = ArrayListMultimap.create(); @@ -59,6 +62,7 @@ public class LocalSearchBackend implements IQueryBackend { super(); this.context = context; this.eAttributesByTypeForEClass = HashBasedTable.create(); + this.generalCache = new PurgableCache(); this.planProvider = new CachingPlanProvider(context.getLogger()); } @@ -96,6 +100,7 @@ public class LocalSearchBackend implements IQueryBackend { public void dispose() { eAttributesByTypeForEClass.clear(); resultProviderCache.clear(); + generalCache.purge(); } @Override @@ -163,4 +168,12 @@ public class LocalSearchBackend implements IQueryBackend { return context; } + /** + * Returns the internal cache of the backend + * @since 1.7 + * @noreference This method is not intended to be referenced by clients. + */ + public ICache getCache() { + return generalCache; + } } diff --git a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java index 3ce483ad1..db1b2817a 100644 --- a/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java +++ b/query/plugins/org.eclipse.viatra.query.runtime.localsearch/src/org/eclipse/viatra/query/runtime/localsearch/matcher/integration/LocalSearchResultProvider.java @@ -164,8 +164,9 @@ public class LocalSearchResultProvider implements IQueryResultProvider { this.planProvider = planProvider; this.userHints = userHints; this.runtimeContext = context.getRuntimeContext(); + try { - searchContext = new ISearchContext.SearchContext(engine.getBaseIndex(), resultProviderAccess, userHints); + searchContext = new ISearchContext.SearchContext(engine.getBaseIndex(), resultProviderAccess, userHints, backend.getCache()); } catch (ViatraQueryException e) { throw new QueryProcessingException("Could not create search context for {1}", new String[]{query.getFullyQualifiedName()}, e.getMessage(), query, e); } @@ -273,9 +274,7 @@ public class LocalSearchResultProvider implements IQueryResultProvider { private LocalSearchMatcher initializeMatcher(Object[] parameters) { try { return newLocalSearchMatcher(parameters); - } catch (QueryProcessingException e) { - throw new RuntimeException(e); - } catch (ViatraQueryException e) { + } catch (QueryProcessingException | ViatraQueryException e) { throw new RuntimeException(e); } diff --git a/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/ICache.java b/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/ICache.java new file mode 100644 index 000000000..a35c9f87b --- /dev/null +++ b/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/ICache.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Zoltan Ujhelyi - initial API and implementation + *******************************************************************************/ +package org.eclipse.viatra.query.runtime.matchers.util; + +/** + * A cache is a simple key-value pair that stores calculated values for specific key objects + * + * <p> + * <b>NOTE</b> These caches are not expected to be used outside query backend implementations + * + * @author Zoltan Ujhelyi + * @since 1.7 + * @noreference This interface is not intended to be referenced by clients. + */ +public interface ICache { + + /** + * Return a selected value for the key object. If the value is not available in the cache yet, the given provider is + * called once + */ + <T> T getValue(Object key, Class<? extends T> clazz, IProvider<T> valueProvider); + +}
\ No newline at end of file diff --git a/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/PurgableCache.java b/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/PurgableCache.java new file mode 100644 index 000000000..6073dddb7 --- /dev/null +++ b/query/plugins/org.eclipse.viatra.query.runtime.matchers/src/org/eclipse/viatra/query/runtime/matchers/util/PurgableCache.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Zoltan Ujhelyi - initial API and implementation + *******************************************************************************/ +package org.eclipse.viatra.query.runtime.matchers.util; + +import java.util.HashMap; +import java.util.Map; + +import com.google.common.base.Preconditions; + +/** + * @author Zoltan Ujhelyi + * @since 1.7 + * @noreference This class is not intended to be referenced by clients. + */ +public class PurgableCache implements ICache { + + Map<Object, Object> storage = new HashMap<>(); + + @Override + @SuppressWarnings("unchecked") + public <T> T getValue(Object key, Class<? extends T> clazz, IProvider<T> valueProvider) { + if (storage.containsKey(key)) { + Object value = storage.get(key); + Preconditions.checkState(clazz.isInstance(value), "Cache stores for key %s a value of %s that is incompatible with the requested type %s", key, value, clazz); + return (T) value; + } else { + T value = valueProvider.get(); + storage.put(key, value); + return value; + } + } + + /** + * Removes all values stored in the cache + */ + public void purge() { + storage.clear(); + } +} |
