removed some old stuff, added profiler, minor performance tuning

This commit is contained in:
Arndt 2016-08-20 18:53:50 +02:00
parent 42e9ddbdd1
commit f70dd3c3ac
22 changed files with 234 additions and 802 deletions

View file

@ -1,99 +0,0 @@
package btools.codec;
import btools.util.ByteDataWriter;
/**
* MicroCache1 is the old data format as of brouter 1.1 that does not allow to
* filter out unaccessable nodes at the beginning of the cache pipeline
*
* Kept for backward compatibility
*/
public final class MicroCache1 extends MicroCache
{
private int lonIdxBase;
private int latIdxBase;
public MicroCache1( int size, byte[] databuffer, int lonIdx80, int latIdx80 ) throws Exception
{
super( databuffer ); // sets ab=databuffer, aboffset=0
faid = new int[size];
fapos = new int[size];
this.size = 0;
lonIdxBase = ( lonIdx80 / 5 ) * 62500 + 31250;
latIdxBase = ( latIdx80 / 5 ) * 62500 + 31250;
}
public MicroCache1( byte[] databuffer, int lonIdx80, int latIdx80 ) throws Exception
{
super( databuffer ); // sets ab=databuffer, aboffset=0
lonIdxBase = ( lonIdx80 / 5 ) * 62500 + 31250;
latIdxBase = ( latIdx80 / 5 ) * 62500 + 31250;
size = readInt();
// get net size
int nbytes = 0;
for ( int i = 0; i < size; i++ )
{
aboffset += 4;
int bodySize = readVarLengthUnsigned();
aboffset += bodySize;
nbytes += bodySize;
}
// new array with only net data
byte[] nab = new byte[nbytes];
aboffset = 4;
int noffset = 0;
faid = new int[size];
fapos = new int[size];
for ( int i = 0; i < size; i++ )
{
faid[i] = readInt() ^ 0x8000; // flip lat-sign for correct ordering
int bodySize = readVarLengthUnsigned();
System.arraycopy( ab, aboffset, nab, noffset, bodySize );
aboffset += bodySize;
noffset += bodySize;
fapos[i] = noffset;
}
ab = nab;
aboffset = noffset;
init( size );
}
@Override
public long expandId( int id32 )
{
int lon32 = lonIdxBase + (short) ( id32 >> 16 );
int lat32 = latIdxBase + (short) ( ( id32 & 0xffff ) ^ 0x8000 );
return ( (long) lon32 ) << 32 | lat32;
}
@Override
public int shrinkId( long id64 )
{
int lon32 = (int) ( id64 >> 32 );
int lat32 = (int) ( id64 & 0xffffffff );
return ( lon32 - lonIdxBase ) << 16 | ( ( ( lat32 - latIdxBase ) & 0xffff ) ^ 0x8000 );
}
@Override
public int encodeMicroCache( byte[] buffer )
{
ByteDataWriter dos = new ByteDataWriter( buffer );
dos.writeInt( size );
for ( int n = 0; n < size; n++ )
{
dos.writeInt( faid[n] ^ 0x8000 );
int start = n > 0 ? fapos[n - 1] : 0;
int end = fapos[n];
int len = end - start;
dos.writeVarLengthUnsigned( len );
dos.write( ab, start, len );
}
return dos.size();
}
}

View file

@ -108,10 +108,11 @@ final class OsmPath implements OsmLinkHolder
private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc ) private void addAddionalPenalty(OsmTrack refTrack, boolean detailMode, OsmPath origin, OsmLink link, RoutingContext rc )
{ {
if ( link.descriptionBitmap == null ) throw new IllegalArgumentException( "null description for: " + link ); byte[] description = link.descriptionBitmap;
if ( description == null ) throw new IllegalArgumentException( "null description for: " + link );
boolean recordTransferNodes = detailMode || rc.countTraffic; boolean recordTransferNodes = detailMode || rc.countTraffic;
boolean recordMessageData = detailMode; boolean recordMessageData = detailMode;
rc.nogomatch = false; rc.nogomatch = false;
@ -126,7 +127,7 @@ final class OsmPath implements OsmLinkHolder
int linkdisttotal = 0; int linkdisttotal = 0;
MessageData msgData = new MessageData(); MessageData msgData = recordMessageData ? new MessageData() : null;
OsmTransferNode transferNode = link.decodeFirsttransfer( p1 ); OsmTransferNode transferNode = link.decodeFirsttransfer( p1 );
OsmNode targetNode = link.targetNode; OsmNode targetNode = link.targetNode;
@ -138,27 +139,21 @@ final class OsmPath implements OsmLinkHolder
int lon2; int lon2;
int lat2; int lat2;
short ele2; short ele2;
byte[] description;
if ( transferNode == null ) if ( transferNode == null )
{ {
lon2 = targetNode.ilon; lon2 = targetNode.ilon;
lat2 = targetNode.ilat; lat2 = targetNode.ilat;
ele2 = targetNode.selev; ele2 = targetNode.selev;
description = link.descriptionBitmap;
if ( description == null ) throw new IllegalArgumentException( "null description for class: " + link.getClass() );
} }
else else
{ {
lon2 = transferNode.ilon; lon2 = transferNode.ilon;
lat2 = transferNode.ilat; lat2 = transferNode.ilat;
ele2 = transferNode.selev; ele2 = transferNode.selev;
description = transferNode.descriptionBitmap;
if ( description == null ) throw new IllegalArgumentException( "null description for class: " + transferNode.getClass() + "/" + link.getClass() + " counterlinkwritten=" + link.counterLinkWritten );
} }
rc.messageHandler.setCurrentPos( lon2, lat2 ); boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description );
boolean sameData = rc.expctxWay.evaluate( rc.inverseDirection ^ link.counterLinkWritten, description, rc.messageHandler );
// if way description changed, store message // if way description changed, store message
if ( recordMessageData && msgData.wayKeyValues != null ) if ( recordMessageData && msgData.wayKeyValues != null )
@ -198,7 +193,10 @@ final class OsmPath implements OsmLinkHolder
} }
} }
msgData.linkdist += dist; if ( recordMessageData )
{
msgData.linkdist += dist;
}
linkdisttotal += dist; linkdisttotal += dist;
boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f; boolean isTrafficBackbone = cost == 0 && rc.expctxWay.getIsTrafficBackbone() > 0.f;
@ -210,9 +208,9 @@ final class OsmPath implements OsmLinkHolder
double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); double cos = rc.calcCosAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty int turncost = (int)(cos * rc.expctxWay.getTurncost() + 0.2 ); // e.g. turncost=90 -> 90 degree = 90m penalty
cost += turncost; cost += turncost;
msgData.linkturncost += turncost;
if ( recordMessageData ) if ( recordMessageData )
{ {
msgData.linkturncost += turncost;
msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 ); msgData.turnangle = (float)rc.calcAngle( lon0, lat0, lon1, lat1, lon2, lat2 );
} }
} }
@ -250,7 +248,10 @@ final class OsmPath implements OsmLinkHolder
{ {
int elevationCost = reduce/rc.downhillcostdiv; int elevationCost = reduce/rc.downhillcostdiv;
cost += elevationCost; cost += elevationCost;
msgData.linkelevationcost += elevationCost; if ( recordMessageData )
{
msgData.linkelevationcost += elevationCost;
}
} }
} }
else if ( ehbd < 0 ) else if ( ehbd < 0 )
@ -280,7 +281,10 @@ final class OsmPath implements OsmLinkHolder
{ {
int elevationCost = reduce/rc.uphillcostdiv; int elevationCost = reduce/rc.uphillcostdiv;
cost += elevationCost; cost += elevationCost;
msgData.linkelevationcost += elevationCost; if ( recordMessageData )
{
msgData.linkelevationcost += elevationCost;
}
} }
} }
else if ( ehbu < 0 ) else if ( ehbu < 0 )
@ -313,6 +317,7 @@ final class OsmPath implements OsmLinkHolder
cost += waycost; cost += waycost;
// calculate traffic // calculate traffic
if ( rc.countTraffic )
{ {
int minDist = (int)rc.trafficSourceMinDist; int minDist = (int)rc.trafficSourceMinDist;
int cost2 = cost < minDist ? minDist : cost; int cost2 = cost < minDist ? minDist : cost;
@ -330,7 +335,10 @@ final class OsmPath implements OsmLinkHolder
lastClassifier = newClassifier; lastClassifier = newClassifier;
float initialcost = rc.expctxWay.getInitialcost(); float initialcost = rc.expctxWay.getInitialcost();
int iicost = (int)initialcost; int iicost = (int)initialcost;
msgData.linkinitcost += iicost; if ( recordMessageData )
{
msgData.linkinitcost += iicost;
}
cost += iicost; cost += iicost;
} }
@ -402,8 +410,7 @@ final class OsmPath implements OsmLinkHolder
if ( targetNode.nodeDescription != null ) if ( targetNode.nodeDescription != null )
{ {
boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.; boolean nodeAccessGranted = rc.expctxWay.getNodeAccessGranted() != 0.;
rc.messageHandler.setCurrentPos( targetNode.ilon, targetNode.ilat ); rc.expctxNode.evaluate( nodeAccessGranted , targetNode.nodeDescription );
rc.expctxNode.evaluate( nodeAccessGranted , targetNode.nodeDescription, rc.messageHandler );
float initialcost = rc.expctxNode.getInitialcost(); float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. ) if ( initialcost >= 1000000. )
{ {
@ -411,12 +418,12 @@ final class OsmPath implements OsmLinkHolder
return; return;
} }
int iicost = (int)initialcost; int iicost = (int)initialcost;
msgData.linknodecost += iicost;
cost += iicost; cost += iicost;
if ( recordMessageData ) if ( recordMessageData )
{ {
msgData.linknodecost += iicost;
msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription ); msgData.nodeKeyValues = rc.expctxNode.getKeyValueDescription( nodeAccessGranted, targetNode.nodeDescription );
} }
} }

View file

@ -111,8 +111,6 @@ public final class RoutingContext implements DistanceChecker
turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f; turnInstructionRoundabouts = expctxGlobal.getVariableValue( "turnInstructionRoundabouts", 1.f ) != 0.f;
} }
public RoutingMessageHandler messageHandler = new RoutingMessageHandler();
public List<OsmNodeNamed> nogopoints = null; public List<OsmNodeNamed> nogopoints = null;
private List<OsmNodeNamed> keepnogopoints = null; private List<OsmNodeNamed> keepnogopoints = null;
@ -222,10 +220,11 @@ public final class RoutingContext implements DistanceChecker
shortestmatch = false; shortestmatch = false;
if ( d > 0. && nogopoints != null ) if ( nogopoints != null && !nogopoints.isEmpty() && d > 0. )
{ {
for( OsmNodeNamed nogo : nogopoints ) for( int ngidx = 0; ngidx < nogopoints.size(); ngidx++ )
{ {
OsmNodeNamed nogo = nogopoints.get(ngidx);
double x1 = (lon1 - nogo.ilon) * coslat6; double x1 = (lon1 - nogo.ilon) * coslat6;
double y1 = (lat1 - nogo.ilat) * 0.000001; double y1 = (lat1 - nogo.ilat) * 0.000001;
double x2 = (lon2 - nogo.ilon) * coslat6; double x2 = (lon2 - nogo.ilon) * coslat6;

View file

@ -16,6 +16,7 @@ import btools.mapaccess.OsmLinkHolder;
import btools.mapaccess.OsmNode; import btools.mapaccess.OsmNode;
import btools.mapaccess.OsmNodesMap; import btools.mapaccess.OsmNodesMap;
import btools.util.SortedHeap; import btools.util.SortedHeap;
import btools.util.StackSampler;
public class RoutingEngine extends Thread public class RoutingEngine extends Thread
{ {
@ -43,6 +44,7 @@ public class RoutingEngine extends Thread
private String logfileBase; private String logfileBase;
private boolean infoLogEnabled; private boolean infoLogEnabled;
private Writer infoLogWriter; private Writer infoLogWriter;
private StackSampler stackSampler;
protected RoutingContext routingContext; protected RoutingContext routingContext;
public double airDistanceCostFactor; public double airDistanceCostFactor;
@ -66,9 +68,10 @@ public class RoutingEngine extends Thread
this.infoLogEnabled = outfileBase != null; this.infoLogEnabled = outfileBase != null;
this.routingContext = rc; this.routingContext = rc;
File baseFolder = new File( routingContext.localFunction ).getParentFile().getParentFile();
try try
{ {
File debugLog = new File( new File( routingContext.localFunction ).getParentFile(), "../debug.txt" ); File debugLog = new File( baseFolder, "debug.txt" );
if ( debugLog.exists() ) if ( debugLog.exists() )
{ {
infoLogWriter = new FileWriter( debugLog, true ); infoLogWriter = new FileWriter( debugLog, true );
@ -80,6 +83,15 @@ public class RoutingEngine extends Thread
{ {
throw new RuntimeException( "cannot open debug-log:" + ioe ); throw new RuntimeException( "cannot open debug-log:" + ioe );
} }
File stackLog = new File( baseFolder, "stacks.txt" );
if ( stackLog.exists() )
{
stackSampler = new StackSampler( stackLog, 1000 );
stackSampler.start();
logInfo( "********** started stacksampling" );
}
boolean cachedProfile = ProfileCache.parseProfile( rc ); boolean cachedProfile = ProfileCache.parseProfile( rc );
if ( hasInfo() ) if ( hasInfo() )
{ {
@ -229,6 +241,13 @@ public class RoutingEngine extends Thread
try { infoLogWriter.close(); } catch( Exception e ) {} try { infoLogWriter.close(); } catch( Exception e ) {}
infoLogWriter = null; infoLogWriter = null;
} }
if ( stackSampler != null )
{
try { stackSampler.close(); } catch( Exception e ) {}
stackSampler = null;
}
} }
} }
@ -378,16 +397,6 @@ public class RoutingEngine extends Thread
{ {
preloadPosition( mwp.waypoint ); preloadPosition( mwp.waypoint );
} }
// preliminary-hack: use old stuff if not yet matched
for( int i=0; i<unmatchedWaypoints.size(); i++)
{
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
if ( mwp.crosspoint == null )
{
unmatchedWaypoints.set(i, matchNodeForPosition( mwp.waypoint ) );
}
}
} }
private void preloadPosition( OsmNode n ) private void preloadPosition( OsmNode n )
@ -408,93 +417,6 @@ public class RoutingEngine extends Thread
} }
// geometric position matching finding the nearest routable way-section
private MatchedWaypoint matchNodeForPosition( OsmNodeNamed wp )
{
try
{
routingContext.setWaypoint( wp, false );
int minRingWith = 1;
for(;;)
{
MatchedWaypoint mwp = _matchNodeForPosition( wp, minRingWith );
if ( mwp.node1 != null )
{
int mismatch = wp.calcDistance( mwp.crosspoint );
if ( mismatch < 50*minRingWith )
{
return mwp;
}
}
if ( minRingWith == 1 && nodesCache.first_file_access_failed )
{
throw new IllegalArgumentException( "datafile " + nodesCache.first_file_access_name + " not found" );
}
if ( minRingWith++ == 5 )
{
throw new IllegalArgumentException( wp.name + "-position not mapped in existing datafile" );
}
}
}
finally
{
routingContext.unsetWaypoint();
}
}
private MatchedWaypoint _matchNodeForPosition( OsmNodeNamed wp, int minRingWidth )
{
wp.radius = 1e9;
resetCache();
preloadPosition( wp, minRingWidth, 2000 );
nodesCache.distanceChecker = routingContext;
List<OsmNode> nodeList = nodesCache.getAllNodes();
MatchedWaypoint mwp = new MatchedWaypoint();
mwp.waypoint = wp;
// first loop just to expand reverse links
for( OsmNode n : nodeList )
{
if ( !nodesCache.obtainNonHollowNode( n ) )
{
continue;
}
expandHollowLinkTargets( n );
OsmLink startLink = new OsmLink();
startLink.targetNode = n;
OsmPath startPath = new OsmPath( startLink );
startLink.addLinkHolder( startPath );
for( OsmLink link = n.firstlink; link != null; link = link.next )
{
if ( link.descriptionBitmap == null ) continue; // reverse link not found
OsmNode nextNode = link.targetNode;
if ( nextNode.isHollow() ) continue; // border node?
if ( nextNode.firstlink == null ) continue; // don't care about dead ends
if ( nextNode == n ) continue; // ?
double oldRadius = wp.radius;
OsmPath testPath = new OsmPath( n, startPath, link, null, false, routingContext );
if ( wp.radius < oldRadius )
{
if ( testPath.cost < 0 )
{
wp.radius = oldRadius; // no valid way
}
else
{
mwp.node1 = n;
mwp.node2 = nextNode;
mwp.radius = wp.radius;
mwp.crosspoint = new OsmNodeNamed();
mwp.crosspoint.ilon = routingContext.ilonshortest;
mwp.crosspoint.ilat = routingContext.ilatshortest;
}
}
}
}
return mwp;
}
// expand hollow link targets and resolve reverse links // expand hollow link targets and resolve reverse links
private void expandHollowLinkTargets( OsmNode n ) private void expandHollowLinkTargets( OsmNode n )

View file

@ -1,28 +0,0 @@
/**
* Container for routig configs
*
* @author ab
*/
package btools.router;
import btools.expressions.BExpressionReceiver;
final class RoutingMessageHandler implements BExpressionReceiver
{
private int ilon;
private int ilat;
public void setCurrentPos( int lon, int lat)
{
ilon = lon;
ilat = lat;
}
@Override
public void expressionWarning( String context, String message )
{
System.out.println( "message (lon=" + (ilon-180000000) + " lat=" + (ilat-90000000)
+ " context " + context + "): " + message );
}
}

View file

@ -25,8 +25,6 @@ final class BExpression
private static final int NUMBER_EXP = 33; private static final int NUMBER_EXP = 33;
private static final int VARIABLE_EXP = 34; private static final int VARIABLE_EXP = 34;
private static final int DUMPPOS_EXP = 40;
private int typ; private int typ;
private BExpression op1; private BExpression op1;
private BExpression op2; private BExpression op2;
@ -147,10 +145,6 @@ final class BExpression
{ {
exp.typ = NOT_EXP; exp.typ = NOT_EXP;
} }
else if ( "dumppos".equals( operator ) )
{
exp.typ = DUMPPOS_EXP;
}
else else
{ {
nops = 0; // check elemantary expressions nops = 0; // check elemantary expressions
@ -263,7 +257,6 @@ final class BExpression
case NUMBER_EXP: return numberValue; case NUMBER_EXP: return numberValue;
case VARIABLE_EXP: return ctx.getVariableValue( variableIdx ); case VARIABLE_EXP: return ctx.getVariableValue( variableIdx );
case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f; case NOT_EXP: return op1.evaluate(ctx) == 0.f ? 1.f : 0.f;
case DUMPPOS_EXP: ctx.expressionWarning( "INFO" ); return op1.evaluate(ctx);
default: throw new IllegalArgumentException( "unknown op-code: " + typ ); default: throw new IllegalArgumentException( "unknown op-code: " + typ );
} }
} }

View file

@ -31,8 +31,6 @@ public abstract class BExpressionContext
private BufferedReader _br = null; private BufferedReader _br = null;
private boolean _readerDone = false; private boolean _readerDone = false;
private BExpressionReceiver _receiver;
private Map<String,Integer> lookupNumbers = new HashMap<String,Integer>(); private Map<String,Integer> lookupNumbers = new HashMap<String,Integer>();
private ArrayList<BExpressionLookupValue[]> lookupValues = new ArrayList<BExpressionLookupValue[]>(); private ArrayList<BExpressionLookupValue[]> lookupValues = new ArrayList<BExpressionLookupValue[]>();
private ArrayList<String> lookupNames = new ArrayList<String>(); private ArrayList<String> lookupNames = new ArrayList<String>();
@ -58,20 +56,21 @@ public abstract class BExpressionContext
private byte[] currentByteArray = null; private byte[] currentByteArray = null;
private boolean currentInverseDirection= false; private boolean currentInverseDirection= false;
public List<BExpression> expressionList; private List<BExpression> expressionList;
private int minWriteIdx; private int minWriteIdx;
// build-in variable indexes for fast access // build-in variable indexes for fast access
private int[] buildInVariableIdx; private int[] buildInVariableIdx;
protected float[][] arrayBuildInVariablesCache; private float[][] arrayBuildInVariablesCache;
private float[] hashBucketVars;
abstract String[] getBuildInVariableNames(); abstract String[] getBuildInVariableNames();
protected float getBuildInVariable( int idx ) protected final float getBuildInVariable( int idx )
{ {
return arrayBuildInVariablesCache[idx][currentHashBucket]; return hashBucketVars[idx];
} }
private int linenr; private int linenr;
@ -105,10 +104,10 @@ public abstract class BExpressionContext
// create the build-in variables cache // create the build-in variables cache
int nBuildInVars = getBuildInVariableNames().length; int nBuildInVars = getBuildInVariableNames().length;
arrayBuildInVariablesCache = new float[nBuildInVars][]; arrayBuildInVariablesCache = new float[hashSize][];
for( int vi=0; vi<nBuildInVars; vi++ ) for( int hi=0; hi<hashSize; hi++ )
{ {
arrayBuildInVariablesCache[vi] = new float[hashSize]; arrayBuildInVariablesCache[hi] = new float[nBuildInVars];
} }
} }
@ -264,9 +263,10 @@ public abstract class BExpressionContext
public void evaluate( int[] lookupData2 ) public void evaluate( int[] lookupData2 )
{ {
lookupData = lookupData2; lookupData = lookupData2;
for( BExpression exp: expressionList) int n = expressionList.size();
for( int expidx = 0; expidx < n; expidx++ )
{ {
exp.evaluate( this ); expressionList.get( expidx ).evaluate( this );
} }
} }
@ -279,7 +279,7 @@ public abstract class BExpressionContext
* *
* @return true if the data is equivilant to the last calls data * @return true if the data is equivilant to the last calls data
*/ */
public boolean evaluate( boolean inverseDirection, byte[] ab, BExpressionReceiver receiver ) public boolean evaluate( boolean inverseDirection, byte[] ab )
{ {
requests ++; requests ++;
lookupDataValid = false; // this is an assertion for a nasty pifall lookupDataValid = false; // this is an assertion for a nasty pifall
@ -291,6 +291,7 @@ public abstract class BExpressionContext
int crc = Crc32.crcWithInverseBit(ab, inverseDirection ? inverseBitByteIndex : -1 ); int crc = Crc32.crcWithInverseBit(ab, inverseDirection ? inverseBitByteIndex : -1 );
int hashSize = _arrayBitmap.length; int hashSize = _arrayBitmap.length;
currentHashBucket = (crc & 0xfffffff) % hashSize; currentHashBucket = (crc & 0xfffffff) % hashSize;
hashBucketVars = arrayBuildInVariablesCache[currentHashBucket];
currentByteArray = ab; currentByteArray = ab;
currentInverseDirection = inverseDirection; currentInverseDirection = inverseDirection;
byte[] abBucket = _arrayBitmap[currentHashBucket]; byte[] abBucket = _arrayBitmap[currentHashBucket];
@ -325,18 +326,15 @@ public abstract class BExpressionContext
_arrayInverse[currentHashBucket] = currentInverseDirection; _arrayInverse[currentHashBucket] = currentInverseDirection;
_arrayCrc[currentHashBucket] = crc; _arrayCrc[currentHashBucket] = crc;
_receiver = receiver;
decode( lookupData, currentInverseDirection, currentByteArray ); decode( lookupData, currentInverseDirection, currentByteArray );
evaluate( lookupData ); evaluate( lookupData );
for( int vi=0; vi<buildInVariableIdx.length; vi++ ) for( int vi=0; vi<buildInVariableIdx.length; vi++ )
{ {
int idx = buildInVariableIdx[vi]; int idx = buildInVariableIdx[vi];
arrayBuildInVariablesCache[vi][currentHashBucket] = idx == -1 ? 0.f : variableData[idx]; hashBucketVars[vi] = idx == -1 ? 0.f : variableData[idx];
} }
_receiver = null;
return false; return false;
} }
@ -763,9 +761,4 @@ public abstract class BExpressionContext
return value; return value;
} }
void expressionWarning( String message )
{
_arrayBitmap[currentHashBucket] = null; // no caching if warnings
if ( _receiver != null ) _receiver.expressionWarning( context, message );
}
} }

View file

@ -50,11 +50,11 @@ public final class BExpressionContextWay extends BExpressionContext implements T
@Override @Override
public int accessType( byte[] description ) public int accessType( byte[] description )
{ {
evaluate( false, description, null ); evaluate( false, description );
float minCostFactor = getCostfactor(); float minCostFactor = getCostfactor();
if ( minCostFactor >= 9999.f ) if ( minCostFactor >= 9999.f )
{ {
evaluate( true, description, null ); evaluate( true, description );
float reverseCostFactor = getCostfactor(); float reverseCostFactor = getCostfactor();
if ( reverseCostFactor < minCostFactor ) if ( reverseCostFactor < minCostFactor )
{ {

View file

@ -1,7 +0,0 @@
package btools.expressions;
public interface BExpressionReceiver
{
public void expressionWarning( String context, String message );
}

View file

@ -39,7 +39,7 @@ public class EncodeDecodeTest
byte[] description = expctxWay.encode(lookupData); byte[] description = expctxWay.encode(lookupData);
// calculate the cost factor from that description // calculate the cost factor from that description
expctxWay.evaluate( false, description, null ); expctxWay.evaluate( false, description );
float costfactor = expctxWay.getCostfactor(); float costfactor = expctxWay.getCostfactor();
Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 ); Assert.assertTrue( "costfactor mismatch", Math.abs( costfactor - 5.15 ) < 0.00001 );

View file

@ -156,9 +156,9 @@ public class OsmCutter extends MapCreatorBase
if ( w.description == null ) return; if ( w.description == null ) return;
// filter according to profile // filter according to profile
_expctxWay.evaluate( false, w.description, null ); _expctxWay.evaluate( false, w.description );
boolean ok = _expctxWay.getCostfactor() < 10000.; boolean ok = _expctxWay.getCostfactor() < 10000.;
_expctxWay.evaluate( true, w.description, null ); _expctxWay.evaluate( true, w.description );
ok |= _expctxWay.getCostfactor() < 10000.; ok |= _expctxWay.getCostfactor() < 10000.;
if ( !ok ) return; if ( !ok ) return;

View file

@ -10,18 +10,10 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import btools.codec.MicroCache; import btools.codec.MicroCache;
import btools.codec.MicroCache1;
import btools.codec.MicroCache2; import btools.codec.MicroCache2;
public class OsmNodeP extends OsmLinkP public class OsmNodeP extends OsmLinkP
{ {
public static final int SIGNLON_BITMASK = 0x80;
public static final int SIGNLAT_BITMASK = 0x40;
public static final int TRANSFERNODE_BITMASK = 0x20;
public static final int WRITEDESC_BITMASK = 0x10;
public static final int SKIPDETAILS_BITMASK = 0x08;
public static final int NODEDESC_BITMASK = 0x04;
/** /**
* The latitude * The latitude
*/ */
@ -104,151 +96,10 @@ public class OsmNodeP extends OsmLinkP
return null; return null;
} }
public void writeNodeData1( MicroCache1 mc ) throws IOException
{
mc.writeShort( getSElev() );
// hack: write node-desc as link tag (copy cycleway-bits)
byte[] nodeDescription = getNodeDecsription();
for ( OsmLinkP link0 = getFirstLink(); link0 != null; link0 = link0.getNext( this ) )
{
int ilonref = ilon;
int ilatref = ilat;
OsmLinkP link = link0;
OsmNodeP origin = this;
int skipDetailBit = link0.descriptionBitmap == null ? SKIPDETAILS_BITMASK : 0;
// first pass just to see if that link is consistent
while (link != null)
{
OsmNodeP target = link.getTarget( origin );
if ( !target.isTransferNode() )
{
break;
}
// next link is the one (of two), does does'nt point back
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
{
if ( link.getTarget( target ) != origin )
break;
}
origin = target;
}
if ( link == null )
continue; // dead end
if ( skipDetailBit == 0 )
{
link = link0;
origin = this;
}
byte[] lastDescription = null;
while (link != null)
{
if ( link.descriptionBitmap == null && skipDetailBit == 0 )
throw new IllegalArgumentException( "missing way description..." );
OsmNodeP target = link.getTarget( origin );
int tranferbit = target.isTransferNode() ? TRANSFERNODE_BITMASK : 0;
int nodedescbit = nodeDescription != null ? NODEDESC_BITMASK : 0;
int writedescbit = 0;
if ( skipDetailBit == 0 ) // check if description changed
{
int inverseBitByteIndex = 0;
boolean inverseDirection = link.isReverse( origin );
byte[] ab = link.descriptionBitmap;
int abLen = ab.length;
int lastLen = lastDescription == null ? 0 : lastDescription.length;
boolean equalsCurrent = abLen == lastLen;
if ( equalsCurrent )
{
for ( int i = 0; i < abLen; i++ )
{
byte b = ab[i];
if ( i == inverseBitByteIndex && inverseDirection )
b ^= 1;
if ( b != lastDescription[i] )
{
equalsCurrent = false;
break;
}
}
}
if ( !equalsCurrent )
{
writedescbit = WRITEDESC_BITMASK;
lastDescription = new byte[abLen];
System.arraycopy( ab, 0, lastDescription, 0, abLen );
if ( inverseDirection )
lastDescription[inverseBitByteIndex] ^= 1;
}
}
int bm = tranferbit | writedescbit | nodedescbit | skipDetailBit;
int dlon = target.ilon - ilonref;
int dlat = target.ilat - ilatref;
ilonref = target.ilon;
ilatref = target.ilat;
if ( dlon < 0 )
{
bm |= SIGNLON_BITMASK;
dlon = -dlon;
}
if ( dlat < 0 )
{
bm |= SIGNLAT_BITMASK;
dlat = -dlat;
}
mc.writeByte( bm );
mc.writeVarLengthUnsigned( dlon );
mc.writeVarLengthUnsigned( dlat );
if ( writedescbit != 0 )
{
// write the way description, code direction into the first bit
mc.writeByte( lastDescription.length );
mc.write( lastDescription );
}
if ( nodedescbit != 0 )
{
mc.writeByte( nodeDescription.length );
mc.write( nodeDescription );
nodeDescription = null;
}
link.descriptionBitmap = null; // mark link as written
if ( tranferbit == 0 )
{
break;
}
mc.writeVarLengthSigned( target.getSElev() - getSElev() );
// next link is the one (of two), does does'nt point back
for ( link = target.getFirstLink(); link != null; link = link.getNext( target ) )
{
if ( link.getTarget( target ) != origin )
break;
}
if ( link == null )
throw new RuntimeException( "follow-up link not found for transfer-node!" );
origin = target;
}
}
}
public void writeNodeData( MicroCache mc ) throws IOException public void writeNodeData( MicroCache mc ) throws IOException
{ {
boolean valid = true; boolean valid = true;
if ( mc instanceof MicroCache1 ) if ( mc instanceof MicroCache2 )
{
writeNodeData1( (MicroCache1) mc );
}
else if ( mc instanceof MicroCache2 )
{ {
valid = writeNodeData2( (MicroCache2) mc ); valid = writeNodeData2( (MicroCache2) mc );
} }

View file

@ -124,11 +124,11 @@ public class RelationMerger extends MapCreatorBase
{ {
boolean ok = true; boolean ok = true;
// check access and log a warning for conflicts // check access and log a warning for conflicts
expctxReport.evaluate( false, data.description, null ); expctxReport.evaluate( false, data.description );
boolean warn = expctxReport.getCostfactor() >= 10000.; boolean warn = expctxReport.getCostfactor() >= 10000.;
if ( warn ) if ( warn )
{ {
expctxCheck.evaluate( false, data.description, null ); expctxCheck.evaluate( false, data.description );
ok = expctxCheck.getCostfactor() < 10000.; ok = expctxCheck.getCostfactor() < 10000.;
System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( false, data.description ) + " (ok=" + ok + ")" ); System.out.println( "** relation access conflict for wid = " + data.wid + " tags:" + expctxReport.getKeyValueDescription( false, data.description ) + " (ok=" + ok + ")" );

View file

@ -9,7 +9,6 @@ import java.util.TreeMap;
import btools.codec.DataBuffers; import btools.codec.DataBuffers;
import btools.codec.MicroCache; import btools.codec.MicroCache;
import btools.codec.MicroCache1;
import btools.codec.MicroCache2; import btools.codec.MicroCache2;
import btools.codec.StatCoderContext; import btools.codec.StatCoderContext;
import btools.expressions.BExpressionContextWay; import btools.expressions.BExpressionContextWay;
@ -57,7 +56,7 @@ public class WayLinker extends MapCreatorBase
private int minLat; private int minLat;
private int microCacheEncoding = 2; private int microCacheEncoding = 2;
private int divisor = microCacheEncoding == 2 ? 32 : 80; private int divisor = 32;
private int cellsize = 1000000 / divisor; private int cellsize = 1000000 / divisor;
private void reset() private void reset()
@ -186,9 +185,9 @@ public class WayLinker extends MapCreatorBase
int lastTraffic = 0; int lastTraffic = 0;
// filter according to profile // filter according to profile
expctxWay.evaluate( false, description, null ); expctxWay.evaluate( false, description );
boolean ok = expctxWay.getCostfactor() < 10000.; boolean ok = expctxWay.getCostfactor() < 10000.;
expctxWay.evaluate( true, description, null ); expctxWay.evaluate( true, description );
ok |= expctxWay.getCostfactor() < 10000.; ok |= expctxWay.getCostfactor() < 10000.;
if ( !ok ) if ( !ok )
return; return;
@ -330,8 +329,7 @@ public class WayLinker extends MapCreatorBase
OsmNodeP n0 = subList.get( 0 ); OsmNodeP n0 = subList.get( 0 );
int lonIdxDiv = n0.ilon / cellsize; int lonIdxDiv = n0.ilon / cellsize;
int latIdxDiv = n0.ilat / cellsize; int latIdxDiv = n0.ilat / cellsize;
MicroCache mc = microCacheEncoding == 0 ? new MicroCache1( size, abBuf2, lonIdxDiv, latIdxDiv ) : new MicroCache2( size, abBuf2, MicroCache mc = new MicroCache2( size, abBuf2, lonIdxDiv, latIdxDiv, divisor );
lonIdxDiv, latIdxDiv, divisor );
// sort via treemap // sort via treemap
TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>(); TreeMap<Integer, OsmNodeP> sortedList = new TreeMap<Integer, OsmNodeP>();
@ -360,8 +358,7 @@ public class WayLinker extends MapCreatorBase
System.arraycopy( abBuf1, 0, subBytes, 0, len ); System.arraycopy( abBuf1, 0, subBytes, 0, len );
// cross-check the encoding: re-instantiate the cache // cross-check the encoding: re-instantiate the cache
MicroCache mc2 = microCacheEncoding == 0 ? new MicroCache1( subBytes, lonIdxDiv, latIdxDiv ) : new MicroCache2( new DataBuffers( MicroCache mc2 = new MicroCache2( new DataBuffers( subBytes ), lonIdxDiv, latIdxDiv, divisor, null, null );
subBytes ), lonIdxDiv, latIdxDiv, divisor, null, null );
// ..and check if still the same // ..and check if still the same
String diffMessage = mc.compareWith( mc2 ); String diffMessage = mc.compareWith( mc2 );
if ( diffMessage != null ) if ( diffMessage != null )

View file

@ -35,8 +35,6 @@ public final class NodesCache
private OsmFile[][] fileRows; private OsmFile[][] fileRows;
private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>(); private ArrayList<MicroCache> segmentList = new ArrayList<MicroCache>();
public DistanceChecker distanceChecker;
public WaypointMatcher waypointMatcher; public WaypointMatcher waypointMatcher;
public boolean first_file_access_failed = false; public boolean first_file_access_failed = false;
@ -212,7 +210,7 @@ public final class NodesCache
long id = node.getIdFromPos(); long id = node.getIdFromPos();
if ( segment.getAndClear( id ) ) if ( segment.getAndClear( id ) )
{ {
node.parseNodeBody( segment, nodesMap, distanceChecker ); node.parseNodeBody( segment, nodesMap );
} }
if ( garbageCollectionEnabled ) // garbage collection if ( garbageCollectionEnabled ) // garbage collection

View file

@ -10,7 +10,6 @@ import java.io.RandomAccessFile;
import btools.codec.DataBuffers; import btools.codec.DataBuffers;
import btools.codec.MicroCache; import btools.codec.MicroCache;
import btools.codec.MicroCache1;
import btools.codec.MicroCache2; import btools.codec.MicroCache2;
import btools.codec.TagValueValidator; import btools.codec.TagValueValidator;
import btools.codec.WaypointMatcher; import btools.codec.WaypointMatcher;
@ -152,10 +151,6 @@ final class OsmFile
int crcData = Crc32.crc( ab, 0, asize - 4 ); int crcData = Crc32.crc( ab, 0, asize - 4 );
int crcFooter = new ByteDataReader( ab, asize - 4 ).readInt(); int crcFooter = new ByteDataReader( ab, asize - 4 ).readInt();
if ( crcData == crcFooter )
{
return reallyDecode ? new MicroCache1( ab, lonIdx, latIdx ) : null;
}
if ( ( crcData ^ 2 ) == crcFooter ) if ( ( crcData ^ 2 ) == crcFooter )
{ {
return reallyDecode ? new MicroCache2( dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher ) : null; return reallyDecode ? new MicroCache2( dataBuffers, lonIdx, latIdx, divisor, wayValidator, waypointMatcher ) : null;

View file

@ -26,21 +26,17 @@ public class OsmLink
public boolean counterLinkWritten; public boolean counterLinkWritten;
public boolean hasNewGeometry; // preliminary
public byte state; public byte state;
public void setGeometry( byte[] geometry ) public void setGeometry( byte[] geometry )
{ {
this.geometry = geometry; this.geometry = geometry;
hasNewGeometry = true;
} }
final public OsmTransferNode decodeFirsttransfer( OsmNode sourceNode ) final public OsmTransferNode decodeFirsttransfer( OsmNode sourceNode )
{ {
if ( geometry == null ) return null; if ( geometry == null ) return null;
if ( hasNewGeometry )
{
OsmTransferNode firstTransferNode = null; OsmTransferNode firstTransferNode = null;
OsmTransferNode lastTransferNode = null; OsmTransferNode lastTransferNode = null;
OsmNode startnode = counterLinkWritten ? targetNode : sourceNode; OsmNode startnode = counterLinkWritten ? targetNode : sourceNode;
@ -53,7 +49,6 @@ public class OsmLink
OsmTransferNode trans = new OsmTransferNode(); OsmTransferNode trans = new OsmTransferNode();
trans.ilon = olon + r.readVarLengthSigned(); trans.ilon = olon + r.readVarLengthSigned();
trans.ilat = olat + r.readVarLengthSigned(); trans.ilat = olat + r.readVarLengthSigned();
trans.descriptionBitmap = descriptionBitmap;
trans.selev = (short)(oselev + r.readVarLengthSigned()); trans.selev = (short)(oselev + r.readVarLengthSigned());
olon = trans.ilon; olon = trans.ilon;
olat = trans.ilat; olat = trans.ilat;
@ -77,14 +72,6 @@ public class OsmLink
} }
} }
return firstTransferNode; return firstTransferNode;
}
return OsmTransferNode.decode( geometry );
}
final public void encodeFirsttransfer( OsmTransferNode firsttransfer )
{
if ( firsttransfer == null ) geometry = null;
else geometry = OsmTransferNode.encode( firsttransfer );
} }
final public void addLinkHolder( OsmLinkHolder holder ) final public void addLinkHolder( OsmLinkHolder holder )

View file

@ -6,22 +6,11 @@
package btools.mapaccess; package btools.mapaccess;
import btools.codec.MicroCache; import btools.codec.MicroCache;
import btools.codec.MicroCache1;
import btools.codec.MicroCache2; import btools.codec.MicroCache2;
import btools.util.ByteArrayUnifier; import btools.util.ByteArrayUnifier;
public class OsmNode implements OsmPos public class OsmNode implements OsmPos
{ {
public static final int EXTERNAL_BITMASK = 0x80; // old semantic
public static final int SIGNLON_BITMASK = 0x80;
public static final int SIGNLAT_BITMASK = 0x40;
public static final int TRANSFERNODE_BITMASK = 0x20;
public static final int WRITEDESC_BITMASK = 0x10;
public static final int SKIPDETAILS_BITMASK = 0x08;
public static final int NODEDESC_BITMASK = 0x04;
public static final int RESERVED1_BITMASK = 0x02;
public static final int RESERVED2_BITMASK = 0x01;
public OsmNode() public OsmNode()
{ {
} }
@ -146,21 +135,17 @@ public class OsmNode implements OsmPos
return "" + getIdFromPos(); return "" + getIdFromPos();
} }
public void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, DistanceChecker dc ) public void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes )
{ {
if ( mc instanceof MicroCache1 ) if ( mc instanceof MicroCache2 )
{ {
parseNodeBody1( (MicroCache1) mc, hollowNodes, dc ); parseNodeBody2( (MicroCache2) mc, hollowNodes );
}
else if ( mc instanceof MicroCache2 )
{
parseNodeBody2( (MicroCache2) mc, hollowNodes, dc );
} }
else else
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() ); throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
} }
public void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes, DistanceChecker dc ) public void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes )
{ {
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier(); ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
@ -184,10 +169,6 @@ public class OsmNode implements OsmPos
} }
byte[] geometry = mc.readDataUntil( endPointer ); byte[] geometry = mc.readDataUntil( endPointer );
// preliminary hack: way-point-matching not here (done at decoding time)
if ( dc != null )
continue;
if ( linklon == ilon && linklat == ilat ) if ( linklon == ilon && linklat == ilat )
{ {
continue; // skip self-ref continue; // skip self-ref
@ -236,186 +217,10 @@ public class OsmNode implements OsmPos
rlink.setGeometry( geometry ); rlink.setGeometry( geometry );
} }
} }
} }
hollowNodes.remove( this ); hollowNodes.remove( this );
} }
public void parseNodeBody1( MicroCache1 is, OsmNodesMap hollowNodes, DistanceChecker dc )
{
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
selev = is.readShort();
while (is.hasMoreData())
{
int ilonref = ilon;
int ilatref = ilat;
boolean counterLinkWritten = false;
OsmTransferNode firstTransferNode = null;
OsmTransferNode lastTransferNode = null;
int linklon;
int linklat;
byte[] description = null;
for ( ;; )
{
int bitField = is.readByte();
int dlon = is.readVarLengthUnsigned();
int dlat = is.readVarLengthUnsigned();
if ( ( bitField & SIGNLON_BITMASK ) != 0 )
{
dlon = -dlon;
}
if ( ( bitField & SIGNLAT_BITMASK ) != 0 )
{
dlat = -dlat;
}
linklon = ilonref + dlon;
linklat = ilatref + dlat;
ilonref = linklon;
ilatref = linklat;
// read variable length or old 8 byte fixed, and ensure that 8 bytes is
// only fixed
if ( ( bitField & WRITEDESC_BITMASK ) != 0 )
{
byte[] ab = new byte[is.readByte()];
is.readFully( ab );
description = abUnifier.unify( ab );
}
if ( ( bitField & NODEDESC_BITMASK ) != 0 )
{
byte[] ab = new byte[is.readByte()];
is.readFully( ab );
nodeDescription = abUnifier.unify( ab );
}
if ( ( bitField & RESERVED1_BITMASK ) != 0 )
{
byte[] ab = new byte[is.readByte()];
is.readFully( ab );
}
if ( ( bitField & RESERVED2_BITMASK ) != 0 )
{
byte[] ab = new byte[is.readByte()];
is.readFully( ab );
}
if ( ( bitField & SKIPDETAILS_BITMASK ) != 0 )
{
counterLinkWritten = true;
}
if ( description == null && !counterLinkWritten )
throw new IllegalArgumentException( "internal error: missing way description!" );
boolean isTransfer = ( bitField & TRANSFERNODE_BITMASK ) != 0;
if ( isTransfer )
{
OsmTransferNode trans = new OsmTransferNode();
trans.ilon = linklon;
trans.ilat = linklat;
trans.descriptionBitmap = description;
trans.selev = (short) ( selev + is.readVarLengthSigned() );
if ( lastTransferNode == null )
{
firstTransferNode = trans;
}
else
{
lastTransferNode.next = trans;
}
lastTransferNode = trans;
}
else
{
break;
}
}
// performance shortcut: ignore link if out of reach
if ( dc != null && !counterLinkWritten )
{
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
{
continue;
}
}
if ( linklon == ilon && linklat == ilat )
{
continue; // skip self-ref
}
// first check the known links for that target
OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 );
if ( link == null ) // .. not found, then check the hollow nodes
{
long targetNodeId = ( (long) linklon ) << 32 | linklat;
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
if ( tn == null ) // node not yet known, create a new hollow proxy
{
tn = new OsmNode( linklon, linklat );
tn.setHollow();
hollowNodes.put( tn );
}
link = new OsmLink();
link.targetNode = tn;
link.counterLinkWritten = counterLinkWritten;
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, !counterLinkWritten, 1 );
if ( rlink == null ) // .. not found, create it
{
rlink = new OsmLink();
rlink.targetNode = this;
rlink.counterLinkWritten = !counterLinkWritten;
rlink.state = 2;
link.targetNode.addLink( rlink );
}
if ( !counterLinkWritten )
{
// we have the data for that link, so fill both the link ..
link.descriptionBitmap = description;
link.encodeFirsttransfer( firstTransferNode );
// .. and the reverse
if ( rlink.counterLinkWritten )
{
rlink.descriptionBitmap = description; // default for no
// transfer-nodes
OsmTransferNode previous = null;
OsmTransferNode rtrans = null;
for ( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
{
if ( previous == null )
{
rlink.descriptionBitmap = trans.descriptionBitmap;
}
else
{
previous.descriptionBitmap = trans.descriptionBitmap;
}
rtrans = new OsmTransferNode();
rtrans.ilon = trans.ilon;
rtrans.ilat = trans.ilat;
rtrans.selev = trans.selev;
rtrans.next = previous;
rtrans.descriptionBitmap = description;
previous = rtrans;
}
rlink.encodeFirsttransfer( rtrans );
}
}
}
if ( dc == null )
{
hollowNodes.remove( this );
}
}
public boolean isHollow() public boolean isHollow()
{ {

View file

@ -5,144 +5,15 @@
*/ */
package btools.mapaccess; package btools.mapaccess;
import btools.util.ByteDataReader;
import btools.util.ByteDataWriter;
public final class OsmTransferNode public final class OsmTransferNode
{ {
/**
* The description bitmap is mainly the way description
* used to calculate the costfactor
*/
public byte[] descriptionBitmap;
public OsmTransferNode next; public OsmTransferNode next;
public int ilon; public int ilon;
public int ilat; public int ilat;
public short selev; public short selev;
private static final int BIT_DESC = 1;
private static final int BIT_ILONHIGH = 2;
private static final int BIT_ILATHIGH = 4;
private static final int BIT_STOP = 8;
// encode this transfer-node into a byte array
public static byte[] encode( OsmTransferNode tn )
{
byte[] currentDesc = null;
int currentILonHigh = 0;
int currentILatHigh = 0;
OsmTransferNode n = tn;
// first loop to calc size
int size = 1; // stop-bit
while( n != null )
{
if ( n.descriptionBitmap == null ) throw new IllegalArgumentException( "transfernode-encode: description is null" );
if( n.descriptionBitmap != currentDesc )
{
currentDesc = n.descriptionBitmap;
size += 1 + currentDesc.length;
}
if( ( n.ilon >> 16 ) != currentILonHigh )
{
size += 2;
currentILonHigh = n.ilon >> 16;
}
if( (n.ilat >> 16) != currentILatHigh )
{
size += 2;
currentILatHigh = n.ilat >> 16;
}
size += 7;
n = n.next;
}
byte[] ab = new byte[size];
ByteDataWriter os = new ByteDataWriter( ab );
currentDesc = null;
currentILonHigh = 0;
currentILatHigh = 0;
n = tn;
while( n != null )
{
int mode = 0;
if( n.descriptionBitmap != currentDesc )
{
mode |= BIT_DESC;
currentDesc = n.descriptionBitmap;
}
if( ( n.ilon >> 16 ) != currentILonHigh )
{
mode |= BIT_ILONHIGH;
currentILonHigh = n.ilon >> 16;
}
if( (n.ilat >> 16) != currentILatHigh )
{
mode |= BIT_ILATHIGH;
currentILatHigh = n.ilat >> 16;
}
os.writeByte( mode);
if ( (mode & BIT_DESC) != 0 ) { os.writeByte( currentDesc.length ); os.write( currentDesc ); }
if ( (mode & BIT_ILONHIGH) != 0 ) os.writeShort( currentILonHigh );
if ( (mode & BIT_ILATHIGH) != 0 ) os.writeShort( currentILatHigh );
os.writeShort( n.ilon );
os.writeShort( n.ilat );
os.writeShort( n.selev );
n = n.next;
}
os.writeByte( BIT_STOP );
return ab;
}
// decode a transfer-node from a byte array
public static OsmTransferNode decode( byte[] ab )
{
ByteDataReader is = new ByteDataReader( ab );
OsmTransferNode firstNode = null;
OsmTransferNode lastNode = null;
byte[] currentDesc = null;
int currentILonHigh = 0;
int currentILatHigh = 0;
for(;;)
{
byte mode = is.readByte();
if ( (mode & BIT_STOP ) != 0 ) break;
OsmTransferNode n = new OsmTransferNode();
if ( (mode & BIT_DESC) != 0 ) { int dlen = is.readByte(); currentDesc = new byte[dlen]; is.readFully( currentDesc ); }
if ( (mode & BIT_ILONHIGH) != 0 ) currentILonHigh = is.readShort();
if ( (mode & BIT_ILATHIGH) != 0 ) currentILatHigh = is.readShort();
n.descriptionBitmap = currentDesc;
if ( n.descriptionBitmap == null ) throw new IllegalArgumentException( "transfernode-decode: description is null" );
int ilon = is.readShort() & 0xffff; ilon |= currentILonHigh << 16;
int ilat = is.readShort() & 0xffff; ilat |= currentILatHigh << 16;
n.ilon = ilon;
n.ilat = ilat;
n.selev = is.readShort();
if ( ilon != n.ilon ) System.out.println( "ilon=" + ilon + " n.ilon=" + n.ilon );
if ( ilat != n.ilat ) System.out.println( "ilat=" + ilat + " n.ilat=" + n.ilat );
if ( lastNode != null )
{
lastNode.next = n;
}
else
{
firstNode = n;
}
lastNode = n;
}
return firstNode;
}
} }

View file

@ -198,7 +198,7 @@ public class GraphLoader extends MapCreatorBase
{ {
if ( link.isWayLink() ) if ( link.isWayLink() )
{ {
wayCtx.evaluate( false, link.descriptionBitmap, null ); wayCtx.evaluate( false, link.descriptionBitmap );
if ( wayCtx.getCostfactor() < 10000.f ) if ( wayCtx.getCostfactor() < 10000.f )
{ {
return true; return true;

View file

@ -347,7 +347,7 @@ System.out.println( "*** finishedOffsets = " + finishedOffsets );
else if ( link.isWayLink() ) else if ( link.isWayLink() )
{ {
// get costfactor // get costfactor
rc.expctxWay.evaluate( link.isReverse( currentNode ), link.descriptionBitmap, null ); rc.expctxWay.evaluate( link.isReverse( currentNode ), link.descriptionBitmap );
// *** penalty for distance // *** penalty for distance
float costfactor = rc.expctxWay.getCostfactor(); float costfactor = rc.expctxWay.getCostfactor();
@ -366,7 +366,7 @@ System.out.println( "*** finishedOffsets = " + finishedOffsets );
if ( node.getNodeDecsription() != null ) if ( node.getNodeDecsription() != null )
{ {
rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0., node.getNodeDecsription(), null ); rc.expctxNode.evaluate( rc.expctxWay.getNodeAccessGranted() != 0., node.getNodeDecsription() );
float initialcost = rc.expctxNode.getInitialcost(); float initialcost = rc.expctxNode.getInitialcost();
if ( initialcost >= 1000000. ) if ( initialcost >= 1000000. )
{ {

View file

@ -0,0 +1,148 @@
package btools.util;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
public class StackSampler extends Thread
{
private DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss,SSS", new Locale( "en", "US" ) );
private BufferedWriter bw;
private Random rand = new Random();
private int interval;
private int flushCnt = 0;
private volatile boolean stopped;
public StackSampler( File logfile, int interval )
{
this.interval = interval;
try
{
bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( logfile, true ) ) );
}
catch (Exception e)
{
printError( "StackSampler: " + e.getMessage() );
}
}
protected void printError( String msg )
{
System.out.println( msg );
}
@Override
public void run()
{
while( !stopped )
{
dumpThreads();
}
if ( bw != null )
{
try
{
bw.close();
}
catch( Exception e ) {}
}
}
public void dumpThreads()
{
try
{
int wait1 = rand.nextInt( interval );
int wait2 = interval - wait1;
Thread.sleep( wait1 );
StringBuilder sb = new StringBuilder( df.format( new Date() ) + " THREADDUMP\n" );
Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces();
for ( Map.Entry<Thread, StackTraceElement[]> e : allThreads.entrySet() )
{
Thread t = e.getKey();
if ( t == Thread.currentThread() )
{
continue; // not me
}
StackTraceElement[] stack = e.getValue();
if ( !matchesFilter( stack ) )
{
continue;
}
sb.append( " (ID=" ).append( t.getId() ).append( " \"" ).append( t.getName() ).append( "\" " ).append( t.getState() ).append( "\n" );
for ( StackTraceElement line : stack )
{
sb.append( " " ).append( line.toString() ).append( "\n" );
}
sb.append( "\n" );
}
bw.write( sb.toString() );
if ( flushCnt++ >= 0 )
{
flushCnt = 0;
bw.flush();
}
Thread.sleep( wait2 );
}
catch (Exception e)
{
// ignore
}
}
public void close()
{
stopped = true;
interrupt();
}
private boolean matchesFilter( StackTraceElement[] stack )
{
boolean positiveMatch = false;
for ( StackTraceElement e : stack )
{
String s = e.toString();
if ( s.indexOf( "btools" ) >= 0 )
{
positiveMatch = true;
}
if ( s.indexOf( "Thread.sleep" ) >= 0 )
{
return false;
}
}
return positiveMatch;
}
public static void main( String[] args ) throws Exception
{
System.out.println( "StackSampler..." );
Class<?> clazz = Class.forName( args[0] );
String[] args2 = new String[args.length - 1];
for ( int i = 1; i < args.length; i++ )
{
args2[i - 1] = args[i];
}
StackSampler t = new StackSampler( new File( "stacks.log" ), 1000 );
t.start();
try
{
clazz.getMethod( "main", String[].class ).invoke( null, new Object[]{ args2 } );
}
finally
{
t.close();
}
}
}