< 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:251_23667616543

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>
 23227    public RoutingNetwork(RouterDb routerDb, int zoom = 14, int maxIslandSize = 1024)
 23228    {
 23229        this.Zoom = zoom;
 23230        this.RouterDb = routerDb;
 31
 23232        IslandManager = new RoutingNetworkIslandManager(maxIslandSize);
 23233        _tiles = new SparseArray<NetworkTile?>(0);
 23234    }
 35
 17336    internal RoutingNetwork(RouterDb routerDb, SparseArray<NetworkTile?> tiles, int zoom, RoutingNetworkIslandManager is
 17337    {
 17338        this.Zoom = zoom;
 17339        this.RouterDb = routerDb;
 17340        IslandManager = islandManager;
 17341        _tiles = tiles;
 17342    }
 43
 44    internal NetworkTile? GetTileForRead(uint localTileId)
 497262445    {
 543729546        if (_tiles.Length <= localTileId) return null;
 47
 48        // get tile, if any.
 450795349        var tile = _tiles[localTileId];
 490426350        if (tile == null) return null;
 51
 52        // check edge type map.
 411164353        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 822328554        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;
 497262462    }
 63
 64    /// <summary>
 65    /// Gets the usage notifier.
 66    /// </summary>
 30507367    public DataUseNotifier UsageNotifier { get; } = new();
 68
 69    internal IEnumerator<uint> GetTileEnumerator()
 1770    {
 1771        using var enumerator = _tiles.GetEnumerator();
 86087672        while (enumerator.MoveNext())
 86086273        {
 86086274            yield return (uint)enumerator.Current.i;
 86085975        }
 1476    }
 77
 78    NetworkTile? IEdgeEnumerable.GetTileForRead(uint localTileId)
 99782579    {
 99782580        return this.GetTileForRead(localTileId);
 99782581    }
 82
 83    /// <summary>
 84    /// Gets the zoom.
 85    /// </summary>
 8195386    public int Zoom { get; }
 87
 88    /// <summary>
 89    /// Gets the routing network.
 90    /// </summary>
 431408591    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)
 3113922102    {
 3113922103        var localTileId = vertex.TileId;
 104
 105        // get tile.
 3113922106        var tile = this.GetTileForRead(localTileId);
 6227710107        if (tile != null) return tile.TryGetVertex(vertex, out longitude, out latitude, out elevation);
 108
 109        // no tile, no vertex.
 134110        longitude = default;
 134111        latitude = default;
 134112        elevation = null;
 134113        return false;
 3113922114    }
 115
 116    /// <summary>
 117    /// Gets an edge enumerator.
 118    /// </summary>
 119    /// <returns>The enumerator.</returns>
 120    public RoutingNetworkEdgeEnumerator GetEdgeEnumerator()
 931020121    {
 931020122        return new RoutingNetworkEdgeEnumerator(this);
 931020123    }
 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()
 17135    {
 17136        return new(this);
 17137    }
 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
 17622        {
 17623            return IslandManager;
 17624        }
 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{
 40510    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()
 17219    {
 17220        lock (_mutatorSync)
 17221        {
 17222            if (_graphMutator != null) throw new InvalidOperationException($"Only one mutable graph is allowed at one ti
 23
 17224            _graphMutator = new RoutingNetworkMutator(this);
 17225            this.RouterDb.SetAsMutable(_graphMutator);
 17226            return _graphMutator;
 27        }
 17228    }
 29
 17230    SparseArray<NetworkTile?> IRoutingNetworkMutable.Tiles => _tiles;
 31
 32    void IRoutingNetworkMutable.ClearMutator()
 16933    {
 16934        _graphMutator = null;
 16935    }
 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{
 40511    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()
 4124    {
 4125        lock (_writeSync)
 4126        {
 4127            if (_writer != null) throw new InvalidOperationException($"Only one writer is allowed at one time." +
 028                                                    $"Check {nameof(this.HasWriter)} for a current writer.");
 29
 4130            _writer = new RoutingNetworkWriter(this);
 4131            return _writer;
 32        }
 4133    }
 34
 35    void IRoutingNetworkWritable.ClearWriter()
 4136    {
 4137        _writer = null;
 4138    }
 39
 40    (NetworkTile tile, Func<IEnumerable<(string key, string value)>, uint> func) IRoutingNetworkWritable.
 41        GetTileForWrite(uint localTileId)
 13142    {
 43        // ensure minimum size.
 13144        _tiles.EnsureMinimumSize(localTileId);
 45
 13146        var edgeTypeMap = this.RouterDb.GetEdgeTypeMap();
 13147        var tile = _tiles[localTileId];
 13148        if (tile != null)
 8649        {
 8650            if (tile.EdgeTypeMapId != edgeTypeMap.id)
 051            {
 052                tile = tile.CloneForEdgeTypeMap(edgeTypeMap);
 053                _tiles[localTileId] = tile;
 054            }
 55            else
 8656            {
 57                // check if there is a mutable graph.
 8658                this.CloneTileIfNeededForMutator(tile);
 8659            }
 60
 8661            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);
 13169    }
 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)
 8686    {
 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**
 8697        var mutableGraph = _graphMutator;
 8698        if (mutableGraph != null && !mutableGraph.HasTile(tile.TileId))
 099        {
 0100            mutableGraph.SetTile(tile.Clone());
 0101        }
 86102    }
 103}