Tim Habigt schrieb:
Hi René,
I tried your patch on the latest unstable version and it seems to work fine. I
have to admit that I didn't test it exhaustively, but I didn't notice any
problems. CPU utilization is much better on my multicore machine and there don't
seem to be errors in the rendered tiles. Thanks for your great work.
Thanks Tim ;)
and now a new version the fix follow problems
i start now all childs on start and use it and start not all childs new on a new
job.. this remove the memory leake.. "hope i"
i moved all my code out in a external class lib/ThreadedRenderer.pm
i fixed an never ending wait loop in my optimizePNG
he put the job now back after a render bug
and many othe problems fixed ;)
René
diff -urbBdpN a/lib/optimizePngTasks.pm b/lib/optimizePngTasks.pm
--- a/lib/optimizePngTasks.pm 1970-01-01 01:00:00.000000000 +0100
+++ b/lib/optimizePngTasks.pm 2008-11-15 21:39:08.000000000 +0100
@@ -0,0 +1,265 @@
+package optimizePngTasks;
+
+
+use warnings;
+use strict;
+use File::Temp qw/ tempfile tempdir /;
+use File::Copy;
+use File::Path;
+use Error qw(:try);
+use TahConf;
+use tahlib;
+use threads;
+use Thread::Semaphore;
+
+
+sub new
+{
+ my $class = shift;
+ my $Config = TahConf->getConfig();
+
+ my %sharedStack :shared;
+ my @sharedFilelist :shared;
+ my @sharedTranslist :shared;
+ my $self = {
+ Config => $Config,
+ SHARED => \%sharedStack,
+ DESTROYED => 0,
+ children => [],
+ };
+
+ $self->{SHARED}->{DESTROYED} = 0;
+ $self->{SHARED}->{JOBS} = -1;
+ $self->{SHARED}->{JOBSREADY} = 0;
+ $self->{SHARED}->{JOBSFILES} = [EMAIL PROTECTED];
+ $self->{SHARED}->{JOBSTRANSPARENT} = [EMAIL PROTECTED];
+ $self->{SHARED}->{CHILDCRASH} = 0; # TODO:
+
+ bless $self, $class;
+ return $self;
+}
+
+
+sub DESTROY
+{
+
+}
+
+########
+# kill all children threads
+########
+sub killAllChilds
+{
+ my $self = shift;
+
+ # set the destroy flag (detached childrens!)
+ $self->{'Semaphore'}->down();
+ $self->{SHARED}->{DESTROYED} = 1;
+ $self->{'Semaphore'}->up();
+
+}
+
+
+##########
+# start and init my children
+##########
+sub startChildren {
+ my $self = shift;
+ my $Config = $self->{Config};
+
+ if ($Config->get("Cores")) {
+ $self->{'maxChildren'} = $Config->get("Cores");
+ $self->{'children'} = [];
+ $self->{'Semaphore'} = Thread::Semaphore->new();
+
+ $::currentSubTask ='optimize';
+ $::progressPercent = 0;
+ ::statusMessage("init ". $self->{'maxChildren'} ." optimizePNG Child Tasks", 0, 6);
+ $self->{SHARED}->{'progress'} = 0;
+ for my $childID (1 .. $self->{'maxChildren'}) {
+ $self->{'children'}->[$childID] = threads->create( sub {
+
+ threads->detach();
+
+ my $sleeping = 0;
+ while (!$self->{SHARED}->{DESTROYED}) {
+
+
+ sleep 1;
+
+ while ($self->{SHARED}->{JOBS} < $#{$self->{SHARED}->{JOBSFILES}}) {
+ my ($png_file, $transparent) = "";
+
+ # access: lock()
+ $self->{'Semaphore'}->down();
+ $self->{SHARED}->{JOBS}++;
+ my $pos = $self->{SHARED}->{JOBS};
+
+ $png_file = $self->{SHARED}->{JOBSFILES}->[ $pos ];
+ $transparent = $self->{SHARED}->{JOBSTRANSPARENT}->[ $pos ];
+
+ $self->{SHARED}->{'progress'}++;
+ if($#{$self->{SHARED}->{JOBSFILES}} >0) {
+ $::progressPercent = 100 * $self->{SHARED}->{'progress'} / ($#{$self->{SHARED}->{JOBSFILES}}+1);
+ }
+
+ # access: unlock()
+ $self->{'Semaphore'}->up();
+
+ if( $png_file) { # no new work? go sleeping
+ #####
+ # lets do my work now
+ #####
+
+ eval {
+ $self->optimizePngClient($png_file, $transparent);
+ };
+ }
+
+ $self->{'Semaphore'}->down();
+ $self->{SHARED}->{JOBSREADY}++;
+ $self->{'Semaphore'}->up();
+
+ }
+
+
+ }
+ ::statusMessage("optimizePNG child $childID exit" ,1,10);
+
+ }
+ ); # threads->create(sub) end
+ } # for
+
+ }
+
+} # sub startChildren
+
+# add a new job ::addJob->($png_file,$transparent)
+sub addJob {
+ my $self = shift;
+ my $png_file = shift;
+ my $transparent = shift;
+
+ $self->{'Semaphore'}->down();
+
+ my $pos = $#{$self->{SHARED}->{JOBSFILES}}+1;
+
+ $self->{SHARED}->{JOBSFILES}->[ $pos ] = $png_file;
+ $self->{SHARED}->{JOBSTRANSPARENT}->[ $pos ] = $transparent;
+
+ $self->{'Semaphore'}->up();
+}
+
+
+# wait of all my jobs
+sub wait {
+ my $self = shift;
+
+ ::statusMessage("Wait of my PNG optimize Children", 0, 6);
+
+ while ($self->{SHARED}->{JOBSREADY} <= $#{$self->{SHARED}->{JOBSFILES}}) {
+ sleep 1;
+# print $self->{SHARED}->{JOBSREADY} ." ".$#{$self->{SHARED}->{JOBSFILES}} ."\n";
+ }
+
+}
+
+# reset my lists
+sub dataReset {
+ my $self = shift;
+
+ $self->{'Semaphore'}->down();
+
+ $self->{SHARED}->{JOBS} = -1;
+ $self->{SHARED}->{JOBSREADY} = 0;
+ undef @{ $self->{SHARED}->{JOBSFILES} };
+ undef @{ $self->{SHARED}->{JOBSTRANSPARENT} };
+
+ $self->{SHARED}->{'progress'} = 0;
+
+ $self->{'Semaphore'}->up();
+}
+
+
+#-----------------------------------------------------------------------------
+# optimize a PNG file
+#
+# Parameters:
+# $png_file - file name of PNG file
+# $transparent - whether or not this is a transparent tile
+#-----------------------------------------------------------------------------
+sub optimizePngClient
+{
+ my $self = shift();
+ my $png_file = shift();
+ my $transparent = shift();
+
+ my $Config = $self->{Config};
+
+ my $optipngOptions = "-l 9";
+
+ my $redirect = ($^O eq "MSWin32") ? "" : ">/dev/null";
+ my $tmp_suffix = '.cut';
+ my $tmp_file = $png_file . $tmp_suffix;
+ my (undef, undef, $png_file_name) = File::Spec->splitpath($png_file);
+
+ my $cmd;
+ if ($transparent) {
+ # Don't quantize if it's transparent
+ rename($png_file, $tmp_file);
+ }
+ elsif (($Config->get("PngQuantizer")||'') eq "pngnq") {
+ $cmd = sprintf("\"%s\" -e .png%s -s1 -n256 %s %s",
+ $Config->get("pngnq"),
+ $tmp_suffix,
+ $png_file,
+ $redirect);
+
+ ::statusMessage("ColorQuantizing $png_file_name", 0, 6);
+ if(::runCommand($cmd, $::PID)) {
+ # Color quantizing successful
+ unlink($png_file);
+ }
+ else {
+ # Color quantizing failed
+ ::statusMessage("ColorQuantizing $png_file_name with ".$Config->get("PngQuantizer")." failed", 1, 0);
+ rename($png_file, $tmp_file);
+ }
+ }
+ else {
+ ::statusMessage("Not Color Quantizing $png_file_name, pngnq not installed?", 0, 6);
+ rename($png_file, $tmp_file);
+ }
+
+ if ($Config->get("PngOptimizer") eq "pngcrush") {
+ $cmd = sprintf("\"%s\" %s -q %s %s %s",
+ $Config->get("Pngcrush"),
+ $optipngOptions,
+ $tmp_file,
+ $png_file,
+ $redirect);
+ }
+ elsif ($Config->get("PngOptimizer") eq "optipng") {
+ $cmd = sprintf("\"%s\" %s -out %s %s", #no quiet, because it even suppresses error output
+ $Config->get("Optipng"),
+ $tmp_file,
+ $png_file,
+ $redirect);
+ }
+ else {
+ ::statusMessage("PngOptimizer not configured (should not happen, update from svn, and check config file)", 1, 0);
+ ::talkInSleep("Install a PNG optimizer and configure it.", 15);
+ }
+
+ ::statusMessage("Optimizing $png_file_name", 0, 6);
+ if(::runCommand($cmd, $::PID)) {
+ unlink($tmp_file);
+ }
+ else {
+ ::statusMessage("Optimizing $png_file_name with " . $Config->get("PngOptimizer") . " failed", 1, 0);
+ rename($tmp_file, $png_file);
+ }
+}
+
+
+1;
diff -urbBdpN a/lib/ThreadedRenderer.pm b/lib/ThreadedRenderer.pm
--- a/lib/ThreadedRenderer.pm 1970-01-01 01:00:00.000000000 +0100
+++ b/lib/ThreadedRenderer.pm 2008-11-15 21:45:04.000000000 +0100
@@ -0,0 +1,294 @@
+package ThreadedRenderer;
+
+use warnings;
+use strict;
+use File::Temp qw/ tempfile tempdir /;
+use File::Copy;
+use File::Path;
+use Error qw(:try);
+use TahConf;
+use tahlib;
+use Tileset;
+use Request;
+
+use threads;
+use Thread::Semaphore;
+
+sub new {
+ my $class = shift;
+ my $Config = TahConf->getConfig();
+
+ my %sharedStack : shared;
+
+ my $self = {
+ Config => $Config,
+ SHARED => \%sharedStack,
+ DESTROYED => 0,
+ children => [],
+ };
+
+ my @sharedJobs : shared;
+ my @sharedJobsLayer : shared;
+ my @sharedJobsLayerDataFile : shared;
+ my @childStop : shared;
+ my @sharedJobErrors : shared;
+ my %sharedRequest : shared;
+
+ $self->{SHARED}->{RENDERERJOBS} = [EMAIL PROTECTED];
+ $self->{SHARED}->{RENDERERJOBLAYER} = [EMAIL PROTECTED];
+ $self->{SHARED}->{RENDERERJOBLAYERDATA} = [EMAIL PROTECTED];
+ $self->{SHARED}->{RENDERERJOBERRORS} = [EMAIL PROTECTED];
+ $self->{SHARED}->{RENDERERJOBERROR} = "";
+ $self->{SHARED}->{RENDERERJOBSPOS} = -1;
+ $self->{SHARED}->{RENDERERJOBSREADY} = 0;
+ $self->{SHARED}->{CHILDSTOP} = [EMAIL PROTECTED]; # for stop single clients
+ $self->{SHARED}->{JOBDIR} = "";
+ $self->{SHARED}->{REQEST} = \%sharedRequest;
+ $self->{SHARED}->{MAXSVGFILESIZE} = 0;
+
+ $self->{'maxChildren'} = $Config->get("Cores");
+
+ bless $self, $class;
+ return $self;
+}
+
+sub startChildren {
+ my $self = shift;
+ my $Config = $self->{Config};
+
+ if ( $Config->get("Cores") ) {
+
+ # add renderer childs
+ $self->{'rendererChildren'} = [];
+ $self->{'rendererSemaphore'} = Thread::Semaphore->new();
+
+
+ ::statusMessage( "init " . $self->{'maxChildren'} . " Renderer Child Tasks", 0, 6 );
+
+ for my $childID ( 1 .. $self->{'maxChildren'} ) {
+ $self->{SHARED}->{CHILDSTOP}->[$childID] = 0;
+ $self->{'rendererChildren'}->[$childID] = threads->create(
+ sub {
+
+ threads->detach();
+
+ my $req = $self->{req};
+ my $Config = $self->{Config};
+ my $pos;
+ my $layer;
+ my $layerDataFile;
+ my $zoom;
+ my $oldJobDir = "";
+
+ # wait of the global destroy flag or of the singel stop flag
+ while ( !$self->{SHARED}->{DESTROYED} ) {
+
+ # create new tileset for a new job
+ # TODO: bad way export some funktions to an external .pl file
+ $self->{'rendererSemaphore'}->down();
+ if ( $oldJobDir ne $self->{SHARED}->{JOBDIR} && $self->{SHARED}->{JOBDIR} ne "" ) {
+ my $req = new Request;
+ $req->ZXY(
+ $self->{SHARED}->{REQEST}->{'z'},
+ $self->{SHARED}->{REQEST}->{'x'},
+ $self->{SHARED}->{REQEST}->{'y'}
+ );
+ $req->layers_str( $self->{SHARED}->{REQEST}->{'layers'} );
+
+ $self->{tileset} = new Tileset( $req, 1, $self->{SHARED}->{JOBDIR} );
+ $oldJobDir = $self->{SHARED}->{JOBDIR};
+ }
+
+ $self->{'rendererSemaphore'}->up();
+
+ while ( !$self->{SHARED}->{CHILDSTOP}->[$childID]
+ && $oldJobDir eq $self->{SHARED}->{JOBDIR}
+ && $self->{SHARED}->{RENDERERJOBSPOS} < $#{ $self->{SHARED}->{RENDERERJOBS} } )
+ {
+
+ # access: lock()
+ $self->{'rendererSemaphore'}->down();
+
+ $self->{SHARED}->{RENDERERJOBSPOS}++;
+ $pos = $self->{SHARED}->{RENDERERJOBSPOS};
+ $zoom = $self->{SHARED}->{RENDERERJOBS}->[$pos];
+ $layer = $self->{SHARED}->{RENDERERJOBLAYER}->[$pos];
+ $layerDataFile = $self->{SHARED}->{RENDERERJOBLAYERDATA}->[$pos];
+
+ # access: unlock()
+ $self->{'rendererSemaphore'}->up();
+
+ ::statusMessage(
+ "Rendererclient $childID get job $pos zoom $zoom on layer $layer $layerDataFile",
+ 1, 10 );
+
+ ####
+ # i do my work now
+ ####
+ eval {
+ $self->{tileset}->Render( $layer, $zoom, $layerDataFile );
+ };
+ if ($@) {
+ ::statusMessage( "ERROR: Rendererclient $childID Renderer return $@", 1, 10 );
+
+ $self->{'rendererSemaphore'}->down();
+ $self->{SHARED}->{RENDERERJOBERROR} = 1;
+ $self->{'rendererSemaphore'}->up();
+
+ }
+ $self->{'rendererSemaphore'}->down();
+ $self->{SHARED}->{RENDERERJOBSREADY}++;
+ $self->{'rendererSemaphore'}->up();
+ }
+
+ sleep 1;
+ }
+ ::statusMessage( "Renderer child $childID exit", 1, 10 );
+ } #sub;
+ ); #threads->create
+ } # for
+ }
+}
+
+sub addJob {
+ my $self = shift;
+
+ # my $Config = $self->{Config};
+ my $zoom = shift;
+ my $layer = shift;
+ my $layerDataFile = shift;
+
+ $self->{'rendererSemaphore'}->down();
+
+ my $pos = $#{ $self->{SHARED}->{RENDERERJOBS} };
+ $pos++;
+
+ $self->{SHARED}->{RENDERERJOBS}->[$pos] = $zoom;
+ $self->{SHARED}->{RENDERERJOBLAYER}->[$pos] = $layer;
+ $self->{SHARED}->{RENDERERJOBLAYERDATA}->[$pos] = $layerDataFile;
+
+ $self->{'rendererSemaphore'}->up();
+
+ $self->updateMaxRenderer($layerDataFile); #TODO: move it to the svg generation after init new workflow
+}
+
+sub wait {
+ my $self = shift;
+
+ while ( $self->{SHARED}->{RENDERERJOBSREADY} <= $#{ $self->{SHARED}->{RENDERERJOBS} } ) {
+ sleep 1;
+ }
+}
+
+# reset my lists
+sub Reset {
+ my $self = shift;
+
+ $self->{'rendererSemaphore'}->down();
+
+ undef @{ $self->{SHARED}->{RENDERERJOBS} };
+ undef @{ $self->{SHARED}->{RENDERERJOBLAYER} };
+ undef @{ $self->{SHARED}->{RENDERERJOBLAYERDATA} };
+ undef @{ $self->{SHARED}->{RENDERERJOBERRORS} };
+ $self->{SHARED}->{RENDERERJOBERROR} = "";
+
+ $self->{SHARED}->{RENDERERJOBSPOS} = -1;
+ $self->{SHARED}->{RENDERERJOBSREADY} = 0;
+ $self->{SHARED}->{MAXSVGFILESIZE} = 0;
+
+ # reset renderer limitation
+ for ( my $i = $self->{'maxChildren'} ; $i > 0 ; $i-- ) {
+ $self->{SHARED}->{CHILDSTOP}->[$i] = 0;
+ }
+
+ $self->{'rendererSemaphore'}->up();
+}
+
+sub setJobDir {
+ my $self = shift;
+ my $jobDir = shift;
+
+ $self->{'rendererSemaphore'}->down();
+
+ $self->{SHARED}->{JOBDIR} = $jobDir;
+
+ $self->{'rendererSemaphore'}->up();
+
+}
+
+sub rendererError {
+ my $self = shift;
+ if( $self->{SHARED}->{RENDERERJOBERROR} ) {
+ return($self->{SHARED}->{RENDERERJOBERROR});
+ }
+
+ return;
+
+}
+
+
+sub setRequest {
+ my $self = shift;
+ my $req = shift;
+
+ my ( $z, $x, $y ) = $req->ZXY;
+ $self->{'rendererSemaphore'}->down();
+
+ $self->{SHARED}->{REQEST}->{'z'} = $z;
+ $self->{SHARED}->{REQEST}->{'x'} = $x;
+ $self->{SHARED}->{REQEST}->{'y'} = $y;
+
+ $self->{SHARED}->{REQEST}->{'layers'} = $req->layers_str();
+
+ $self->{'rendererSemaphore'}->up();
+
+}
+
+# set the maximum of paralel working renderer
+#TODO: use svg files and not the osm files for calculate
+sub updateMaxRenderer {
+ my $self = shift;
+ my $filename = shift;
+
+ my $Config = $self->{Config};
+
+ $filename = File::Spec->join( $self->{SHARED}->{JOBDIR}, $filename );
+ my @datafileStats = stat($filename);
+
+ if ( $self->{SHARED}->{MAXSVGFILESIZE} < $datafileStats[7] ) {
+ $self->{'rendererSemaphore'}->down();
+ $self->{SHARED}->{MAXSVGFILESIZE} = $datafileStats[7];
+ $self->{'rendererSemaphore'}->up();
+ }
+ else {
+ return;
+ }
+
+ my $caMemoryUsage = $self->{SHARED}->{MAXSVGFILESIZE} / 1024 / 16;
+
+ if ( ( $caMemoryUsage * $self->{'maxChildren'} ) > $Config->get("MaxMemory") ) {
+
+ # too little memory
+ my $newMaxChildren = int( $Config->get("MaxMemory") / $caMemoryUsage );
+ $newMaxChildren = 1 if $self->{'maxChildren'} eq $newMaxChildren;
+
+ ::statusMessage(
+ "too little memory for the render job and "
+ . $self->{'maxChildren'}
+ . " Children, stopp "
+ . ( $self->{'maxChildren'} - $newMaxChildren )
+ . " renderer childs from "
+ . $self->{'maxChildren'},
+ 1, 10
+ );
+
+ $self->{'rendererSemaphore'}->down();
+ for ( my $stopCount = ( $self->{'maxChildren'} - $newMaxChildren ) ; $stopCount > 0 ; $stopCount-- ) {
+ $self->{SHARED}->{CHILDSTOP}->[$stopCount] = 1;
+
+ }
+ $self->{'rendererSemaphore'}->up();
+ }
+}
+
+1;
diff -urbBdpN a/lib/Tileset.pm b/lib/Tileset.pm
--- a/lib/Tileset.pm 2008-11-15 00:07:59.530154027 +0100
+++ b/lib/Tileset.pm 2008-11-15 21:44:28.000000000 +0100
@@ -30,6 +30,12 @@ use File::Copy;
use File::Path;
use GD 2 qw(:DEFAULT :cmp);
+use threads;
+use Thread::Semaphore;
+
+use Data::Dumper;
+
+
#-----------------------------------------------------------------------------
# creates a new Tileset instance and returns it
# parameter is a request object with x,y,z, and layer atributes set
@@ -41,7 +47,8 @@ sub new
my $class = shift;
my $Config = TahConf->getConfig();
my $req = shift; #Request object
-
+ my $child = shift;
+ my $jobDir = shift;
my $self = {
req => $req,
Config => $Config,
@@ -53,11 +60,17 @@ sub new
my $delTmpDir = 1-$Config->get('Debug');
+ if($child) {
+ $self->{bbox}= bbox->new(ProjectXY($req->ZXY));
+ $self->{JobDir} = $jobDir;
+ }
+ else {
$self->{JobDir} = tempdir(
sprintf("%d_%d_%d_XXXXX",$self->{req}->ZXY),
DIR => $Config->get('WorkingDirectory'),
CLEANUP => $delTmpDir,
);
+ }
# create true color images by default
GD::Image->trueColor(1);
@@ -125,14 +139,11 @@ sub new
#-----------------------------------------------------------------------------
sub DESTROY
{
- my $self = shift;
- # Don't clean up in child threads
- return if ($self->{childThread});
+# perl call DESTROY more as on time!
- # only cleanup if we are the parent thread
- $self->cleanup();
}
+
#-----------------------------------------------------------------------------
# generate does everything that is needed to end up with a finished tileset
# that just needs compressing and uploading. It outputs status messages, and
@@ -149,6 +160,11 @@ sub generate
$self->{bbox}= bbox->new(ProjectXY($req->ZXY));
+ if(defined $::GlobalChildren->{ThreadedRenderer}) {
+ $::GlobalChildren->{ThreadedRenderer}->setRequest($self->{req});
+ $::GlobalChildren->{ThreadedRenderer}->setJobDir($self->{JobDir});
+ }
+
::statusMessage(sprintf("Tileset (%d,%d,%d) around %.2f,%.2f", $req->ZXY, $self->{bbox}->center), 1, 0);
if($req->Z >= 12)
@@ -158,9 +174,30 @@ sub generate
#------------------------------------------------------
my $beforeDownload = time();
- my $FullDataFile = $self->downloadData($req->layers);
+
+ # TODO: FIXME: remove it on the stable version! only for debuging and tests else { its the original}
+ # add a optional testadata directory (download not the data)
+ # DO NOT UPLOAD THE RESULTS REAL!
+ my $testdatadir = File::Spec->join($Config->get("WorkingDirectory"), 'testdatadir');
+ my $testdatafile = File::Spec->join($testdatadir, 'data.osm');
+ my $FullDataFile = "";
+
+ if($Config->get("useTestDirData") && $Config->get("debug") && $Config->get("UploadToDirectory")
+ && -d $testdatadir && -f $testdatafile)
+ {
+ $FullDataFile = File::Spec->join($self->{JobDir}, 'data.osm');
+ copy($testdatafile,$FullDataFile)
+ }
+ else {
+ $FullDataFile = $self->downloadData($req->layers);
+ }
+
::statusMessage("Download in ".(time() - $beforeDownload)." sec",1,10);
+ # manage renderer memory usage
+ # a 16mb osm file consum ca 1gb ram as svg "int(16786037/1024/16)"
+
+
#------------------------------------------------------
# Handle all layers, one after the other
#------------------------------------------------------
@@ -327,7 +364,15 @@ sub generate
$::currentSubTask = "";
::keepLog($$,"GenerateTileset","stop",'x='.$req->X.',y='.$req->Y.',z='.$req->Z." for layers ".$req->layers_str);
+
+ # cleanup children data
+ $::GlobalChildren->{ThreadedRenderer}->Reset();
+
+
# Cleaning up of tmpdirs etc. are called in the destructor DESTROY
+ # TODO: i move it back! DESTORY is not called only one time!
+ # the GC from perl call DESTROY a 2. time and in thread mode 2*child
+ $self->cleanup();
}
sub generateNormalLayer
@@ -356,6 +401,10 @@ sub generateNormalLayer
{ # Forking to render zoom levels in parallel
$self->forkedRender($layer, $layerDataFile);
}
+ elsif ($self->{Config}->get("Cores") && defined $::GlobalChildren->{ThreadedRenderer} )
+ { # use threads for rendering zoom levels parallel
+ $self->threadedRender($layer, $layerDataFile);
+ }
else
{ # Non-forking render
$self->nonForkedRender($layer, $layerDataFile);
@@ -800,7 +849,8 @@ sub downloadData
throw TilesetError "UTF8 test failed", "utf8";
}
::resetFault("utf8"); #reset to zero if no UTF8 errors found.
- return ($DataFile ,"");
+
+ return ($DataFile);
}
@@ -1002,6 +1052,58 @@ sub nonForkedRender
$self->Render($layer, $zoom, $layerDataFile)
}
+ if (defined $::GlobalChildren->{optimizePngTasks}) {
+ $::GlobalChildren->{optimizePngTasks}->wait();
+ $::GlobalChildren->{optimizePngTasks}->dataReset();
+ }
+
+
+ if ($Config->get("CreateTilesetFile") and !$Config->get("LocalSlippymap")) {
+ $self->createTilesetFile($layer);
+ }
+ else {
+ $self->createZipFile($layer);
+ }
+}
+
+#-------------------------------------------------------------------
+# renders the tiles, not using threads
+# paramter: ($layer, $layerDataFile)
+#-------------------------------------------------------------------
+sub threadedRender
+{
+ my $self = shift;
+ my ($layer, $layerDataFile) = @_;
+ my $req = $self->{req};
+ my $Config = $self->{Config};
+ my $minzoom = $req->Z;
+ my $maxzoom = $Config->get($layer."_MaxZoom");
+
+
+ for (my $zoom = $maxzoom ; $zoom >= $req->Z; $zoom--) {
+
+ ::statusMessage("add renderjob zoom: $zoom " ,1,10);
+ $::GlobalChildren->{ThreadedRenderer}->addJob($zoom,$layer,$layerDataFile);
+
+ }
+
+
+ #############
+ # at this time is the client on work and the main process wait now
+ #############
+ $::GlobalChildren->{ThreadedRenderer}->wait();
+
+# sleep 2; # dead zone
+
+ if( $::GlobalChildren->{ThreadedRenderer}->rendererError() ) {
+ throw TilesetError "Render failure", "renderer";
+ }
+
+ if (defined $::GlobalChildren->{optimizePngTasks}) {
+ $::GlobalChildren->{optimizePngTasks}->wait();
+ $::GlobalChildren->{optimizePngTasks}->dataReset();
+ }
+
if ($Config->get("CreateTilesetFile") and !$Config->get("LocalSlippymap")) {
$self->createTilesetFile($layer);
}
@@ -1286,11 +1388,16 @@ sub SplitTiles
print $fp $png_data;
close $fp;
+ if(defined $::GlobalChildren->{optimizePngTasks}) {
+ $::GlobalChildren->{optimizePngTasks}->addJob($tile_file,$Config->get("${layer}_Transparent"));
+ }
+ else {
$self->optimizePng($tile_file, $Config->get("${layer}_Transparent"));
}
}
}
}
+ }
}
diff -urbBdpN a/tilesGen.pl b/tilesGen.pl
--- a/tilesGen.pl 2008-11-12 18:58:51.618157433 +0100
+++ b/tilesGen.pl 2008-11-15 21:48:24.000000000 +0100
@@ -44,6 +44,9 @@ use English '-no_match_vars';
use Encode;
use POSIX;
+use optimizePngTasks;
+use ThreadedRenderer;
+
#---------------------------------
# Read the config file
@@ -74,7 +77,7 @@ else
# set the progress indicator variables
our $currentSubTask;
my $progress = 0;
-our $progressJobs = 1;
+our $progressJobs :shared = 1;
our $progressPercent = 0;
my $LastTimeVersionChecked = 0; # version is only checked when last time was more than 10 min ago
@@ -229,6 +232,27 @@ if( my $nice = $Config->get("Niceness")
}
}
+
+#########
+# init Children for optimizePngTasks
+#########
+if ($Config->get("Cores") && !$Config->get("Fork")
+ && ($Mode eq "xy" || $Mode eq "loop") ) {
+
+ our $GlobalChildren = {};
+
+ # start optimizePng Childs
+ $GlobalChildren->{optimizePngTasks} = optimizePngTasks->new();
+ $GlobalChildren->{optimizePngTasks}->startChildren();
+
+ #start threadedrenderer childs
+ $GlobalChildren->{ThreadedRenderer} = ThreadedRenderer->new();
+ $GlobalChildren->{ThreadedRenderer}->startChildren();
+
+}
+
+
+
#---------------------------------
## Start processing
_______________________________________________
Tilesathome mailing list
[email protected]
http://lists.openstreetmap.org/listinfo/tilesathome