1.4.6 (memory footprint)
This commit is contained in:
parent
448bb11ad4
commit
56bdf76806
27 changed files with 613 additions and 454 deletions
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.btools</groupId>
|
||||
<artifactId>brouter</artifactId>
|
||||
<version>1.4.4</version>
|
||||
<version>1.4.6</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>brouter-mapaccess</artifactId>
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ public final class NodesCache
|
|||
|
||||
private long cacheSum = 0;
|
||||
private long maxmem;
|
||||
private boolean detailed;
|
||||
|
||||
private boolean garbageCollectionEnabled = false;
|
||||
private boolean ghostCleaningDone = false;
|
||||
|
|
@ -52,7 +53,7 @@ public final class NodesCache
|
|||
return "collecting=" + garbageCollectionEnabled + " noGhosts=" + ghostCleaningDone + " cacheSum=" + cacheSum + " cacheSumClean=" + cacheSumClean + " ghostSum=" + ghostSum + " ghostWakeup=" + ghostWakeup ;
|
||||
}
|
||||
|
||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache )
|
||||
public NodesCache( String segmentDir, OsmNodesMap nodesMap, BExpressionContextWay ctxWay, boolean forceSecondaryData, long maxmem, NodesCache oldCache, boolean detailed )
|
||||
{
|
||||
this.segmentDir = new File( segmentDir );
|
||||
this.nodesMap = nodesMap;
|
||||
|
|
@ -61,6 +62,12 @@ public final class NodesCache
|
|||
this.lookupMinorVersion = ctxWay.meta.lookupMinorVersion;
|
||||
this.forceSecondaryData = forceSecondaryData;
|
||||
this.maxmem = maxmem;
|
||||
this.detailed = detailed;
|
||||
|
||||
if ( ctxWay != null )
|
||||
{
|
||||
ctxWay.setDecodeForbidden( detailed );
|
||||
}
|
||||
|
||||
first_file_access_failed = false;
|
||||
first_file_access_name = null;
|
||||
|
|
@ -74,17 +81,24 @@ public final class NodesCache
|
|||
dataBuffers = oldCache.dataBuffers;
|
||||
secondarySegmentsDir = oldCache.secondarySegmentsDir;
|
||||
|
||||
// re-use old, virgin caches
|
||||
fileRows = oldCache.fileRows;
|
||||
for ( OsmFile[] fileRow : fileRows )
|
||||
// re-use old, virgin caches (if same detail-mode)
|
||||
if ( oldCache.detailed == detailed)
|
||||
{
|
||||
if ( fileRow == null )
|
||||
continue;
|
||||
for ( OsmFile osmf : fileRow )
|
||||
fileRows = oldCache.fileRows;
|
||||
for ( OsmFile[] fileRow : fileRows )
|
||||
{
|
||||
cacheSum += osmf.setGhostState();
|
||||
if ( fileRow == null )
|
||||
continue;
|
||||
for ( OsmFile osmf : fileRow )
|
||||
{
|
||||
cacheSum += osmf.setGhostState();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileRows = new OsmFile[180][];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -113,7 +127,7 @@ public final class NodesCache
|
|||
// clean all ghosts and enable garbage collection
|
||||
private void checkEnableCacheCleaning()
|
||||
{
|
||||
if ( cacheSum < maxmem || ghostCleaningDone )
|
||||
if ( cacheSum < maxmem )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -127,7 +141,7 @@ public final class NodesCache
|
|||
}
|
||||
for ( OsmFile osmf : fileRow )
|
||||
{
|
||||
if ( garbageCollectionEnabled )
|
||||
if ( garbageCollectionEnabled && !ghostCleaningDone )
|
||||
{
|
||||
cacheSum -= osmf.cleanGhosts();
|
||||
}
|
||||
|
|
@ -141,6 +155,7 @@ public final class NodesCache
|
|||
if ( garbageCollectionEnabled )
|
||||
{
|
||||
ghostCleaningDone = true;
|
||||
maxmem *= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,36 +10,168 @@ package btools.mapaccess;
|
|||
public class OsmLink
|
||||
{
|
||||
/**
|
||||
* The description bitmap is mainly the way description
|
||||
* used to calculate the costfactor
|
||||
* The description bitmap contains the waytags (valid for both directions)
|
||||
*/
|
||||
public byte[] descriptionBitmap;
|
||||
|
||||
public OsmNode targetNode;
|
||||
|
||||
public OsmLink next;
|
||||
|
||||
public OsmLinkHolder firstlinkholder = null;
|
||||
|
||||
/**
|
||||
* The geometry contains intermediate nodes, null for none (valid for both directions)
|
||||
*/
|
||||
public byte[] geometry;
|
||||
|
||||
public boolean counterLinkWritten;
|
||||
// a link logically knows only its target, but for the reverse link, source and target are swapped
|
||||
protected OsmNode n1;
|
||||
protected OsmNode n2;
|
||||
|
||||
public byte state;
|
||||
// same for the next-link-for-node pointer: previous applies to the reverse link
|
||||
protected OsmLink previous;
|
||||
protected OsmLink next;
|
||||
|
||||
public void setGeometry( byte[] geometry )
|
||||
private OsmLinkHolder reverselinkholder = null;
|
||||
private OsmLinkHolder firstlinkholder = null;
|
||||
|
||||
protected OsmLink()
|
||||
{
|
||||
this.geometry = geometry;
|
||||
}
|
||||
|
||||
final public void addLinkHolder( OsmLinkHolder holder )
|
||||
{
|
||||
if ( firstlinkholder != null ) { holder.setNextForLink( firstlinkholder ); }
|
||||
firstlinkholder = holder;
|
||||
}
|
||||
public OsmLink( OsmNode source, OsmNode target )
|
||||
{
|
||||
n1 = source;
|
||||
n2 = target;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
/**
|
||||
* Get the relevant target-node for the given source
|
||||
*/
|
||||
public final OsmNode getTarget( OsmNode source )
|
||||
{
|
||||
return n2 != source && n2 != null ? n2 : n1;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return n2;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return n1;
|
||||
}
|
||||
else
|
||||
{
|
||||
new Throwable( "ups" ).printStackTrace();
|
||||
throw new IllegalArgumentException( "internal error: getTarget: unknown source; " + source + " n1=" + n1 + " n2=" + n2 );
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the relevant next-pointer for the given source
|
||||
*/
|
||||
public final OsmLink getNext( OsmNode source )
|
||||
{
|
||||
return n2 != source && n2 != null ? next : previous;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return next;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: gextNext: unknown source" );
|
||||
} */
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this link for the given direction
|
||||
*/
|
||||
protected final OsmLink clear( OsmNode source )
|
||||
{
|
||||
OsmLink n;
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
n = next;
|
||||
next = null;
|
||||
n2 = null;
|
||||
firstlinkholder = null;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
n = previous;
|
||||
previous = null;
|
||||
n1 = null;
|
||||
reverselinkholder = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: setNext: unknown source" );
|
||||
}
|
||||
if ( n1 == null && n2 == null )
|
||||
{
|
||||
descriptionBitmap = null;
|
||||
geometry = null;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
public final void setFirstLinkHolder( OsmLinkHolder holder, OsmNode source )
|
||||
{
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
firstlinkholder = holder;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
reverselinkholder = holder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: setFirstLinkHolder: unknown source" );
|
||||
}
|
||||
}
|
||||
|
||||
public final OsmLinkHolder getFirstLinkHolder( OsmNode source )
|
||||
{
|
||||
if ( n2 != null && n2 != source )
|
||||
{
|
||||
return firstlinkholder;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return reverselinkholder;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: getFirstLinkHolder: unknown source" );
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isReverse( OsmNode source )
|
||||
{
|
||||
return n1 != source && n1 != null;
|
||||
/* if ( n2 != null && n2 != source )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if ( n1 != null && n1 != source )
|
||||
{
|
||||
return "Link(target=" + targetNode.getIdFromPos() + " counterLinkWritten=" + counterLinkWritten + " state=" + state + ")";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "internal error: isReverse: unknown source" );
|
||||
} */
|
||||
}
|
||||
|
||||
public final boolean isBidirectional()
|
||||
{
|
||||
return n1 != null && n2 != null;
|
||||
}
|
||||
|
||||
public final void addLinkHolder( OsmLinkHolder holder, OsmNode source )
|
||||
{
|
||||
OsmLinkHolder firstHolder = getFirstLinkHolder( source );
|
||||
if ( firstHolder != null ) { holder.setNextForLink( firstHolder ); }
|
||||
setFirstLinkHolder( holder, source );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,33 @@ import btools.expressions.BExpressionContextWay;
|
|||
import btools.util.ByteArrayUnifier;
|
||||
import btools.util.IByteArrayUnifier;
|
||||
|
||||
public class OsmNode implements OsmPos
|
||||
public class OsmNode extends OsmLink implements OsmPos
|
||||
{
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
/**
|
||||
* The node-tags, if any
|
||||
*/
|
||||
public byte[] nodeDescription;
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
|
@ -29,22 +54,6 @@ public class OsmNode implements OsmPos
|
|||
ilat = (int) ( id & 0xffffffff );
|
||||
}
|
||||
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
public byte[] nodeDescription;
|
||||
|
||||
// interface OsmPos
|
||||
public final int getILat()
|
||||
|
|
@ -67,58 +76,28 @@ public class OsmNode implements OsmPos
|
|||
return selev / 4.;
|
||||
}
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
// preliminry in forward order to avoid regressions
|
||||
public final void addLink( OsmLink link )
|
||||
private void addLink( OsmLink link, boolean isReverse, OsmNode tn )
|
||||
{
|
||||
if ( firstlink == null )
|
||||
if ( isReverse )
|
||||
{
|
||||
link.n1 = tn;
|
||||
link.n2 = this;
|
||||
link.next = tn.firstlink;
|
||||
link.previous = firstlink;
|
||||
tn.firstlink = link;
|
||||
firstlink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink l = firstlink;
|
||||
while (l.next != null)
|
||||
l = l.next;
|
||||
l.next = link;
|
||||
link.n1 = this;
|
||||
link.n2 = tn;
|
||||
link.next = firstlink;
|
||||
link.previous = tn.firstlink;
|
||||
tn.firstlink = link;
|
||||
firstlink = link;
|
||||
}
|
||||
}
|
||||
|
||||
private OsmLink getCompatibleLink( int ilon, int ilat, boolean counterLinkWritten, int state )
|
||||
{
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( counterLinkWritten == l.counterLinkWritten && l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
// second try ignoring counterLinkWritten
|
||||
// (border links are written in both directions)
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = ( ilat - 90000000 ) * 0.00000001234134;
|
||||
|
|
@ -154,6 +133,8 @@ public class OsmNode implements OsmPos
|
|||
selev = mc.readShort();
|
||||
int nodeDescSize = mc.readVarLengthUnsigned();
|
||||
nodeDescription = nodeDescSize == 0 ? null : mc.readUnified( nodeDescSize, abUnifier );
|
||||
|
||||
OsmLink link0 = firstlink;
|
||||
|
||||
while (mc.hasMoreData())
|
||||
{
|
||||
|
|
@ -176,47 +157,42 @@ public class OsmNode implements OsmPos
|
|||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
// first check the known links for that target
|
||||
OsmLink link = getCompatibleLink( linklon, linklat, isReverse, 2 );
|
||||
if ( link == null ) // .. not found, then check the hollow nodes
|
||||
OsmNode tn = null; // find the target node
|
||||
OsmLink link = null;
|
||||
|
||||
// ...in our known links
|
||||
for ( OsmLink l = link0; l != null; l = l.getNext( this ) )
|
||||
{
|
||||
OsmNode tn = hollowNodes.get( linklon, linklat ); // target node
|
||||
OsmNode t = l.getTarget( this );
|
||||
if ( t.ilon == linklon && t.ilat == linklat )
|
||||
{
|
||||
tn = t;
|
||||
if ( isReverse || ( l.descriptionBitmap == null && !l.isReverse( this ) ) )
|
||||
{
|
||||
link = l; // the correct one that needs our data
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( tn == null ) // .. not found, then check the hollow nodes
|
||||
{
|
||||
tn = hollowNodes.get( linklon, linklat ); // target node
|
||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
||||
{
|
||||
tn = new OsmNode( linklon, linklat );
|
||||
tn.setHollow();
|
||||
hollowNodes.put( tn );
|
||||
addLink( link = tn, isReverse, tn ); // technical inheritance: link instance in node
|
||||
}
|
||||
link = new OsmLink();
|
||||
link.targetNode = tn;
|
||||
link.counterLinkWritten = isReverse;
|
||||
link.state = 1;
|
||||
addLink( link );
|
||||
}
|
||||
|
||||
// now we have a link with a target node -> get the reverse link
|
||||
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !isReverse, 1 );
|
||||
if ( rlink == null ) // .. not found, create it
|
||||
if ( link == null )
|
||||
{
|
||||
rlink = new OsmLink();
|
||||
rlink.targetNode = this;
|
||||
rlink.counterLinkWritten = !isReverse;
|
||||
rlink.state = 2;
|
||||
link.targetNode.addLink( rlink );
|
||||
addLink( link = new OsmLink(), isReverse, tn );
|
||||
}
|
||||
|
||||
if ( !isReverse )
|
||||
{
|
||||
// we have the data for that link, so fill both the link ..
|
||||
link.descriptionBitmap = description;
|
||||
link.setGeometry( geometry );
|
||||
|
||||
// .. and the reverse
|
||||
if ( rlink.counterLinkWritten )
|
||||
{
|
||||
rlink.descriptionBitmap = description;
|
||||
rlink.setGeometry( geometry );
|
||||
}
|
||||
link.geometry = geometry;
|
||||
}
|
||||
}
|
||||
hollowNodes.remove( this );
|
||||
|
|
@ -240,21 +216,41 @@ public class OsmNode implements OsmPos
|
|||
|
||||
public final void unlinkLink( OsmLink link )
|
||||
{
|
||||
OsmLink n = link.clear( this );
|
||||
|
||||
if ( link == firstlink )
|
||||
{
|
||||
firstlink = link.next;
|
||||
firstlink = n;
|
||||
return;
|
||||
}
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
OsmLink l = firstlink;
|
||||
while( l != null )
|
||||
{
|
||||
if ( l.next == link )
|
||||
// if ( l.isReverse( this ) )
|
||||
if ( l.n1 != this && l.n1 != null ) // isReverse inline
|
||||
{
|
||||
l.next = link.next;
|
||||
return;
|
||||
OsmLink nl = l.previous;
|
||||
if ( nl == link )
|
||||
{
|
||||
l.previous = n;
|
||||
return;
|
||||
}
|
||||
l = nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink nl = l.next;
|
||||
if ( nl == link )
|
||||
{
|
||||
l.next = n;
|
||||
return;
|
||||
}
|
||||
l = nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final boolean equals( Object o )
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue