/** * This method has the ability to load the data via the HTTP and aggregate the data if the {@link * IAggregator} is provided. If the {@link IAggregator} is not provided, the data will be returned * not aggregated. * * <p>This method should be used by all subclasses, because it guards against massive data loading * that can make out of memory exceptions on the UI. * * @param storageIndexQuery Query. * @param aggregator {@link IAggregator} * @return Return results of a query. */ private List<E> loadData(StorageIndexQuery storageIndexQuery, IAggregator<E> aggregator) { List<IStorageDescriptor> descriptors = getIndexingTree().query(storageIndexQuery); // sort the descriptors to optimize the number of read operations Collections.sort( descriptors, new Comparator<IStorageDescriptor>() { @Override public int compare(IStorageDescriptor o1, IStorageDescriptor o2) { int channelCompare = Integer.compare(o1.getChannelId(), o2.getChannelId()); if (channelCompare != 0) { return channelCompare; } else { return Long.compare(o1.getPosition(), o2.getPosition()); } } }); AggregationPerformer<E> aggregationPerformer = null; if (null != aggregator) { aggregationPerformer = new AggregationPerformer<>(aggregator); } List<E> returnList = new ArrayList<>(); int size = 0; int count = 0; List<IStorageDescriptor> limitedDescriptors = new ArrayList<>(); for (IStorageDescriptor storageDescriptor : descriptors) { // increase count, add descriptor size and update current list count++; size += storageDescriptor.getSize(); limitedDescriptors.add(storageDescriptor); // if the size is already to big, or we reached end do query if ((size > MAX_QUERY_SIZE) || (count == descriptors.size())) { // load data and filter with restrictions List<E> allData; if (localStorageData.isFullyDownloaded()) { try { allData = dataRetriever.getDataLocally(localStorageData, descriptors); } catch (SerializationException e) { String msg = "Data in the downloaded storage " + localStorageData + " can not be loaded with this version of the inspectIT. Version of the CMR where storage was created is " + localStorageData.getCmrVersion() + "."; InspectIT.getDefault().createErrorDialog(msg, e, -1); return Collections.emptyList(); } catch (IOException e) { InspectIT.getDefault() .createErrorDialog("Exception occurred trying to load the data.", e, -1); return Collections.emptyList(); } } else { try { allData = dataRetriever.getDataViaHttp( getCmrRepositoryDefinition(), localStorageData, limitedDescriptors); } catch (SerializationException e) { String msg = "Data in the remote storage " + localStorageData + " can not be loaded with this version of the inspectIT. Version of the CMR where storage was created is " + localStorageData.getCmrVersion() + "."; InspectIT.getDefault().createErrorDialog(msg, e, -1); return Collections.emptyList(); } catch (IOException e) { InspectIT.getDefault() .createErrorDialog("Exception occurred trying to load the data.", e, -1); return Collections.emptyList(); } } List<E> passedData = getRestrictionsPassedList(allData, storageIndexQuery); // if we need to aggregate then do so, otherwise just add to result list if (null != aggregationPerformer) { aggregationPerformer.processCollection(passedData); } else { returnList.addAll(passedData); } // reset the size and current list size = 0; limitedDescriptors.clear(); } } // aggregate if needed if (null != aggregator) { returnList = aggregationPerformer.getResultList(); } return returnList; }
/** * This method executes the query in way that it first checks if wanted data is already cached. If * not method has the ability to load the data via the HTTP or locally and aggregate the data if * the {@link IAggregator} is provided. If the {@link IAggregator} is not provided, the data will * be returned not aggregated. * * <p>In addition it will try to cache the results if they are not yet cached. * * <p>This method should be used by all subclasses, because it guards against massive data loading * that can make out of memory exceptions on the UI. * * @param storageIndexQuery Query. * @param aggregator {@link IAggregator} * @param comparator If supplied the final result list will be sorted by this comparator. * @param limit Limit the number of results by given number. Value <code>-1</code> means no limit. * @return Return results of a query. */ protected List<E> executeQuery( StorageIndexQuery storageIndexQuery, IAggregator<E> aggregator, Comparator<? super E> comparator, int limit) { List<E> returnList = null; // check if this can be cached if (storageManager.canBeCached(storageIndexQuery, aggregator)) { int hash = storageManager.getCachedDataHash(storageIndexQuery, aggregator); if (!localStorageData.isFullyDownloaded()) { // check if it s cached on the CMR StorageData storageData = new StorageData(localStorageData); try { returnList = dataRetriever.getCachedDataViaHttp(getCmrRepositoryDefinition(), storageData, hash); } catch (BusinessException | IOException | SerializationException e) { // NOPMD // NOCHK // ignore cause we can still load results in other way } if (null == returnList) { // if not we load data regular way returnList = loadData(storageIndexQuery, aggregator); // and cache it on the CMR if we get something if (CollectionUtils.isNotEmpty(returnList)) { cacheQueryResultOnCmr(getCmrRepositoryDefinition(), storageData, returnList, hash); } } } else { try { returnList = dataRetriever.getCachedDataLocally(localStorageData, hash); } catch (IOException | SerializationException e) { // NOPMD NOCHK // ignore cause we can still load results in other way } if (null == returnList) { // if not we load data regular way returnList = loadData(storageIndexQuery, aggregator); // and cache it locally if we get something if (CollectionUtils.isNotEmpty(returnList)) { cacheQueryResultLocally(localStorageData, returnList, hash); } } } } else { returnList = loadData(storageIndexQuery, aggregator); } // sort if needed if (null != comparator) { Collections.sort(returnList, comparator); } // limit the size if needed if ((limit > -1) && (returnList.size() > limit)) { returnList = returnList.subList(0, limit); } return returnList; }