< Summary

Class:Itinero.Network.RoutingNetwork
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Islands.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Mutation.cs
/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Writer.cs
Covered lines:98
Uncovered lines:27
Coverable lines:125
Total lines:315
Line coverage:78.4% (98 of 125)
Covered branches:17
Total branches:28
Branch coverage:60.7% (17 of 28)
Tag:224_14471318300

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%1100%
.ctor(...)100%1100%
GetTileForRead(...)100%6100%
get_UsageNotifier()100%1100%
GetTileEnumerator()100%2100%
Itinero.Network.Enumerators.Edges.IEdgeEnumerable.GetTileForRead(...)100%1100%
get_Zoom()100%1100%
get_RouterDb()100%1100%
TryGetVertex(...)100%2100%
GetEdgeEnumerator()100%1100%
Itinero.Network.Writer.IRoutingNetworkWritable.GetEdgeEnumerator()100%10%
GetVertexEnumerator()100%1100%
HasTile(...)0%20%
Itinero.Network.Writer.IRoutingNetworkWritable.get_IslandManager()100%10%
Itinero.Network.Mutation.IRoutingNetworkMutable.get_IslandManager()100%1100%
.ctor(...)100%1100%
GetAsMutable()50%2100%
Itinero.Network.Mutation.IRoutingNetworkMutable.get_Tiles()100%1100%
Itinero.Network.Mutation.IRoutingNetworkMutable.ClearMutator()100%1100%
.ctor(...)100%1100%
get_HasWriter()100%10%
GetWriter()50%287.5%
Itinero.Network.Writer.IRoutingNetworkWritable.ClearWriter()100%1100%
Itinero.Network.Writer.IRoutingNetworkWritable.GetTileForWrite(...)75%478.94%
Itinero.Network.Writer.IRoutingNetworkWritable.SetTile(...)0%40%
CloneTileIfNeededForMutator(...)50%457.14%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using Itinero.Data.Usage;
 4using Itinero.Network.DataStructures;
 5using Itinero.Network.Enumerators.Edges;
 6using Itinero.Network.Enumerators.Vertices;
 7using Itinero.Network.Mutation;
 8using Itinero.Network.Search.Islands;
 9using Itinero.Network.Tiles;
 10using Itinero.Network.Writer;
 11
 12namespace Itinero.Network;
 13
 14/// <summary>
 15/// The routing network.
 16/// </summary>
 17public sealed partial class RoutingNetwork : IEdgeEnumerable, IRoutingNetworkMutable, IRoutingNetworkWritable
 18{
 19    private readonly SparseArray<NetworkTile?> _tiles;
 20
 21    /// <summary>
 22    /// Creates a new routing network.
 23    /// </summary>
 24    /// <param name="routerDb"></param>
 25    /// <param name="zoom"></param>
 26    /// <param name="maxIslandSize"></param>
 17327    public RoutingNetwork(RouterDb routerDb, int zoom = 14, int maxIslandSize = 1024)
 17328    {
 17329        this.Zoom = zoom;
 17330        this.RouterDb = routerDb;
 31
 17332        IslandManager = new RoutingNetworkIslandManager(maxIslandSize);
 17333        _tiles = new SparseArray<NetworkTile?>(0);
 17334    }
 35
 12336    internal RoutingNetwork(RouterDb routerDb, SparseArray<NetworkTile?> tiles, int zoom, RoutingNetworkIslandManager is
 12337    {
 12338        this.Zoom = zoom;
 12339        this.RouterDb = routerDb;
 12340        IslandManager = islandManager;
 12341        _tiles = tiles;
 12342    }
 43
 44    internal NetworkTile? GetTileForRead(uint localTileId)
 73031345    {
 111342046        if (_tiles.Length <= localTileId) return null;
 47
 48        // get tile, if any.
 34720649        var tile = _tiles[localTileId];
 69390250        if (tile == null) return null;
 51
 52        // check edge type map.
 51053        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 101954        if (tile.EdgeTypeMapId == edgeTypeMap.id) return tile;
 55
 56        // tile.EdgeTypeMapId indicates the version of the used edgeTypeMap
 57        // If the id is different, the loaded tile needs updating; e.g. because a cost function has been changed
 158        tile = tile.CloneForEdgeTypeMap(edgeTypeMap);
 159        _tiles[localTileId] = tile;
 60
 161        return tile;
 73031362    }
 63
 64    /// <summary>
 65    /// Gets the usage notifier.
 66    /// </summary>
 50367    public DataUseNotifier UsageNotifier { get; } = new();
 68
 69    internal IEnumerator<uint> GetTileEnumerator()
 1570    {
 1571        using var enumerator = _tiles.GetEnumerator();
 72980272        while (enumerator.MoveNext())
 72979073        {
 72979074            yield return (uint)enumerator.Current.i;
 72978775        }
 1276    }
 77
 78    NetworkTile? IEdgeEnumerable.GetTileForRead(uint localTileId)
 34879    {
 34880        return this.GetTileForRead(localTileId);
 34881    }
 82
 83    /// <summary>
 84    /// Gets the zoom.
 85    /// </summary>
 106886    public int Zoom { get; }
 87
 88    /// <summary>
 89    /// Gets the routing network.
 90    /// </summary>
 155491    public RouterDb RouterDb { get; }
 92
 93    /// <summary>
 94    /// Tries to get the given vertex.
 95    /// </summary>
 96    /// <param name="vertex">The vertex.</param>
 97    /// <param name="longitude">The longitude.</param>
 98    /// <param name="latitude">The latitude.</param>
 99    /// <param name="elevation">The elevation.</param>
 100    /// <returns>The vertex.</returns>
 101    public bool TryGetVertex(VertexId vertex, out double longitude, out double latitude, out float? elevation)
 175102    {
 175103        var localTileId = vertex.TileId;
 104
 105        // get tile.
 175106        var tile = this.GetTileForRead(localTileId);
 324107        if (tile != null) return tile.TryGetVertex(vertex, out longitude, out latitude, out elevation);
 108
 109        // no tile, no vertex.
 26110        longitude = default;
 26111        latitude = default;
 26112        elevation = null;
 26113        return false;
 175114    }
 115
 116    /// <summary>
 117    /// Gets an edge enumerator.
 118    /// </summary>
 119    /// <returns>The enumerator.</returns>
 120    public RoutingNetworkEdgeEnumerator GetEdgeEnumerator()
 365121    {
 365122        return new RoutingNetworkEdgeEnumerator(this);
 365123    }
 124
 125    RoutingNetworkEdgeEnumerator IRoutingNetworkWritable.GetEdgeEnumerator()
 0126    {
 0127        return this.GetEdgeEnumerator();
 0128    }
 129
 130    /// <summary>
 131    /// Gets a vertex enumerator.
 132    /// </summary>
 133    /// <returns>The enumerator.</returns>
 134    internal RoutingNetworkVertexEnumerator GetVertexEnumerator()
 15135    {
 15136        return new(this);
 15137    }
 138
 139    /// <summary>
 140    /// Returns true if this network has the given tile loaded.
 141    /// </summary>
 142    /// <param name="localTileId"></param>
 143    /// <returns></returns>
 144    public bool HasTile(uint localTileId)
 0145    {
 0146        if (localTileId >= _tiles.Length) return false;
 147
 0148        return _tiles[localTileId] != null;
 0149    }
 150}

/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Islands.cs

#LineLine coverage
 1using Itinero.Network.Mutation;
 2using Itinero.Network.Search.Islands;
 3using Itinero.Network.Writer;
 4
 5namespace Itinero.Network;
 6
 7public sealed partial class RoutingNetwork
 8{
 9    internal readonly RoutingNetworkIslandManager IslandManager;
 10
 11    RoutingNetworkIslandManager IRoutingNetworkWritable.IslandManager
 12    {
 13        get
 014        {
 015            return IslandManager;
 016        }
 17    }
 18
 19    RoutingNetworkIslandManager IRoutingNetworkMutable.IslandManager
 20    {
 21        get
 12622        {
 12623            return IslandManager;
 12624        }
 25    }
 26}

/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Mutation.cs

#LineLine coverage
 1using System;
 2using Itinero.Network.DataStructures;
 3using Itinero.Network.Mutation;
 4using Itinero.Network.Tiles;
 5
 6namespace Itinero.Network;
 7
 8public sealed partial class RoutingNetwork
 9{
 29610    private readonly object _mutatorSync = new();
 11    private RoutingNetworkMutator? _graphMutator;
 12
 13    /// <summary>
 14    /// Gets a mutable version of this network.
 15    /// </summary>
 16    /// <returns>The mutable version.</returns>
 17    /// <exception cref="InvalidOperationException"></exception>
 18    public RoutingNetworkMutator GetAsMutable()
 12219    {
 12220        lock (_mutatorSync)
 12221        {
 12222            if (_graphMutator != null) throw new InvalidOperationException($"Only one mutable graph is allowed at one ti
 23
 12224            _graphMutator = new RoutingNetworkMutator(this);
 12225            this.RouterDb.SetAsMutable(_graphMutator);
 12226            return _graphMutator;
 27        }
 12228    }
 29
 12230    SparseArray<NetworkTile?> IRoutingNetworkMutable.Tiles => _tiles;
 31
 32    void IRoutingNetworkMutable.ClearMutator()
 11933    {
 11934        _graphMutator = null;
 11935    }
 36}

/home/runner/work/routing2/routing2/src/Itinero/Network/RoutingNetwork.Writer.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using Itinero.Network.DataStructures;
 4using Itinero.Network.Tiles;
 5using Itinero.Network.Writer;
 6
 7namespace Itinero.Network;
 8
 9public sealed partial class RoutingNetwork
 10{
 29611    private readonly object _writeSync = new();
 12    private RoutingNetworkWriter? _writer;
 13
 14    /// <summary>
 15    /// Returns true if there is already a writer.
 16    /// </summary>
 017    public bool HasWriter => _writer != null;
 18
 19    /// <summary>
 20    /// Gets a writer.
 21    /// </summary>
 22    /// <returns>The writer.</returns>
 23    public RoutingNetworkWriter GetWriter()
 2924    {
 2925        lock (_writeSync)
 2926        {
 2927            if (_writer != null) throw new InvalidOperationException($"Only one writer is allowed at one time." +
 028                                                    $"Check {nameof(this.HasWriter)} for a current writer.");
 29
 2930            _writer = new RoutingNetworkWriter(this);
 2931            return _writer;
 32        }
 2933    }
 34
 35    void IRoutingNetworkWritable.ClearWriter()
 2936    {
 2937        _writer = null;
 2938    }
 39
 40    (NetworkTile tile, Func<IEnumerable<(string key, string value)>, uint> func) IRoutingNetworkWritable.
 41        GetTileForWrite(uint localTileId)
 8242    {
 43        // ensure minimum size.
 8244        _tiles.EnsureMinimumSize(localTileId);
 45
 8246        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 8247        var tile = _tiles[localTileId];
 8248        if (tile != null)
 5049        {
 5050            if (tile.EdgeTypeMapId != edgeTypeMap.id)
 051            {
 052                tile = tile.CloneForEdgeTypeMap(edgeTypeMap);
 053                _tiles[localTileId] = tile;
 054            }
 55            else
 5056            {
 57                // check if there is a mutable graph.
 5058                this.CloneTileIfNeededForMutator(tile);
 5059            }
 60
 5061            return (tile, edgeTypeMap.func);
 62        }
 63
 64        // create a new tile.
 3265        tile = new NetworkTile(this.Zoom, localTileId, edgeTypeMap.id);
 3266        _tiles[localTileId] = tile;
 67
 3268        return (tile, edgeTypeMap.func);
 8269    }
 70
 71    void IRoutingNetworkWritable.SetTile(NetworkTile tile)
 072    {
 073        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 074        if (tile.EdgeTypeMapId != edgeTypeMap.id) throw new ArgumentException("Cannot add an entire tile without a match
 75
 76        // ensure minimum size.
 077        _tiles.EnsureMinimumSize(tile.TileId);
 78
 79        // set tile if not yet there.
 080        var existingTile = _tiles[tile.TileId];
 081        if (existingTile != null) throw new ArgumentException("Cannot overwrite a tile");
 082        _tiles[tile.TileId] = tile;
 083    }
 84
 85    private void CloneTileIfNeededForMutator(NetworkTile tile)
 5086    {
 87        // this is weird right?
 88        //
 89        // the combination these features make this needed:
 90        // - we don't want to clone every tile when we read data in the mutable graph so we use the exiting tiles.
 91        // - a graph can be written to at all times (to lazy load data) but can be mutated at any time too.
 92        //
 93        // this makes it possible the graph is being written to and mutated at the same time.
 94        // we need to check, when writing to a graph, a mutator doesn't have the tile in use or
 95        // data from the write could bleed into the mutator creating an invalid state.
 96        // so **we have to clone tiles before writing to them and give them to the mutator**
 5097        var mutableGraph = _graphMutator;
 5098        if (mutableGraph != null && !mutableGraph.HasTile(tile.TileId))
 099        {
 0100            mutableGraph.SetTile(tile.Clone());
 0101        }
 50102    }
 103}