< Summary

Class:Itinero.IO.Osm.Tiles.DataProvider
Assembly:Itinero.IO.Osm.Tiles
File(s):/home/runner/work/routing2/routing2/src/Itinero.IO.Osm.Tiles/DataProvider.cs
Covered lines:0
Uncovered lines:112
Coverable lines:112
Total lines:189
Line coverage:0% (0 of 112)
Covered branches:0
Total branches:22
Branch coverage:0% (0 of 22)
Tag:224_14471318300

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%10%
.ctor(...)100%10%
Itinero.Data.Usage.IDataUseListener.CloneForNewNetwork(...)100%10%
Itinero.Data.Usage.IDataUseListener.VertexTouched(...)0%80%
Itinero.Data.Usage.IDataUseListener.BoxTouched(...)0%60%
WriteTo(...)0%20%
ReadFrom(...)0%60%

File(s)

/home/runner/work/routing2/routing2/src/Itinero.IO.Osm.Tiles/DataProvider.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.IO;
 3using System.Threading;
 4using System.Threading.Tasks;
 5using Itinero.Data.Usage;
 6using Itinero.IO.Osm.Tiles.Parsers;
 7using Itinero.Network;
 8
 9namespace Itinero.IO.Osm.Tiles;
 10
 11/// <summary>
 12/// A data provider loading routable tiles on demand.
 13/// </summary>
 14internal class DataProvider : IDataUseListener
 15{
 16    private readonly GlobalIdMap _idMap;
 17    private readonly string _baseUrl;
 18    private readonly HashSet<uint> _loadedTiles;
 19    private readonly uint _zoom;
 20
 21    /// <summary>
 22    /// Creates a new data provider.
 23    /// </summary>
 24    /// <param name="routerDb">The router db.</param>
 25    /// <param name="baseUrl">The base url to load tiles from.</param>
 26    /// <param name="zoom">The zoom level.</param>
 027    internal DataProvider(RouterDb routerDb, string baseUrl = TileParser.BaseUrl, uint zoom = 14)
 028    {
 029        _baseUrl = baseUrl;
 030        _zoom = 14;
 31
 032        _loadedTiles = new HashSet<uint>();
 033        _idMap = new GlobalIdMap();
 34
 35        // get notified when a location/area is used.
 036        routerDb.Latest.UsageNotifier.AddListener(this);
 037    }
 38
 039    private DataProvider(RouterDb routerDb, string baseUrl, uint zoom,
 040        HashSet<uint> loadedTiles, GlobalIdMap idMap)
 041    {
 042        _baseUrl = baseUrl;
 043        _zoom = zoom;
 044        _idMap = idMap;
 045        _loadedTiles = loadedTiles;
 46
 47        // get notified when a location/area is used.
 048        routerDb.Latest.UsageNotifier.AddListener(this);
 049    }
 50
 51    IDataUseListener? IDataUseListener.CloneForNewNetwork(RoutingNetwork routingNetwork)
 052    {
 053        return null;
 054    }
 55
 56    Task IDataUseListener.VertexTouched(RoutingNetwork network, VertexId vertexId, CancellationToken cancellationToken)
 057    {
 058        if (_loadedTiles.Contains(vertexId.TileId))
 059        {
 060            return Task.CompletedTask;
 61        }
 62
 063        lock (_loadedTiles)
 064        {
 065            if (_loadedTiles.Contains(vertexId.TileId))
 066            {
 067                return Task.CompletedTask;
 68            }
 69
 70            // download the tile.
 071            var tile = Tile.FromLocalId(vertexId.TileId, (int)_zoom);
 072            var url = _baseUrl + $"/{tile.Zoom}/{tile.X}/{tile.Y}";
 073            using var stream = TileParser.DownloadFunc(url);
 74
 75            // parse the tile.
 076            var parse = stream?.Parse(tile);
 077            if (parse == null)
 078            {
 079                return Task.CompletedTask;
 80            }
 81
 82            // add the data from the tile.
 083            using (var routerDbInstanceWriter = network.GetWriter())
 084            {
 085                routerDbInstanceWriter.AddOsmTile(_idMap, tile, parse);
 086            }
 87
 088            _loadedTiles.Add(vertexId.TileId);
 089        }
 90
 091        return Task.CompletedTask;
 092    }
 93
 94    Task IDataUseListener.BoxTouched(RoutingNetwork network,
 95        ((double longitude, double latitude, float? e) topLeft, (double longitude, double latitude, float? e)
 96            bottomRight) box, CancellationToken cancellationToken)
 097    {
 98        // build the tile range.
 099        var tileRange = new TileRange(box, (int)_zoom);
 100
 0101        Parallel.ForEach(tileRange, (tile) =>
 0102        {
 0103            if (_loadedTiles.Contains(tile.LocalId))
 0104            {
 0105                return;
 0106            }
 0107
 0108            var url = _baseUrl + $"/{tile.Zoom}/{tile.X}/{tile.Y}";
 0109
 0110            using var stream = TileParser.DownloadFunc(url);
 0111
 0112            var parse = stream?.Parse(tile);
 0113            if (parse == null)
 0114            {
 0115                return;
 0116            }
 0117
 0118            lock (_loadedTiles)
 0119            {
 0120                // add the data from the tile.
 0121                using (var routerDbInstanceWriter = network.GetWriter())
 0122                {
 0123                    routerDbInstanceWriter.AddOsmTile(_idMap, tile, parse);
 0124                }
 0125
 0126                // mark tile as loaded.
 0127                _loadedTiles.Add(tile.LocalId);
 0128            }
 0129        });
 0130        return Task.CompletedTask;
 0131    }
 132
 133    internal void WriteTo(Stream stream)
 0134    {
 135        // write version #.
 0136        stream.WriteWithSize($"{nameof(DataProvider)}");
 0137        stream.WriteVarInt32(1);
 138
 139        // write details.
 0140        stream.WriteWithSize(_baseUrl);
 0141        stream.WriteVarUInt32(_zoom);
 142
 143        // write global id map.
 0144        lock (_loadedTiles)
 0145        {
 0146            _idMap.WriteTo(stream);
 147
 148            // write loaded tiles.
 0149            stream.WriteVarInt64(_loadedTiles.Count);
 0150            foreach (var tileId in _loadedTiles)
 0151            {
 0152                stream.WriteVarUInt32(tileId);
 0153            }
 0154        }
 0155    }
 156
 157    internal static DataProvider ReadFrom(Stream stream, RouterDb routerDb)
 0158    {
 159        // read & verify header.
 0160        var header = stream.ReadWithSizeString();
 0161        var version = stream.ReadVarInt32();
 0162        if (header != nameof(DataProvider))
 0163        {
 0164            throw new InvalidDataException($"Cannot read {nameof(DataProvider)}: Header invalid.");
 165        }
 166
 0167        if (version != 1)
 0168        {
 0169            throw new InvalidDataException($"Cannot read {nameof(DataProvider)}: Version # invalid.");
 170        }
 171
 172        // read details.
 0173        var baseUrl = stream.ReadWithSizeString();
 0174        var zoom = stream.ReadVarUInt32();
 175
 176        // write global id map.
 0177        var idMap = GlobalIdMap.ReadFrom(stream);
 178
 179        // read loaded tiles.
 0180        var loadedTileCount = stream.ReadVarInt64();
 0181        var loadedTiles = new HashSet<uint>();
 0182        for (var t = 0; t < loadedTileCount; t++)
 0183        {
 0184            loadedTiles.Add(stream.ReadVarUInt32());
 0185        }
 186
 0187        return new DataProvider(routerDb, baseUrl, zoom, loadedTiles, idMap);
 0188    }
 189}