예제 #1
0
        private List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart> GetSeriesListForExtent(Extent extent, IEnumerable<string> keywords, double tileWidth, double tileHeight,
            DateTime startDate, DateTime endDate, ICollection<WebServiceNode> serviceIDs,
            BusinessObjects.Models.IProgressHandler bgWorker, Func<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart, bool> seriesFilter)
        {
            var servicesToSearch = new List<Tuple<WebServiceNode[], Extent>>();
            if (serviceIDs.Count > 0)
            {
                foreach (var webService in serviceIDs)
                {
                    if (webService.ServiceBoundingBox == null)
                    {
                        servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new[] { webService }, extent));
                        continue;
                    }
                    const double eps = 0.05; //tolerance (0.05 deg) used for services whose bounding box is one point
                    var wsBox = webService.ServiceBoundingBox;
                    var wsExtent = new Extent(wsBox.XMin - eps, wsBox.YMin - eps, wsBox.XMax + eps, wsBox.YMax + eps);
                    if (wsExtent.Intersects(extent))
                    {
                        servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new[] { webService }, wsExtent.Intersection(extent)));
                    }
                }
            }
            else
            {
                servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new WebServiceNode[] { }, extent));
            }

            var servicesWithExtents = new List<Tuple<WebServiceNode[], List<Extent>>>(servicesToSearch.Count);
            int totalTilesCount = 0;
            foreach (var wsInfo in servicesToSearch)
            {
                var tiles = SearchHelper.CreateTiles(wsInfo.Item2, tileWidth, tileHeight);
                servicesWithExtents.Add(new Tuple<WebServiceNode[], List<Extent>>(wsInfo.Item1, tiles));
                totalTilesCount += tiles.Count;
            }

            var fullSeriesList = new List<List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>>();
            long  currentTileIndex = 0;
            int tilesFinished = 0;
            totalSeriesCount = 0;

            bgWorker.ReportProgress(0, "0 Series found");

            var serviceLoopOptions = new ParallelOptions
                {
                        CancellationToken = bgWorker.CancellationToken,
                        MaxDegreeOfParallelism = 2,
                };
            var tileLoopOptions = new ParallelOptions
                {
                        CancellationToken = bgWorker.CancellationToken,
                        // Note: currently HIS Central returns timeout if many requests are sent in the same time.
                        // To test set  MaxDegreeOfParallelism = -1
                        MaxDegreeOfParallelism = 4,
                };

            Parallel.ForEach(servicesWithExtents, serviceLoopOptions, wsInfo =>
            {
                bgWorker.CheckForCancel();
                var ids = wsInfo.Item1.Select(item => item.ServiceID).ToArray();
                var tiles = wsInfo.Item2;

                Parallel.ForEach(tiles, tileLoopOptions, tile =>
                {
                    var current = Interlocked.Add(ref currentTileIndex, 1);
                    bgWorker.CheckForCancel();

                    // Do the web service call
                    var tileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();

                    if (SearchSettings.AndSearch == true)
                    {
                        //CHANGES FOR "AND" SEARCH
                        var totalTileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                        var tileSeriesList2 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                        var tileSeriesList3 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                        var tileSeriesList4 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();

                        SeriesComparer sc = new SeriesComparer();

                        for (int i = 0; i < keywords.Count(); i++)
                        {
                            String keyword = keywords.ElementAt(i);

                            bgWorker.CheckForCancel();
                            var series = GetSeriesCatalogForBox(tile.MinX, tile.MaxX, tile.MinY, tile.MaxY, keyword, startDate, endDate, ids, bgWorker, current, totalTilesCount);
                            totalTileSeriesList.AddRange(series);
                            if (tileSeriesList.Count() == 0)
                            {
                                if (i == 0)
                                {
                                    tileSeriesList.AddRange(series);
                                }
                                else
                                {
                                    break;
                                }
                            }
                            else
                            {

                                tileSeriesList2.AddRange(tileSeriesList.Intersect(series, sc));
                                tileSeriesList.Clear();
                                tileSeriesList.AddRange(tileSeriesList2);
                                tileSeriesList2.Clear();
                            }
                        }

                        for (int i = 0; i < tileSeriesList.Count(); i++)
                        {
                            tileSeriesList4 = totalTileSeriesList.Where(item => (item.SiteName.Equals(tileSeriesList.ElementAt(i).SiteName))).ToList();
                            tileSeriesList3.AddRange(tileSeriesList4);
                        }

                        tileSeriesList = tileSeriesList3;
                    }
                    else
                    {
                        tileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                        foreach (var keyword in keywords)
                        {
                            bgWorker.CheckForCancel();
                            var series = GetSeriesCatalogForBox(tile.MinX, tile.MaxX, tile.MinY, tile.MaxY, keyword, startDate, endDate, ids, bgWorker, current, totalTilesCount);
                            tileSeriesList.AddRange(series);
                        }
                    }
                    //END CHANGES FOR "AND" SEARCH

                    bgWorker.CheckForCancel();
                    if (tileSeriesList.Count > 0)
                    {
                        var filtered = tileSeriesList.Where(seriesFilter).ToList();
                        if (filtered.Count > 0)
                        {
                            lock (_lockGetSeries)
                            {
                                totalSeriesCount += filtered.Count;
                                fullSeriesList.Add(filtered);
                            }
                        }
                    }

                    // Report progress
                    var currentFinished = Interlocked.Add(ref tilesFinished, 1);
                    var message = string.Format("{0} Series found", totalSeriesCount);
                    var percentProgress = (currentFinished * 100) / totalTilesCount;
                    bgWorker.ReportProgress(percentProgress, message);
                });
            });

            // Collect all series into result list
            var result = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>(totalSeriesCount);
            fullSeriesList.ForEach(result.AddRange);
            return result;
        }
예제 #2
0
        private List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart> GetSeriesListForExtent(Extent extent, IEnumerable<string> keywords, double tileWidth, double tileHeight,
            DateTime startDate, DateTime endDate, ICollection<WebServiceNode> serviceIDs,
            //BusinessObjects.Models.IProgressHandler bgWorker,
            Func<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart, bool> seriesFilter)
        {
            var servicesToSearch = new List<Tuple<WebServiceNode[], Extent>>();
            if (serviceIDs.Count > 0)
            {
                foreach (var webService in serviceIDs)
                {
                    if (webService.ServiceBoundingBox == null)
                    {
                        servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new[] { webService }, extent));
                        continue;
                    }
                    const double eps = 0.05; //tolerance (0.05 deg) used for services whose bounding box is one point
                    var wsBox = webService.ServiceBoundingBox;
                    var wsExtent = new Extent(wsBox.XMin - eps, wsBox.YMin - eps, wsBox.XMax + eps, wsBox.YMax + eps);
                    if (wsExtent.Intersects(extent))
                    {
                        servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new[] { webService }, wsExtent.Intersection(extent)));
                    }
                }
            }
            else
            {
                servicesToSearch.Add(new Tuple<WebServiceNode[], Extent>(new WebServiceNode[] { }, extent));
            }

            var servicesWithExtents = new List<Tuple<WebServiceNode[], List<Extent>>>(servicesToSearch.Count);
            int totalTilesCount = 0;
            foreach (var wsInfo in servicesToSearch)
            {
                var tiles = SearchHelper.CreateTiles(wsInfo.Item2, tileWidth, tileHeight);
                servicesWithExtents.Add(new Tuple<WebServiceNode[], List<Extent>>(wsInfo.Item1, tiles));
                totalTilesCount += tiles.Count;
            }

            var fullSeriesList = new List<List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>>();
            long  currentTileIndex = 0;
            int tilesFinished = 0;
            totalSeriesCount = 0;

            //bgWorker.ReportProgress(0, "0 Series found");
            CancellationTokenSource cts = new CancellationTokenSource();

            var serviceLoopOptions = new ParallelOptions
                {
                        //CancellationToken = bgWorker.CancellationToken,
            #if (DEBUG)
                        MaxDegreeOfParallelism = EnvironmentContext.LocalEnvironment() ? 1 : 2
            #else
                        MaxDegreeOfParallelism = 2
            #endif
                };
            var tileLoopOptions = new ParallelOptions
                {
                        //CancellationToken = bgWorker.CancellationToken,
                        CancellationToken = cts.Token,
                        // Note: currently HIS Central returns timeout if many requests are sent in the same time.
                        // To test set  MaxDegreeOfParallelism = -1
            #if (DEBUG)
                        MaxDegreeOfParallelism = EnvironmentContext.LocalEnvironment() ? 1 : 4
            #else
                        MaxDegreeOfParallelism = 4
            #endif
                };
            try
            {
                Parallel.ForEach(servicesWithExtents, serviceLoopOptions, wsInfo =>
                {
                    //bgWorker.CheckForCancel();
                    var ids = wsInfo.Item1.Select(item => item.ServiceID).ToArray();
                    var tiles = wsInfo.Item2;
                    try
                    {
                        Parallel.ForEach(tiles, tileLoopOptions, tile =>
                        {
                            var current = Interlocked.Add(ref currentTileIndex, 1);
                            //bgWorker.CheckForCancel();

                            // Do the web service call
                            var tileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();

                            if (SearchSettings.AndSearch == true)
                            {
                                //CHANGES FOR "AND" SEARCH
                                var totalTileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                                var tileSeriesList2 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                                var tileSeriesList3 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                                var tileSeriesList4 = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();

                                SeriesComparer sc = new SeriesComparer();

                                for (int i = 0; i < keywords.Count(); i++)
                                {
                                    String keyword = keywords.ElementAt(i);

                                    string sampleMedium = String.Empty;
                                    string dataType = String.Empty;
                                    string valueType = string.Empty;

                                    var series = GetSeriesCatalogForBox(tile.MinX, tile.MaxX, tile.MinY, tile.MaxY, sampleMedium, dataType, valueType, keyword, startDate, endDate, ids, current, totalTilesCount);

                                    totalTileSeriesList.AddRange(series);
                                    if (tileSeriesList.Count() == 0)
                                    {
                                        if (i == 0)
                                        {
                                            tileSeriesList.AddRange(series);
                                        }
                                        else
                                        {
                                            break;
                                        }
                                    }
                                    else
                                    {

                                        tileSeriesList2.AddRange(tileSeriesList.Intersect(series, sc));
                                        tileSeriesList.Clear();
                                        tileSeriesList.AddRange(tileSeriesList2);
                                        tileSeriesList2.Clear();
                                    }
                                }

                                for (int i = 0; i < tileSeriesList.Count(); i++)
                                {
                                    tileSeriesList4 = totalTileSeriesList.Where(item => (item.SiteName.Equals(tileSeriesList.ElementAt(i).SiteName))).ToList();
                                    tileSeriesList3.AddRange(tileSeriesList4);
                                }

                                tileSeriesList = tileSeriesList3;
                            }
                            else
                            {
                                tileSeriesList = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>();
                                foreach (var keyword in keywords)
                                {
                                    string sampleMedium = String.Empty;
                                    string dataType = String.Empty;
                                    string valueType = string.Empty;

                                    var series = GetSeriesCatalogForBox(tile.MinX, tile.MaxX, tile.MinY, tile.MaxY, sampleMedium, dataType, valueType, keyword, startDate, endDate, ids, current, totalTilesCount);

                                    tileSeriesList.AddRange(series);
                                }
                            }
                            //END CHANGES FOR "AND" SEARCH

                            //bgWorker.CheckForCancel();
                            if (tileSeriesList.Count > 0)
                            {
                                var filtered = tileSeriesList.Where(seriesFilter).ToList();
                                if (filtered.Count > 0)
                                {
                                    lock (_lockGetSeries)
                                    {
                                        totalSeriesCount += filtered.Count;
                                        fullSeriesList.Add(filtered);
                                    }
                                }
                            }

                            // Report progress
                            var currentFinished = Interlocked.Add(ref tilesFinished, 1);
                            if (totalSeriesCount > maxAllowedTimeseriesReturn)
                            {
                                //Maximum time series exceeded - register a delegate to add an exception to the aggregate exception returned by the task cancellation processing...
                                cts.Token.Register(() => {
                                    string errorMessage = String.Format("Search returned more than {0:#,###0} timeseries and was canceled. Please limit search area and/or Keywords.", maxAllowedTimeseriesReturn);
                                    InvalidOperationException exp = new InvalidOperationException(errorMessage);
                                    throw exp;
                                });

                                cts.Cancel();
                            }
                            var message = string.Format("{0} Series found", totalSeriesCount);
                            var percentProgress = (currentFinished * 100) / totalTilesCount;
                            //bgWorker.ReportProgress(percentProgress, message);

                        });
                    }
                    catch (OperationCanceledException oex)
                    {
                        throw oex;
                    }
                });
                // Collect all series into result list
                var result = new List<BusinessObjects.Models.SeriesDataCartModel.SeriesDataCart>(totalSeriesCount);
                fullSeriesList.ForEach(result.AddRange);
                return result;
            }
            catch (OperationCanceledException oex)
            {
                throw oex;
            }
        }

        #endregion Methods
    }
}