< 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:105
Uncovered lines:20
Coverable lines:125
Total lines:315
Line coverage:84% (105 of 125)
Covered branches:18
Total branches:28
Branch coverage:64.2% (18 of 28)
Tag:263_26948838820

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(...)50%255.55%
GetEdgeEnumerator()100%1100%
Itinero.Network.Writer.IRoutingNetworkWritable.GetEdgeEnumerator()100%1100%
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(...)50%4100%
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>
 33927    public RoutingNetwork(RouterDb routerDb, int zoom = 14, int maxIslandSize = 1024)
 33928    {
 33929        this.Zoom = zoom;
 33930        this.RouterDb = routerDb;
 31
 33932        IslandManager = new RoutingNetworkIslandManager(maxIslandSize);
 33933        _tiles = new SparseArray<NetworkTile?>(0);
 33934    }
 35
 25036    internal RoutingNetwork(RouterDb routerDb, SparseArray<NetworkTile?> tiles, int zoom, RoutingNetworkIslandManager is
 25037    {
 25038        this.Zoom = zoom;
 25039        this.RouterDb = routerDb;
 25040        IslandManager = islandManager;
 25041        _tiles = tiles;
 25042    }
 43
 44    internal NetworkTile? GetTileForRead(uint localTileId)
 550393645    {
 596857446        if (_tiles.Length <= localTileId) return null;
 47
 48        // get tile, if any.
 503929849        var tile = _tiles[localTileId];
 605558150        if (tile == null) return null;
 51
 52        // check edge type map.
 402301553        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 804602954        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;
 550393662    }
 63
 64    /// <summary>
 65    /// Gets the usage notifier.
 66    /// </summary>
 31100167    public DataUseNotifier UsageNotifier { get; } = new();
 68
 69    internal IEnumerator<uint> GetTileEnumerator()
 4270    {
 4271        using var enumerator = _tiles.GetEnumerator();
 148088372        while (enumerator.MoveNext())
 148086973        {
 148086974            yield return (uint)enumerator.Current.i;
 148084175        }
 1476    }
 77
 78    NetworkTile? IEdgeEnumerable.GetTileForRead(uint localTileId)
 101924579    {
 101924580        return this.GetTileForRead(localTileId);
 101924581    }
 82
 83    /// <summary>
 84    /// Gets the zoom.
 85    /// </summary>
 7816886    public int Zoom { get; }
 87
 88    /// <summary>
 89    /// Gets the routing network.
 90    /// </summary>
 424126891    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)
 2998318102    {
 2998318103        var localTileId = vertex.TileId;
 104
 105        // get tile.
 2998318106        var tile = this.GetTileForRead(localTileId);
 5996636107        if (tile != null) return tile.TryGetVertex(vertex, out longitude, out latitude, out elevation);
 108
 109        // no tile, no vertex.
 0110        longitude = default;
 0111        latitude = default;
 0112        elevation = null;
 0113        return false;
 2998318114    }
 115
 116    /// <summary>
 117    /// Gets an edge enumerator.
 118    /// </summary>
 119    /// <returns>The enumerator.</returns>
 120    public RoutingNetworkEdgeEnumerator GetEdgeEnumerator()
 952603121    {
 952603122        return new RoutingNetworkEdgeEnumerator(this);
 952603123    }
 124
 125    RoutingNetworkEdgeEnumerator IRoutingNetworkWritable.GetEdgeEnumerator()
 12126    {
 12127        return this.GetEdgeEnumerator();
 12128    }
 129
 130    /// <summary>
 131    /// Gets a vertex enumerator.
 132    /// </summary>
 133    /// <returns>The enumerator.</returns>
 134    internal RoutingNetworkVertexEnumerator GetVertexEnumerator()
 42135    {
 42136        return new(this);
 42137    }
 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
 25322        {
 25323            return IslandManager;
 25324        }
 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{
 58910    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()
 24919    {
 24920        lock (_mutatorSync)
 24921        {
 24922            if (_graphMutator != null) throw new InvalidOperationException($"Only one mutable graph is allowed at one ti
 23
 24924            _graphMutator = new RoutingNetworkMutator(this);
 24925            this.RouterDb.SetAsMutable(_graphMutator);
 24926            return _graphMutator;
 27        }
 24928    }
 29
 24930    SparseArray<NetworkTile?> IRoutingNetworkMutable.Tiles => _tiles;
 31
 32    void IRoutingNetworkMutable.ClearMutator()
 24633    {
 24634        _graphMutator = null;
 24635    }
 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{
 58911    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()
 6224    {
 6225        lock (_writeSync)
 6226        {
 6227            if (_writer != null) throw new InvalidOperationException($"Only one writer is allowed at one time." +
 028                                                    $"Check {nameof(this.HasWriter)} for a current writer.");
 29
 6230            _writer = new RoutingNetworkWriter(this);
 6231            return _writer;
 32        }
 6233    }
 34
 35    void IRoutingNetworkWritable.ClearWriter()
 6236    {
 6237        _writer = null;
 6238    }
 39
 40    (NetworkTile tile, Func<IEnumerable<(string key, string value)>, uint> func) IRoutingNetworkWritable.
 41        GetTileForWrite(uint localTileId)
 17142    {
 43        // ensure minimum size.
 17144        _tiles.EnsureMinimumSize(localTileId);
 45
 17146        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 17147        var tile = _tiles[localTileId];
 17148        if (tile != null)
 12649        {
 12650            if (tile.EdgeTypeMapId != edgeTypeMap.id)
 051            {
 052                tile = tile.CloneForEdgeTypeMap(edgeTypeMap);
 053                _tiles[localTileId] = tile;
 054            }
 55            else
 12656            {
 57                // check if there is a mutable graph.
 12658                this.CloneTileIfNeededForMutator(tile);
 12659            }
 60
 12661            return (tile, edgeTypeMap.func);
 62        }
 63
 64        // create a new tile.
 4565        tile = new NetworkTile(this.Zoom, localTileId, edgeTypeMap.id);
 4566        _tiles[localTileId] = tile;
 67
 4568        return (tile, edgeTypeMap.func);
 17169    }
 70
 71    void IRoutingNetworkWritable.SetTile(NetworkTile tile)
 2372    {
 2373        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 2374        if (tile.EdgeTypeMapId != edgeTypeMap.id) throw new ArgumentException("Cannot add an entire tile without a match
 75
 76        // ensure minimum size.
 2377        _tiles.EnsureMinimumSize(tile.TileId);
 78
 79        // set tile if not yet there.
 2380        var existingTile = _tiles[tile.TileId];
 2381        if (existingTile != null) throw new ArgumentException("Cannot overwrite a tile");
 2382        _tiles[tile.TileId] = tile;
 2383    }
 84
 85    private void CloneTileIfNeededForMutator(NetworkTile tile)
 12686    {
 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**
 12697        var mutableGraph = _graphMutator;
 12698        if (mutableGraph != null && !mutableGraph.HasTile(tile.TileId))
 099        {
 0100            mutableGraph.SetTile(tile.Clone());
 0101        }
 126102    }
 103}