mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-02-16 20:41:57 +01:00
Save state during render with CLI and restart unfinished renders
This commit is contained in:
parent
9427c1cc58
commit
b7db58461f
@ -24,8 +24,14 @@
|
|||||||
*/
|
*/
|
||||||
package de.bluecolored.bluemap.cli;
|
package de.bluecolored.bluemap.cli;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -36,6 +42,8 @@
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ForkJoinPool;
|
import java.util.concurrent.ForkJoinPool;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
import org.apache.commons.cli.CommandLine;
|
||||||
import org.apache.commons.cli.CommandLineParser;
|
import org.apache.commons.cli.CommandLineParser;
|
||||||
@ -152,86 +160,118 @@ public void renderMaps() throws IOException {
|
|||||||
resourcePack.saveTextureFile(textureExportFile);
|
resourcePack.saveTextureFile(textureExportFile);
|
||||||
|
|
||||||
RenderManager renderManager = new RenderManager(config.getRenderThreadCount());
|
RenderManager renderManager = new RenderManager(config.getRenderThreadCount());
|
||||||
|
File rmstate = new File(configFolder, "rmstate");
|
||||||
|
|
||||||
|
if (rmstate.exists()) {
|
||||||
|
try (
|
||||||
|
InputStream in = new GZIPInputStream(new FileInputStream(rmstate));
|
||||||
|
DataInputStream din = new DataInputStream(in);
|
||||||
|
){
|
||||||
|
renderManager.readState(din, maps.values());
|
||||||
|
Logger.global.logInfo("Found unfinished render, continuing ... (If you want to start a new render, delete the this file: " + rmstate.getCanonicalPath());
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to read saved render-state! Remove the file " + rmstate.getCanonicalPath() + " to start a new render.", ex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (MapType map : maps.values()) {
|
||||||
|
Logger.global.logInfo("Creating render-task for map '" + map.getId() + "' ...");
|
||||||
|
Logger.global.logInfo("Collecting tiles ...");
|
||||||
|
|
||||||
|
Collection<Vector2i> chunks;
|
||||||
|
if (!forceRender) {
|
||||||
|
long lastRender = webSettings.getLong(map.getId(), "last-render");
|
||||||
|
chunks = map.getWorld().getChunkList(lastRender);
|
||||||
|
} else {
|
||||||
|
chunks = map.getWorld().getChunkList();
|
||||||
|
}
|
||||||
|
|
||||||
|
HiresModelManager hiresModelManager = map.getTileRenderer().getHiresModelManager();
|
||||||
|
Collection<Vector2i> tiles = hiresModelManager.getTilesForChunks(chunks);
|
||||||
|
Logger.global.logInfo("Found " + tiles.size() + " tiles to render! (" + chunks.size() + " chunks)");
|
||||||
|
if (!forceRender && chunks.size() == 0) {
|
||||||
|
Logger.global.logInfo("(This is normal if nothing has changed in the world since the last render. Use -f on the command-line to force a render of all chunks)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tiles.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderTask task = new RenderTask(map.getName(), map);
|
||||||
|
task.addTiles(tiles);
|
||||||
|
task.optimizeQueue();
|
||||||
|
|
||||||
|
renderManager.addRenderTask(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.global.logInfo("Starting render ...");
|
||||||
renderManager.start();
|
renderManager.start();
|
||||||
|
|
||||||
for (MapType map : maps.values()) {
|
long startTime = System.currentTimeMillis();
|
||||||
Logger.global.logInfo("Rendering map '" + map.getId() + "' ...");
|
|
||||||
Logger.global.logInfo("Collecting tiles to render...");
|
|
||||||
|
|
||||||
Collection<Vector2i> chunks;
|
|
||||||
if (!forceRender) {
|
|
||||||
long lastRender = webSettings.getLong(map.getId(), "last-render");
|
|
||||||
chunks = map.getWorld().getChunkList(lastRender);
|
|
||||||
} else {
|
|
||||||
chunks = map.getWorld().getChunkList();
|
|
||||||
}
|
|
||||||
|
|
||||||
HiresModelManager hiresModelManager = map.getTileRenderer().getHiresModelManager();
|
|
||||||
Collection<Vector2i> tiles = hiresModelManager.getTilesForChunks(chunks);
|
|
||||||
Logger.global.logInfo("Found " + tiles.size() + " tiles to render! (" + chunks.size() + " chunks)");
|
|
||||||
if (!forceRender && chunks.size() == 0) {
|
|
||||||
Logger.global.logInfo("(This is normal if nothing has changed in the world since the last render. Use -f on the command-line to force a render of all chunks)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tiles.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.global.logInfo("Starting Render...");
|
long lastLogUpdate = startTime;
|
||||||
long starttime = System.currentTimeMillis();
|
long lastSave = startTime;
|
||||||
|
|
||||||
RenderTask task = new RenderTask("Map-Render: " + map.getName(), map);
|
while(renderManager.getRenderTaskCount() != 0) {
|
||||||
task.addTiles(tiles);
|
|
||||||
task.optimizeQueue();
|
|
||||||
|
|
||||||
renderManager.addRenderTask(task);
|
|
||||||
|
|
||||||
long lastLogUpdate = System.currentTimeMillis();
|
|
||||||
long lastSave = lastLogUpdate;
|
|
||||||
|
|
||||||
while(!task.isFinished()) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(200);
|
|
||||||
} catch (InterruptedException e) {}
|
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
|
|
||||||
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
|
||||||
lastLogUpdate = now;
|
|
||||||
long time = task.getActiveTime();
|
|
||||||
|
|
||||||
String durationString = DurationFormatUtils.formatDurationWords(time, true, true);
|
|
||||||
int tileCount = task.getRemainingTileCount() + task.getRenderedTileCount();
|
|
||||||
double pct = (double)task.getRenderedTileCount() / (double) tileCount;
|
|
||||||
|
|
||||||
long ert = (long)((time / pct) * (1d - pct));
|
|
||||||
String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true);
|
|
||||||
|
|
||||||
double tps = task.getRenderedTileCount() / (time / 1000.0);
|
|
||||||
|
|
||||||
Logger.global.logInfo("Rendered " + task.getRenderedTileCount() + " of " + tileCount + " tiles in " + durationString + " | " + GenericMath.round(tps, 3) + " tiles/s");
|
|
||||||
Logger.global.logInfo(GenericMath.round(pct * 100, 3) + "% | Estimated remaining time: " + ertDurationString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lastSave < now - 5 * 60000) { // save every 5 minutes
|
|
||||||
lastSave = now;
|
|
||||||
map.getTileRenderer().save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
map.getTileRenderer().save();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
webSettings.set(starttime, map.getId(), "last-render");
|
Thread.sleep(200);
|
||||||
webSettings.save();
|
} catch (InterruptedException e) {}
|
||||||
} catch (IOException e) {
|
|
||||||
Logger.global.logError("Failed to update web-settings!", e);
|
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
if (lastLogUpdate < now - 10000) { // print update all 10 seconds
|
||||||
|
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||||
|
lastLogUpdate = now;
|
||||||
|
long time = currentTask.getActiveTime();
|
||||||
|
|
||||||
|
String durationString = DurationFormatUtils.formatDurationWords(time, true, true);
|
||||||
|
int tileCount = currentTask.getRemainingTileCount() + currentTask.getRenderedTileCount();
|
||||||
|
double pct = (double)currentTask.getRenderedTileCount() / (double) tileCount;
|
||||||
|
|
||||||
|
long ert = (long)((time / pct) * (1d - pct));
|
||||||
|
String ertDurationString = DurationFormatUtils.formatDurationWords(ert, true, true);
|
||||||
|
|
||||||
|
double tps = currentTask.getRenderedTileCount() / (time / 1000.0);
|
||||||
|
|
||||||
|
Logger.global.logInfo("Rendering map '" + currentTask.getName() + "':");
|
||||||
|
Logger.global.logInfo("Rendered " + currentTask.getRenderedTileCount() + " of " + tileCount + " tiles in " + durationString + " | " + GenericMath.round(tps, 3) + " tiles/s");
|
||||||
|
Logger.global.logInfo(GenericMath.round(pct * 100, 3) + "% | Estimated remaining time: " + ertDurationString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastSave < now - 1 * 60000) { // save every minute
|
||||||
|
RenderTask currentTask = renderManager.getCurrentRenderTask();
|
||||||
|
|
||||||
|
lastSave = now;
|
||||||
|
currentTask.getMapType().getTileRenderer().save();
|
||||||
|
|
||||||
|
try (
|
||||||
|
OutputStream os = new GZIPOutputStream(new FileOutputStream(rmstate));
|
||||||
|
DataOutputStream dos = new DataOutputStream(os);
|
||||||
|
){
|
||||||
|
renderManager.writeState(dos);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to save render-state!", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderManager.stop();
|
renderManager.stop();
|
||||||
|
|
||||||
Logger.global.logInfo("Waiting for all threads to quit...");
|
//render finished, so remove render state file
|
||||||
|
rmstate.delete();
|
||||||
|
|
||||||
|
for (MapType map : maps.values()) {
|
||||||
|
webSettings.set(startTime, map.getId(), "last-render");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
webSettings.save();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.logError("Failed to update web-settings!", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.global.logInfo("Waiting for all threads to quit ...");
|
||||||
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
if (!ForkJoinPool.commonPool().awaitQuiescence(30, TimeUnit.SECONDS)) {
|
||||||
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
Logger.global.logWarning("Some save-threads are taking very long to exit (>30s), they will be ignored.");
|
||||||
}
|
}
|
||||||
@ -240,14 +280,14 @@ public void renderMaps() throws IOException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startWebserver() throws IOException {
|
public void startWebserver() throws IOException {
|
||||||
Logger.global.logInfo("Starting webserver...");
|
Logger.global.logInfo("Starting webserver ...");
|
||||||
|
|
||||||
BlueMapWebServer webserver = new BlueMapWebServer(configManager.getMainConfig());
|
BlueMapWebServer webserver = new BlueMapWebServer(configManager.getMainConfig());
|
||||||
webserver.start();
|
webserver.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean loadResources() throws IOException, ParseResourceException {
|
private boolean loadResources() throws IOException, ParseResourceException {
|
||||||
Logger.global.logInfo("Loading resources...");
|
Logger.global.logInfo("Loading resources ...");
|
||||||
|
|
||||||
MainConfig config = configManager.getMainConfig();
|
MainConfig config = configManager.getMainConfig();
|
||||||
|
|
||||||
|
@ -157,7 +157,17 @@ public int getQueueSize() {
|
|||||||
* Returns a copy of the deque with the render tasks in order as array
|
* Returns a copy of the deque with the render tasks in order as array
|
||||||
*/
|
*/
|
||||||
public RenderTask[] getRenderTasks(){
|
public RenderTask[] getRenderTasks(){
|
||||||
return renderTasks.toArray(new RenderTask[renderTasks.size()]);
|
synchronized (renderTasks) {
|
||||||
|
return renderTasks.toArray(new RenderTask[renderTasks.size()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRenderTaskCount(){
|
||||||
|
return renderTasks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderTask getCurrentRenderTask() {
|
||||||
|
return renderTasks.peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
|
Loading…
Reference in New Issue
Block a user