From 9d1922b6d0277dc97e77d17ef68a3130a51b1c45 Mon Sep 17 00:00:00 2001 From: tpylak <tpylak> Date: Tue, 10 Nov 2009 09:07:34 +0000 Subject: [PATCH] LMS-1253 refactoring of the caching mechanism of the custom grid SVN: 13286 --- .../application/MatchingEntitiesPanel.java | 2 +- .../ui/data/DataSetReporterGrid.java | 9 +- .../ui/grid/AbstractBrowserGrid.java | 135 +++++++++++------- .../ui/grid/AbstractEntityBrowserGrid.java | 9 +- .../ui/grid/AbstractSimpleBrowserGrid.java | 2 +- .../client/dto/DefaultResultSetConfig.java | 19 +-- .../web/client/dto/IResultSetConfig.java | 5 +- .../web/client/dto/IResultSetKeyHolder.java | 30 ---- .../web/client/dto/ResultSetFetchConfig.java | 103 +++++++++++++ .../web/client/dto/TableExportCriteria.java | 6 +- .../web/server/AbstractClientService.java | 3 +- .../web/server/CommonClientService.java | 4 +- .../resultset/CachedResultSetManager.java | 92 +++++++++--- .../web/server/resultset/IResultSet.java | 8 +- .../resultset/CachedResultSetManagerTest.java | 17 +-- .../ProteinByExperimentBrowserGrid.java | 2 +- 16 files changed, 306 insertions(+), 140 deletions(-) delete mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetKeyHolder.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSetFetchConfig.java diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java index 5182b853824..2cbfcb33c35 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/MatchingEntitiesPanel.java @@ -136,7 +136,7 @@ final class MatchingEntitiesPanel extends AbstractBrowserGrid<MatchingEntity, Ma @Override protected final void refresh() { - super.refresh(null, null, false); + super.refresh(false); } /** used to make a first data refresh, but can be also called many times */ diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java index d0628574bc6..29e29ae16b6 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/DataSetReporterGrid.java @@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.Co import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableModelReference; import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel; @@ -146,8 +147,10 @@ public class DataSetReporterGrid extends protected void listEntities(DefaultResultSetConfig<String, TableModelRow> resultSetConfig, AbstractAsyncCallback<ResultSet<TableModelRow>> callback) { - // in all cases the data should be taken from the cache, and we know the key already - resultSetConfig.setResultSetKey(resultSetKey); + // In all cases the data should be taken from the cache, and we know the key already. + // The custom columns should be recomputed. + resultSetConfig.setCacheConfig(ResultSetFetchConfig + .createFetchFromCacheAndRecompute(resultSetKey)); viewContext.getService().listDatasetReport(resultSetConfig, callback); } @@ -187,7 +190,7 @@ public class DataSetReporterGrid extends @Override protected void refresh() { - refresh(null, false); + refresh(false); } @Override diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java index beb6ceedc21..a333433393e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractBrowserGrid.java @@ -94,6 +94,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridFilters; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RelatedDataSetCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel; import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition; @@ -195,8 +196,12 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod private CustomColumnsMetadataProvider customColumnsMetadataProvider; - // result set key of the last refreshed data - private String resultSetKey; + // result set key of the last refreshed data + private String resultSetKeyOrNull; + + // not null only if there is a pending request. No new request can be issued until this one is + // finished. + private ResultSetFetchConfig<String> pendingFetchConfigOrNull; private IDataRefreshCallback refreshCallback; @@ -342,13 +347,15 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod { public void execute() { - if (isHardRefreshNeeded() == false) + if (resultSetKeyOrNull != null) { // TODO 2009-09-16, Piotr Buczek: reload of data is not needed in some cases // - when filters with no text are removed, // - when new filters are created, // but when filter with text is removed it is needed. - reloadData(); + ResultSetFetchConfig<String> fetchConfig = + ResultSetFetchConfig.createFetchFromCache(resultSetKeyOrNull); + reloadData(fetchConfig); } } }; @@ -456,30 +463,32 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod private PagingLoader<PagingLoadConfig> createPagingLoader() { - final RpcProxy<PagingLoadConfig, PagingLoadResult<M>> proxy = createDataLoaderProxy(); + final RpcProxy<PagingLoadConfig, PagingLoadResult<M>> proxy = + new RpcProxy<PagingLoadConfig, PagingLoadResult<M>>() + { + @Override + public final void load(final PagingLoadConfig loadConfig, + final AsyncCallback<PagingLoadResult<M>> callback) + { + loadData(loadConfig, callback); + } + }; final BasePagingLoader<PagingLoadConfig, PagingLoadResult<M>> newPagingLoader = new BasePagingLoader<PagingLoadConfig, PagingLoadResult<M>>(proxy); newPagingLoader.setRemoteSort(true); return newPagingLoader; } - private RpcProxy<PagingLoadConfig, PagingLoadResult<M>> createDataLoaderProxy() + private void loadData(final PagingLoadConfig loadConfig, + final AsyncCallback<PagingLoadResult<M>> callback) { - return new RpcProxy<PagingLoadConfig, PagingLoadResult<M>>() - { - @Override - public final void load(final PagingLoadConfig loadConfig, - final AsyncCallback<PagingLoadResult<M>> callback) - { - DefaultResultSetConfig<String, T> resultSetConfig = - createPagingConfig(loadConfig, columnDefinitions, filterToolbar - .getFilters(), resultSetKey, getGridDisplayTypeID()); - debug("create a refresh callback"); - ListEntitiesCallback listCallback = - new ListEntitiesCallback(viewContext, callback, resultSetConfig); - listEntities(resultSetConfig, listCallback); - } - }; + DefaultResultSetConfig<String, T> resultSetConfig = + createPagingConfig(loadConfig, columnDefinitions, filterToolbar.getFilters(), + pendingFetchConfigOrNull, getGridDisplayTypeID()); + debug("create a refresh callback " + pendingFetchConfigOrNull); + ListEntitiesCallback listCallback = + new ListEntitiesCallback(viewContext, callback, resultSetConfig); + listEntities(resultSetConfig, listCallback); } private void debug(String msg) @@ -487,7 +496,8 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod if (DEBUG) { String text = - "[grid: " + getGridDisplayTypeID() + ", cache: " + resultSetKey + "] " + msg; + "[grid: " + getGridDisplayTypeID() + ", cache: " + resultSetKeyOrNull + "] " + + msg; System.out.println(text); } } @@ -513,7 +523,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod private static <T> DefaultResultSetConfig<String, T> createPagingConfig( PagingLoadConfig loadConfig, Set<IColumnDefinition<T>> availableColumns, - GridFilters<T> filters, String resultSetKey, String gridDisplayId) + GridFilters<T> filters, ResultSetFetchConfig<String> cacheConfig, String gridDisplayId) { int limit = loadConfig.getLimit(); int offset = loadConfig.getOffset(); @@ -526,7 +536,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod resultSetConfig.setAvailableColumns(availableColumns); resultSetConfig.setSortInfo(translatedSortInfo); resultSetConfig.setFilters(filters); - resultSetConfig.setResultSetKey(resultSetKey); + resultSetConfig.setCacheConfig(cacheConfig); resultSetConfig.setGridDisplayId(gridDisplayId); return resultSetConfig; } @@ -634,6 +644,7 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod // notify that the refresh is done private void onComplete(boolean wasSuccessful) { + pendingFetchConfigOrNull = null; refreshCallback.postRefresh(wasSuccessful); } @@ -884,9 +895,9 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod * Note that, doing so, the result set associated on the server side will be removed. * </p> */ - protected final void refresh(String headerOrNull, boolean refreshColumnsDefinition) + protected final void refresh(boolean refreshColumnsDefinition) { - refresh(null, headerOrNull, refreshColumnsDefinition); + refresh(null, null, refreshColumnsDefinition); } /** @@ -898,17 +909,27 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod { pagingToolbar.updateDefaultRefreshButton(false); debug("clean cache for refresh"); - disposeCache(); this.refreshCallback = createRefreshCallback(externalRefreshCallbackOrNull); setHeader(headerOrNull); if (columnDefinitions == null || refreshColumnsDefinition) { recreateColumnModelAndRefreshColumnsWithFilters(); } - reloadData(); + reloadData(createDisposeAndRefreshFetchMode()); refreshColumnHeaderWidths(); } + private ResultSetFetchConfig<String> createDisposeAndRefreshFetchMode() + { + if (resultSetKeyOrNull != null) + { + return ResultSetFetchConfig.createClearComputeAndCache(resultSetKeyOrNull); + } else + { + return ResultSetFetchConfig.createComputeAndCache(); + } + } + private void refreshColumnHeaderWidths() { // Workaround for the problem of incorrect column header widths if column header is very @@ -1002,8 +1023,15 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod } // Refreshes the data, does not clear the cache. Does not change the column model. - private void reloadData() + private void reloadData(ResultSetFetchConfig<String> resultSetFetchConfig) { + if (pendingFetchConfigOrNull != null) + { + System.err.println("Cannot reload the data with the mode '" + resultSetFetchConfig + + "', there is an unfinished request already: " + pendingFetchConfigOrNull); + return; + } + pendingFetchConfigOrNull = resultSetFetchConfig; pagingLoader.load(0, PAGE_SIZE); } @@ -1129,22 +1157,16 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod private void saveCacheKey(final String newResultSetKey) { - String oldResultSetKey = resultSetKey; - resultSetKey = newResultSetKey; + resultSetKeyOrNull = newResultSetKey; debug("saving new cache key"); - if (oldResultSetKey != null && oldResultSetKey.equals(newResultSetKey) == false) - { - debug("cleaning old cache " + oldResultSetKey); - removeResultSet(oldResultSetKey); - } } private void disposeCache() { - if (resultSetKey != null) + if (resultSetKeyOrNull != null) { - removeResultSet(resultSetKey); - resultSetKey = null; + removeResultSet(resultSetKeyOrNull); + resultSetKeyOrNull = null; } } @@ -1154,11 +1176,6 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod new VoidAsyncCallback<Void>(viewContext)); } - private boolean isHardRefreshNeeded() - { - return resultSetKey == null; - } - /** Export always deals with data from the previous refresh operation */ private void export() { @@ -1203,8 +1220,9 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod if (customColumnsChanged || filtersChanged) { - debug("refreshing the custom columns or filters"); - refresh(); + debug("refreshing the custom columns or filters in " + + pendingFetchConfigOrNull + " mode"); + reloadData(createRefreshSettingsFetchConfig()); } else { if (filtersChanged) @@ -1220,6 +1238,24 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod filterToolbar.refresh(); } } + + private ResultSetFetchConfig<String> createRefreshSettingsFetchConfig() + { + if (pendingFetchConfigOrNull == null) + { + if (resultSetKeyOrNull == null) + { + return ResultSetFetchConfig.createComputeAndCache(); + } else + { + return ResultSetFetchConfig + .createFetchFromCacheAndRecompute(resultSetKeyOrNull); + } + } else + { + return pendingFetchConfigOrNull; + } + } }; ColumnSettingsDialog.show(viewContext, provider, getGridDisplayTypeID()); } @@ -1241,13 +1277,14 @@ public abstract class AbstractBrowserGrid<T/* Entity */, M extends BaseEntityMod protected final TableExportCriteria<T> createTableExportCriteria() { assert columnDefinitions != null : "refresh before exporting!"; - assert resultSetKey != null : "refresh before exporting, resultSetKey is null!"; + assert resultSetKeyOrNull != null : "refresh before exporting, resultSetKey is null!"; final List<IColumnDefinition<T>> columnDefs = getVisibleColumns(columnDefinitions); SortInfo<T> sortInfo = getGridSortInfo(); final TableExportCriteria<T> exportCriteria = - new TableExportCriteria<T>(resultSetKey, sortInfo, filterToolbar.getFilters(), - columnDefs, columnDefinitions, getGridDisplayTypeID()); + new TableExportCriteria<T>(resultSetKeyOrNull, sortInfo, + filterToolbar.getFilters(), columnDefs, columnDefinitions, + getGridDisplayTypeID()); return exportCriteria; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractEntityBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractEntityBrowserGrid.java index ed188696bd8..d19f4eac158 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractEntityBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractEntityBrowserGrid.java @@ -76,8 +76,6 @@ public abstract class AbstractEntityBrowserGrid<T extends IEntityPropertiesHolde abstract protected ICriteriaProvider<K> getCriteriaProvider(); - private IDataRefreshCallback externalRefreshCallbackOrNull; - // criteria used in the previous refresh operation or null if it has not occurred yet protected K criteria; @@ -147,7 +145,7 @@ public abstract class AbstractEntityBrowserGrid<T extends IEntityPropertiesHolde return; } String newHeader = createHeader(); - super.refresh(externalRefreshCallbackOrNull, newHeader, refreshColumnsNeeded); + super.refresh(null, newHeader, refreshColumnsNeeded); } protected final void refreshColumnsSettingsIfNecessary() @@ -175,11 +173,6 @@ public abstract class AbstractEntityBrowserGrid<T extends IEntityPropertiesHolde return refreshColumnsDefinition; } - protected final void setExternalRefreshCallback(IDataRefreshCallback externalRefreshCallback) - { - this.externalRefreshCallbackOrNull = externalRefreshCallback; - } - @Override protected boolean isRefreshEnabled() { diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java index a9d15418ce5..1377db478d1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/AbstractSimpleBrowserGrid.java @@ -66,7 +66,7 @@ abstract public class AbstractSimpleBrowserGrid<T/* Entity */> extends @Override protected void refresh() { - super.refresh(null, false); + super.refresh(false); } @Override diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java index ec9f3f42871..c3b73e9ec9c 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/DefaultResultSetConfig.java @@ -36,13 +36,7 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS private SortInfo<T> sortInfo = new SortInfo<T>(); - /** - * The result set key. - * <p> - * Can be <code>null</code> if unknown. - * </p> - */ - private K resultSetKeyOrNull; + private ResultSetFetchConfig<K> cacheConfig = ResultSetFetchConfig.createComputeAndCache(); private Set<IColumnDefinition<T>> availableColumns; @@ -71,9 +65,9 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS this.sortInfo = sortInfo; } - public final void setResultSetKey(final K resultSetKey) + public final void setCacheConfig(final ResultSetFetchConfig<K> cacheConfig) { - this.resultSetKeyOrNull = resultSetKey; + this.cacheConfig = cacheConfig; } public GridFilters<T> getFilters() @@ -93,7 +87,7 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS setAvailableColumns(resultSetConfig.getAvailableColumns()); setSortInfo(resultSetConfig.getSortInfo()); setFilters(resultSetConfig.getFilters()); - setResultSetKey(resultSetConfig.getResultSetKey()); + setCacheConfig(resultSetConfig.getCacheConfig()); setGridDisplayId(resultSetConfig.tryGetGridDisplayId()); } @@ -121,10 +115,9 @@ public class DefaultResultSetConfig<K, T> implements IResultSetConfig<K, T>, IsS return sortInfo; } - /** Can be <code>null</code> if unknown. */ - public final K getResultSetKey() + public final ResultSetFetchConfig<K> getCacheConfig() { - return resultSetKeyOrNull; + return cacheConfig; } public void setFilters(GridFilters<T> filters) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java index 0ea906383ca..c6d9c0919e1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetConfig.java @@ -30,10 +30,13 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo; * * @author Christian Ribeaud */ -public interface IResultSetConfig<K, T> extends IResultSetKeyHolder<K> +public interface IResultSetConfig<K, T> { public static final int NO_LIMIT = -1; + /** Instructions how to use the server side cache when computing the results. */ + public ResultSetFetchConfig<K> getCacheConfig(); + /** * The offset for the first record to retrieve. */ diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetKeyHolder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetKeyHolder.java deleted file mode 100644 index 4f17ecb47be..00000000000 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/IResultSetKeyHolder.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2008 ETH Zuerich, CISD - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package ch.systemsx.cisd.openbis.generic.client.web.client.dto; - -/** - * A result set key holder. - * - * @author Christian Ribeaud - */ -public interface IResultSetKeyHolder<K> -{ - /** - * Uniquely identifies a result set on the server side. - */ - public K getResultSetKey(); -} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSetFetchConfig.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSetFetchConfig.java new file mode 100644 index 00000000000..2c0198c6127 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ResultSetFetchConfig.java @@ -0,0 +1,103 @@ +/* + * Copyright 2009 ETH Zuerich, CISD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ch.systemsx.cisd.openbis.generic.client.web.client.dto; + +import com.google.gwt.user.client.rpc.IsSerializable; + +/** + * Describes the way in which cache should be used when computing the result set. + * + * @author Tomasz Pylak + */ +public class ResultSetFetchConfig<K> implements IsSerializable +{ + public enum ResultSetFetchMode implements IsSerializable + { + COMPUTE_AND_CACHE, CLEAR_COMPUTE_AND_CACHE, FETCH_FROM_CACHE, + FETCH_FROM_CACHE_AND_RECOMPUTE + } + + private ResultSetFetchConfig.ResultSetFetchMode mode; + + private K resultSetKeyOrNull; + + /** + * Instruction to compute a new result and to cache it. Should be used only if the result is + * computed for the first time and has not been cached yet. + */ + public static <K> ResultSetFetchConfig<K> createComputeAndCache() + { + return new ResultSetFetchConfig<K>(ResultSetFetchMode.COMPUTE_AND_CACHE, null); + } + + /** + * Instruction to clear the cache at the specified key, recompute the result and cache it again. + */ + public static <K> ResultSetFetchConfig<K> createClearComputeAndCache(K resultSetKey) + { + return new ResultSetFetchConfig<K>(ResultSetFetchMode.CLEAR_COMPUTE_AND_CACHE, resultSetKey); + } + + /** Instruction to fetch the result at the specified key in the cache. */ + public static <K> ResultSetFetchConfig<K> createFetchFromCache(K resultSetKey) + { + return new ResultSetFetchConfig<K>(ResultSetFetchMode.FETCH_FROM_CACHE, resultSetKey); + } + + /** + * Instruction to fetch the result at the specified key in the cache an then recompute the + * custom columns and distinct filter values. + */ + public static <K> ResultSetFetchConfig<K> createFetchFromCacheAndRecompute(K resultSetKey) + { + return new ResultSetFetchConfig<K>(ResultSetFetchMode.FETCH_FROM_CACHE_AND_RECOMPUTE, + resultSetKey); + } + + private ResultSetFetchConfig(ResultSetFetchConfig.ResultSetFetchMode mode, K resultSetKeyOrNull) + { + this.mode = mode; + this.resultSetKeyOrNull = resultSetKeyOrNull; + } + + private ResultSetFetchConfig() + { + } + + public ResultSetFetchConfig.ResultSetFetchMode getMode() + { + return mode; + } + + /** + * If mode is COMPUTE_AND_CACHE, returns null.<br> + * If mode is FETCH_FROM_CACHE, returns a key which uniquely identifies a result set in the + * cache on the server side.<br> + * If mode is CLEAR_CACHE_AND_RECOMPUTE, returns a key to the item in the cache which should be + * removed.<br> + */ + public K tryGetResultSetKey() + { + return resultSetKeyOrNull; + } + + @Override + public String toString() + { + return "(mode = " + mode + ", resultSetKey = " + resultSetKeyOrNull + ")"; + } +} \ No newline at end of file diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java index 30b27797d43..94c2baea853 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/TableExportCriteria.java @@ -30,8 +30,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SortInfo; * * @author Tomasz Pylak */ -public class TableExportCriteria<T/* exported entity */> implements IResultSetKeyHolder<String>, - IsSerializable +public class TableExportCriteria<T/* exported entity */> implements IsSerializable { // a key at which data are stored in the server cache private String resultSetKey; @@ -70,6 +69,9 @@ public class TableExportCriteria<T/* exported entity */> implements IResultSetKe this.gridDisplayId = gridDisplayId; } + /** + * Uniquely identifies a result set on the server side. + */ public String getResultSetKey() { return resultSetKey; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java index e206e46515f..ac505b631c9 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java @@ -35,6 +35,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; @@ -129,7 +130,7 @@ public abstract class AbstractClientService implements IClientService IOriginalDataProvider<T> dataProvider, String resultSetKey) { DefaultResultSetConfig<String, T> criteria = DefaultResultSetConfig.createFetchAll(); - criteria.setResultSetKey(resultSetKey); + criteria.setCacheConfig(ResultSetFetchConfig.createFetchFromCache(resultSetKey)); final IResultSet<String, T> allData = getResultSet(criteria, dataProvider); Set<BasicEntityType> result = new HashSet<BasicEntityType>(); for (T row : allData.getList().extractOriginalObjects()) diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java index eca8c3e1ad2..c34950b848d 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java @@ -56,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListPersonsCriteri import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.RelatedDataSetCriteria; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSet; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetWithEntityTypes; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SearchableEntity; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria; @@ -214,7 +215,8 @@ public final class CommonClientService extends AbstractClientService implements final DefaultResultSetConfig<String, T> criteria = DefaultResultSetConfig.createFetchAll(); criteria.setSortInfo(exportCriteria.getSortInfo()); criteria.setFilters(exportCriteria.getFilters()); - criteria.setResultSetKey(exportCriteria.getResultSetKey()); + criteria.setCacheConfig(ResultSetFetchConfig.createFetchFromCache(exportCriteria + .getResultSetKey())); criteria.setAvailableColumns(exportCriteria.getAvailableColumns()); criteria.setGridDisplayId(exportCriteria.getGridDisplayId()); return criteria; diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java index 9c48e640ea1..f5e39cba1a8 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManager.java @@ -36,11 +36,13 @@ import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ColumnDistinctValues; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CustomFilterInfo; -import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridColumnFilterInfo; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridCustomColumnInfo; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridFilters; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig.ResultSetFetchMode; import ch.systemsx.cisd.openbis.generic.client.web.server.calculator.GridExpressionUtils; import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel; import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition; @@ -317,34 +319,86 @@ public final class CachedResultSetManager<K> implements IResultSetManager<K>, Se { assert resultConfig != null : "Unspecified result configuration"; assert dataProvider != null : "Unspecified data retriever"; - GridRowModels<T> data; - K dataKey = resultConfig.getResultSetKey(); - if (dataKey == null) + ResultSetFetchConfig<K> cacheConfig = resultConfig.getCacheConfig(); + ResultSetFetchMode mode = cacheConfig.getMode(); + debug("getResultSet(cache config = " + cacheConfig + ")"); + + if (mode == ResultSetFetchMode.CLEAR_COMPUTE_AND_CACHE) { - dataKey = resultSetKeyProvider.createKey(); - debug("Unknown result set key: retrieving the data with a new key " + dataKey); + removeResultSet(cacheConfig.tryGetResultSetKey()); + } + if (mode == ResultSetFetchMode.COMPUTE_AND_CACHE + || mode == ResultSetFetchMode.CLEAR_COMPUTE_AND_CACHE) + { + K dataKey = resultSetKeyProvider.createKey(); + debug("retrieving the data with a new key " + dataKey); List<T> rows = dataProvider.getOriginalData(); - data = calculateRowModels(sessionToken, rows, resultConfig); - results.put(dataKey, data); + return calculateResult(sessionToken, resultConfig, dataKey, rows); } else { - debug(String.format("Fetching the result from the specifed result set key '%s'.", - dataKey)); - data = cast(results.get(dataKey)); - if (data == null) + K dataKey = cacheConfig.tryGetResultSetKey(); + GridRowModels<T> data = fetchCachedData(dataKey); + + if (mode == ResultSetFetchMode.FETCH_FROM_CACHE) + { + return filterLimitAndSort(resultConfig, data, dataKey); + } else if (mode == ResultSetFetchMode.FETCH_FROM_CACHE_AND_RECOMPUTE) { - debug(String - .format("Invalid result set key '%s'. This should not happen.", dataKey)); + List<T> rows = extractRows(data); + return calculateResult(sessionToken, resultConfig, dataKey, rows); + } else + { + throw new IllegalStateException("unexpected mode " + mode); } } - assert data != null : "Unspecified data"; - data = filterData(data, resultConfig.getAvailableColumns(), resultConfig.getFilters()); - final int size = data.size(); + } + + private <T> IResultSet<K, T> calculateResult(final String sessionToken, + final IResultSetConfig<K, T> resultConfig, K dataKey, List<T> rows) + { + GridRowModels<T> data = + calculateRowModelsAndSave(rows, sessionToken, resultConfig, dataKey); + return filterLimitAndSort(resultConfig, data, dataKey); + } + + private <T> GridRowModels<T> fetchCachedData(K dataKey) + { + debug(String.format("Fetching the result from the specifed result set key '%s'.", dataKey)); + GridRowModels<T> data = cast(results.get(dataKey)); + assert data != null : String.format("Invalid result set key '%s'. This should not happen.", + dataKey); + return data; + } + + private <T> GridRowModels<T> calculateRowModelsAndSave(List<T> rows, final String sessionToken, + final IResultSetConfig<K, T> resultConfig, K dataKey) + { + GridRowModels<T> data = calculateRowModels(sessionToken, rows, resultConfig); + results.put(dataKey, data); + return data; + } + + private static <T> List<T> extractRows(ArrayList<GridRowModel<T>> rowModels) + { + List<T> result = new ArrayList<T>(); + for (GridRowModel<T> rowModel : rowModels) + { + result.add(rowModel.getOriginalObject()); + } + return result; + } + + private <T> IResultSet<K, T> filterLimitAndSort(final IResultSetConfig<K, T> resultConfig, + GridRowModels<T> data, K dataKey) + { + GridRowModels<T> filteredData = + filterData(data, resultConfig.getAvailableColumns(), resultConfig.getFilters()); + final int size = filteredData.size(); final int offset = getOffset(size, resultConfig.getOffset()); final int limit = getLimit(size, resultConfig.getLimit(), offset); final SortInfo<T> sortInfo = resultConfig.getSortInfo(); - sortData(data, sortInfo); - final GridRowModels<T> list = subList(data, offset, limit); + sortData(filteredData, sortInfo); + final GridRowModels<T> list = subList(filteredData, offset, limit); return new DefaultResultSet<K, T>(dataKey, list, size); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java index bd6668553c3..e6d8355718e 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/IResultSet.java @@ -18,15 +18,19 @@ package ch.systemsx.cisd.openbis.generic.client.web.server.resultset; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig; -import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetKeyHolder; /** * A result set that is returned to the client. * * @author Christian Ribeaud */ -public interface IResultSet<K, T> extends IResultSetKeyHolder<K> +public interface IResultSet<K, T> { + /** + * Uniquely identifies a result set on the server side. + */ + public K getResultSetKey(); + /** * Returns the list produced by a given {@link IResultSetConfig}. */ diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java index 13fa0d97e47..1a2c8e0eab8 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/CachedResultSetManagerTest.java @@ -39,6 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridColumnFilterIn import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridFilters; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.GridRowModels; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.IResultSetConfig; +import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ResultSetFetchConfig; import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CacheManager.TokenBasedResultSetKeyGenerator; import ch.systemsx.cisd.openbis.generic.client.web.server.resultset.CachedResultSetManager.ICustomColumnsProvider; import ch.systemsx.cisd.openbis.generic.client.web.server.util.TSVRendererTest; @@ -192,8 +193,8 @@ public final class CachedResultSetManagerTest context.checking(new Expectations() { { - one(resultSetConfig).getResultSetKey(); - will(returnValue(null)); + one(resultSetConfig).getCacheConfig(); + will(returnValue(ResultSetFetchConfig.createComputeAndCache())); allowing(resultSetConfig).getAvailableColumns(); will(returnValue(null)); @@ -221,8 +222,8 @@ public final class CachedResultSetManagerTest context.checking(new Expectations() { { - one(resultSetConfig).getResultSetKey(); - will(returnValue("1")); + one(resultSetConfig).getCacheConfig(); + will(returnValue(ResultSetFetchConfig.createFetchFromCache("1"))); allowing(resultSetConfig).getAvailableColumns(); will(returnValue(null)); @@ -245,8 +246,8 @@ public final class CachedResultSetManagerTest context.checking(new Expectations() { { - one(resultSetConfig).getResultSetKey(); - will(returnValue(null)); + one(resultSetConfig).getCacheConfig(); + will(returnValue(ResultSetFetchConfig.createComputeAndCache())); allowing(resultSetConfig).getAvailableColumns(); will(returnValue(null)); @@ -308,8 +309,8 @@ public final class CachedResultSetManagerTest assertEquals("1", values.get(1)); } - private static List<GridColumnFilterInfo<String>> createFilterList(IColumnDefinition<String> c1, - IColumnDefinition<String> c2) + private static List<GridColumnFilterInfo<String>> createFilterList( + IColumnDefinition<String> c1, IColumnDefinition<String> c2) { List<GridColumnFilterInfo<String>> result = new ArrayList<GridColumnFilterInfo<String>>(); result.add(new GridColumnFilterInfo<String>(c1, null)); diff --git a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java index c787284116c..13a014286a8 100644 --- a/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java +++ b/rtd_phosphonetx/source/java/ch/systemsx/cisd/openbis/plugin/phosphonetx/client/web/client/application/ProteinByExperimentBrowserGrid.java @@ -110,7 +110,7 @@ class ProteinByExperimentBrowserGrid extends AbstractSimpleBrowserGrid<ProteinIn criteria.setTreatmentTypeCode(treatmentTypeCode); criteria.setAggregateOriginal(aggregateOriginal); abundanceColumnDefinitions = definitions; - refresh(null, true); + refresh(true); } @Override -- GitLab