Cleanup Error logging + Polish OpenGL Error/Warning/Message handling
This commit is contained in:
@@ -274,8 +274,7 @@ public class LodDimensionFileHandler
|
||||
}
|
||||
catch (IOException ioEx)
|
||||
{
|
||||
ApiShared.LOGGER.error("LOD file read error. Unable to read xz compressed file [" + file + "] error [" + ioEx.getMessage() + "]: ");
|
||||
ioEx.printStackTrace();
|
||||
ApiShared.LOGGER.error("LOD file read error. Unable to read xz compressed file [" + file + "]: ",ioEx);
|
||||
region.addLevelContainer(new VerticalLevelContainer(tempDetailLevel));
|
||||
}
|
||||
}// for each detail level
|
||||
@@ -301,8 +300,7 @@ public class LodDimensionFileHandler
|
||||
try {
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to create parent directory for [" + file + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to create parent directory for [" + file + "]: ", e);
|
||||
return;
|
||||
}
|
||||
try (FileOutputStream fileOutStream = new FileOutputStream(file))
|
||||
@@ -318,8 +316,7 @@ public class LodDimensionFileHandler
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to write to temp file [" + file + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to write to temp file [" + file + "]: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,8 +392,7 @@ public class LodDimensionFileHandler
|
||||
if (!worked)
|
||||
ApiShared.LOGGER.error("File writing timed out! File data may not be saved correctly and may cause corruptions!!!");
|
||||
} catch (InterruptedException e) {
|
||||
ApiShared.LOGGER.error("File writing wait is interrupted! File data may not be saved correctly and may cause corruptions!!!");
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("File writing wait is interrupted! File data may not be saved correctly and may cause corruptions!!!: ", e);
|
||||
} finally {
|
||||
fileWritingThreadPool = Executors.newSingleThreadExecutor(new LodThreadFactory(this.getClass().getSimpleName(), Thread.NORM_PRIORITY+1));
|
||||
}
|
||||
@@ -449,7 +445,7 @@ public class LodDimensionFileHandler
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("Lod: UNCAUGHT exception when saving region "+r.getRegionPos()+": ", e);
|
||||
} finally {
|
||||
r.isWriting.decrementAndGet();
|
||||
}
|
||||
@@ -560,8 +556,7 @@ public class LodDimensionFileHandler
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to write to temp file [" + tempFile + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to write to temp file [" + tempFile + "]: ", e);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -569,8 +564,7 @@ public class LodDimensionFileHandler
|
||||
try {
|
||||
Files.move(tempFile.toPath(), oldFile.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to update file [" + oldFile + "] error [" + e.getMessage() + "]: ");
|
||||
e.printStackTrace();
|
||||
ApiShared.LOGGER.error("LOD file write error. Unable to update file [" + oldFile + "]: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,26 +124,20 @@ public class LodVertexBuffer implements AutoCloseable
|
||||
_destroy();
|
||||
_create(useBuffStorage);
|
||||
}
|
||||
try {
|
||||
switch (uploadMethod) {
|
||||
case AUTO:
|
||||
throw new IllegalArgumentException("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
|
||||
case BUFFER_STORAGE:
|
||||
_uploadBufferStorage(bb);
|
||||
break;
|
||||
case DATA:
|
||||
_uploadData(bb);
|
||||
break;
|
||||
case SUB_DATA:
|
||||
_uploadSubData(bb, maxExpensionSize);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid GpuUploadMethod enum");
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
ApiShared.LOGGER.error("vboUpload failed: ", e);
|
||||
switch (uploadMethod) {
|
||||
case AUTO:
|
||||
throw new IllegalArgumentException("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
|
||||
case BUFFER_STORAGE:
|
||||
_uploadBufferStorage(bb);
|
||||
break;
|
||||
case DATA:
|
||||
_uploadData(bb);
|
||||
break;
|
||||
case SUB_DATA:
|
||||
_uploadSubData(bb, maxExpensionSize);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid GpuUploadMethod enum");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.objects.opengl.LodQuadBuilder.BufferFiller;
|
||||
@@ -96,7 +97,13 @@ public class SimpleRenderBuffer extends RenderBuffer
|
||||
ByteBuffer bb = iter.next();
|
||||
LodVertexBuffer vbo = getOrMakeVbo(i++, method.useBufferStorage);
|
||||
int size = bb.limit() - bb.position();
|
||||
vbo.uploadBuffer(bb, size/LodUtil.LOD_VERTEX_FORMAT.getByteSize(), method, FULL_SIZED_BUFFERS);
|
||||
try {
|
||||
vbo.uploadBuffer(bb, size/LodUtil.LOD_VERTEX_FORMAT.getByteSize(), method, FULL_SIZED_BUFFERS);
|
||||
} catch (Exception e) {
|
||||
vbos[i-1] = null;
|
||||
vbo.close();
|
||||
ApiShared.LOGGER.error("Failed to upload buffer: ", e);
|
||||
}
|
||||
if (BPerNS<=0) continue;
|
||||
// upload buffers over an extended period of time
|
||||
// to hopefully prevent stuttering.
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
|
||||
package com.seibel.lod.core.render;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@@ -37,10 +35,10 @@ import org.lwjgl.opengl.GLUtil;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.GLProxyContext;
|
||||
import com.seibel.lod.core.util.GLMessage;
|
||||
import com.seibel.lod.core.util.GLMessageOutputStream;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
@@ -65,6 +63,12 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
public class GLProxy
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
|
||||
private ExecutorService workerThread = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(GLProxy.class.getSimpleName() + "-Worker-Thread").build());
|
||||
@@ -103,6 +107,9 @@ public class GLProxy
|
||||
|
||||
private final GpuUploadMethod preferredUploadMethod;
|
||||
|
||||
public final GLMessage.Builder lodBuilderDebugMessageBuilder;
|
||||
public final GLMessage.Builder proxyWorkerDebugMessageBuilder;
|
||||
|
||||
|
||||
private String getFailedVersionInfo(GLCapabilities c) {
|
||||
|
||||
@@ -150,6 +157,31 @@ public class GLProxy
|
||||
"4.6: " + c.OpenGL46 + "\n";
|
||||
}
|
||||
|
||||
private static void logMessage(GLMessage msg) {
|
||||
GLMessage.Severity s = msg.severity;
|
||||
if (msg.type == GLMessage.Type.ERROR ||
|
||||
msg.type == GLMessage.Type.UNDEFINED_BEHAVIOR) {
|
||||
ApiShared.LOGGER.error("GL ERROR {} from {}: {}", msg.id, msg.source, msg.message);
|
||||
throw new RuntimeException("GL ERROR: "+msg.toString());
|
||||
}
|
||||
RuntimeException e = new RuntimeException("GL MESSAGE: "+msg.toString());
|
||||
switch (s) {
|
||||
case HIGH:
|
||||
ApiShared.LOGGER.error(e);
|
||||
break;
|
||||
case MEDIUM:
|
||||
ApiShared.LOGGER.warn(e);
|
||||
break;
|
||||
case LOW:
|
||||
ApiShared.LOGGER.info(e);
|
||||
break;
|
||||
case NOTIFICATION:
|
||||
ApiShared.LOGGER.debug(e);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws IllegalStateException
|
||||
@@ -158,9 +190,35 @@ public class GLProxy
|
||||
*/
|
||||
private GLProxy()
|
||||
{
|
||||
lodBuilderDebugMessageBuilder = new GLMessage.Builder(
|
||||
(type) -> {
|
||||
if (type == GLMessage.Type.POP_GROUP) return false;
|
||||
if (type == GLMessage.Type.PUSH_GROUP) return false;
|
||||
if (type == GLMessage.Type.MARKER) return false;
|
||||
// if (type == GLMessage.Type.PERFORMANCE) return false;
|
||||
return true;
|
||||
}
|
||||
,(severity) -> {
|
||||
if (severity == GLMessage.Severity.NOTIFICATION) return false;
|
||||
return true;
|
||||
},null
|
||||
);
|
||||
proxyWorkerDebugMessageBuilder = new GLMessage.Builder(
|
||||
(type) -> {
|
||||
if (type == GLMessage.Type.POP_GROUP) return false;
|
||||
if (type == GLMessage.Type.PUSH_GROUP) return false;
|
||||
if (type == GLMessage.Type.MARKER) return false;
|
||||
// if (type == GLMessage.Type.PERFORMANCE) return false;
|
||||
return true;
|
||||
}
|
||||
,(severity) -> {
|
||||
if (severity == GLMessage.Severity.NOTIFICATION) return false;
|
||||
return true;
|
||||
},null
|
||||
);
|
||||
|
||||
|
||||
|
||||
// boolean enableDebugLogging = CONFIG.client().advanced().debugging().getDebugMode() == DebugMode.SHOW_DETAIL;
|
||||
boolean enableDebugLogging = true;
|
||||
// this must be created on minecraft's render context to work correctly
|
||||
|
||||
ApiShared.LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see in the log there must have been a OpenGL error.");
|
||||
@@ -194,6 +252,8 @@ public class GLProxy
|
||||
}
|
||||
ApiShared.LOGGER.info("minecraftGlCapabilities:\n"+getVersionInfo(minecraftGlCapabilities));
|
||||
|
||||
GLFW.glfwMakeContextCurrent(0L);
|
||||
|
||||
// context creation setup
|
||||
GLFW.glfwDefaultWindowHints();
|
||||
// make the context window invisible
|
||||
@@ -203,17 +263,34 @@ public class GLProxy
|
||||
// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
// GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 5);
|
||||
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// create the LodBuilder context
|
||||
lodBuilderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Builder Window", 0L, minecraftGlContext);
|
||||
if (lodBuilderGlContext == 0) {
|
||||
ApiShared.LOGGER.error("ERROR: Failed to create GLFW context for OpenGL 3.2 with"
|
||||
+ " Forward Compat Core Profile! Your OS may have not been able to support it!");
|
||||
throw new UnsupportedOperationException("Forward Compat Core Profile 3.2 creation failure");
|
||||
}
|
||||
GLFW.glfwMakeContextCurrent(lodBuilderGlContext);
|
||||
lodBuilderGlCapabilities = GL.createCapabilities();
|
||||
ApiShared.LOGGER.info("lodBuilderGlCapabilities:\n"+getVersionInfo(lodBuilderGlCapabilities));
|
||||
GLFW.glfwMakeContextCurrent(0L);
|
||||
|
||||
// create the proxyWorker's context
|
||||
proxyWorkerGlContext = GLFW.glfwCreateWindow(64, 48, "LOD proxy worker Window", 0L, minecraftGlContext);
|
||||
if (proxyWorkerGlContext == 0) {
|
||||
ApiShared.LOGGER.error("ERROR: Failed to create GLFW context for OpenGL 3.2 with"
|
||||
+ " Forward Compat Core Profile! Your OS may have not been able to support it!");
|
||||
throw new UnsupportedOperationException("Forward Compat Core Profile 3.2 creation failure");
|
||||
}
|
||||
GLFW.glfwMakeContextCurrent(proxyWorkerGlContext);
|
||||
proxyWorkerGlCapabilities = GL.createCapabilities();
|
||||
ApiShared.LOGGER.info("proxyWorkerGlCapabilities:\n"+getVersionInfo(lodBuilderGlCapabilities));
|
||||
GLFW.glfwMakeContextCurrent(0L);
|
||||
|
||||
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
|
||||
VertexAttributeBufferBindingSupported = minecraftGlCapabilities.glBindVertexBuffer != 0L; // Nullptr
|
||||
@@ -228,22 +305,10 @@ public class GLProxy
|
||||
//==================================//
|
||||
|
||||
setGlContext(GLProxyContext.LOD_BUILDER);
|
||||
// TODO: Enable this but disable INFO logging
|
||||
|
||||
File proxyLog = new File("OpenGL-Lod-ProxyContext.log");
|
||||
try {
|
||||
proxyLog.createNewFile();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (enableDebugLogging)
|
||||
try {
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(proxyLog));
|
||||
} catch (FileNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream((msg) -> {
|
||||
logMessage(msg);
|
||||
}, lodBuilderDebugMessageBuilder), true));
|
||||
|
||||
// get specific capabilities
|
||||
// Check if we can use the Buffer Storage, which is available in GL4.4 or after
|
||||
@@ -270,20 +335,10 @@ public class GLProxy
|
||||
ApiShared.LOGGER.info("GPU Vendor [" + vendor + "], Preferred upload method is [" + preferredUploadMethod + "].");
|
||||
|
||||
setGlContext(GLProxyContext.PROXY_WORKER);
|
||||
File workerLog = new File("OpenGL-Lod-WorkerContext.log");
|
||||
try {
|
||||
workerLog.createNewFile();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (enableDebugLogging)
|
||||
try {
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(workerLog));
|
||||
} catch (FileNotFoundException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream((msg) -> {
|
||||
logMessage(msg);
|
||||
}, proxyWorkerDebugMessageBuilder), true));
|
||||
|
||||
//==========//
|
||||
// clean up //
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ComsumerOutputStream extends OutputStream
|
||||
{
|
||||
final Consumer<String> func;
|
||||
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
public ComsumerOutputStream(Consumer<String> func) {
|
||||
this.func = func;
|
||||
}
|
||||
@Override
|
||||
public void write(int b)
|
||||
{
|
||||
buffer.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
buffer.write(b);
|
||||
}
|
||||
@Override
|
||||
public void write(byte[] b,
|
||||
int off,
|
||||
int len) {
|
||||
buffer.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
String str = buffer.toString();
|
||||
buffer.reset();
|
||||
func.accept(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
buffer.close();
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,6 @@ package com.seibel.lod.core.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -196,11 +193,13 @@ public class DataPointUtil
|
||||
}
|
||||
|
||||
|
||||
private static SpamReducedLogger warnLogger = new SpamReducedLogger(1);
|
||||
|
||||
public static byte getGenerationMode(long dataPoint)
|
||||
{
|
||||
byte genMode = (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
if (doesItExist(dataPoint) && genMode==0) {
|
||||
ApiShared.LOGGER.warn("Existing datapoint with genMode 0 detected! This is invalid in DataPoint version 10!"
|
||||
if (warnLogger.canMaybeLog() && doesItExist(dataPoint) && genMode==0) {
|
||||
warnLogger.warnInc("Existing datapoint with genMode 0 detected! This is invalid in DataPoint version 10!"
|
||||
+ " This may be caused by old data that has not been updated correctly.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class GLMessage {
|
||||
static final String HEADER = "[LWJGL] OpenGL debug message";
|
||||
public final GLMessage.Type type;
|
||||
public final GLMessage.Severity severity;
|
||||
public final GLMessage.Source source;
|
||||
public final String id;
|
||||
public final String message;
|
||||
GLMessage(GLMessage.Type t, GLMessage.Severity s, GLMessage.Source sr, String id, String ms) {
|
||||
this.type = t;
|
||||
this.source = sr;
|
||||
this.severity = s;
|
||||
this.id = id;
|
||||
this.message = ms;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[level:"+severity+", type:"+type+", source:"+source+", id:"+id+", msg:{"+message+"}]";
|
||||
}
|
||||
|
||||
|
||||
public enum Type {
|
||||
ERROR,
|
||||
DEPRECATED_BEHAVIOR,
|
||||
UNDEFINED_BEHAVIOR,
|
||||
PORTABILITY,
|
||||
PERFORMANCE,
|
||||
MARKER,
|
||||
PUSH_GROUP,
|
||||
POP_GROUP,
|
||||
OTHER;
|
||||
public final String str;
|
||||
private Type() {
|
||||
str = super.toString().toUpperCase();
|
||||
}
|
||||
@Override
|
||||
public final String toString() {
|
||||
return str;
|
||||
}
|
||||
static final HashMap<String, GLMessage.Type> toEnum;
|
||||
static {
|
||||
toEnum = new HashMap<String, GLMessage.Type>();
|
||||
for (GLMessage.Type t : Type.values()) {
|
||||
toEnum.put(t.str, t);
|
||||
}
|
||||
}
|
||||
public final static GLMessage.Type get(String str) {
|
||||
return toEnum.get(str);
|
||||
}
|
||||
}
|
||||
public enum Source {
|
||||
API,
|
||||
WINDOW_SYSTEM,
|
||||
SHADER_COMPILER,
|
||||
THIRD_PARTY,
|
||||
APPLICATION,
|
||||
OTHER;
|
||||
public final String str;
|
||||
private Source() {
|
||||
str = super.toString().toUpperCase();
|
||||
}
|
||||
static final HashMap<String, GLMessage.Source> toEnum;
|
||||
static {
|
||||
toEnum = new HashMap<String, GLMessage.Source>();
|
||||
for (GLMessage.Source t : Source.values()) {
|
||||
toEnum.put(t.str, t);
|
||||
}
|
||||
}
|
||||
public final static GLMessage.Source get(String str) {
|
||||
return toEnum.get(str);
|
||||
}
|
||||
}
|
||||
public enum Severity {
|
||||
HIGH, MEDIUM, LOW, NOTIFICATION;
|
||||
public final String str;
|
||||
private Severity() {
|
||||
str = super.toString().toUpperCase();
|
||||
}
|
||||
static final HashMap<String, GLMessage.Severity> toEnum;
|
||||
static {
|
||||
toEnum = new HashMap<String, GLMessage.Severity>();
|
||||
for (GLMessage.Severity t : Severity.values()) {
|
||||
toEnum.put(t.str, t);
|
||||
}
|
||||
}
|
||||
public final static GLMessage.Severity get(String str) {
|
||||
return toEnum.get(str);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
GLMessage.Type type;
|
||||
GLMessage.Severity severity;
|
||||
GLMessage.Source source;
|
||||
Function<Type, Boolean> typeFilter;
|
||||
Function<Severity, Boolean> severityFilter;
|
||||
Function<Source, Boolean> sourceFilter;
|
||||
|
||||
String id;
|
||||
String message;
|
||||
int stage = 0;
|
||||
public Builder() {
|
||||
this(null, null, null);
|
||||
}
|
||||
public Builder(
|
||||
Function<Type, Boolean> typeFilter,
|
||||
Function<Severity, Boolean> severityFilter,
|
||||
Function<Source, Boolean> sourceFilter) {
|
||||
this.typeFilter = typeFilter;
|
||||
this.severityFilter = severityFilter;
|
||||
this.sourceFilter = sourceFilter;
|
||||
}
|
||||
|
||||
public GLMessage add(String str) {
|
||||
str = str.strip();
|
||||
if (str.isEmpty()) return null;
|
||||
boolean b = runStage(str);
|
||||
if (b && stage >= 16) {
|
||||
stage = 0;
|
||||
return new GLMessage(type, severity, source, id, message);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setTypeFilter(Function<Type, Boolean> typeFilter) {
|
||||
this.typeFilter = typeFilter;
|
||||
}
|
||||
public void setSeverityFilter(Function<Severity, Boolean> severityFilter) {
|
||||
this.severityFilter = severityFilter;
|
||||
}
|
||||
public void setSourceFilter(Function<Source, Boolean> sourceFilter) {
|
||||
this.sourceFilter = sourceFilter;
|
||||
}
|
||||
|
||||
private boolean runStage(String str) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
return checkAndIncStage(str, GLMessage.HEADER);
|
||||
case 1:
|
||||
return checkAndIncStage(str, "ID");
|
||||
case 2:
|
||||
return checkAndIncStage(str, ":");
|
||||
case 3:
|
||||
id = str;
|
||||
stage++;
|
||||
return true;
|
||||
case 4:
|
||||
return checkAndIncStage(str, "Source");
|
||||
case 5:
|
||||
return checkAndIncStage(str, ":");
|
||||
case 6:
|
||||
source = Source.get(str);
|
||||
if (sourceFilter!=null && !sourceFilter.apply(source)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 7:
|
||||
return checkAndIncStage(str, "Type");
|
||||
case 8:
|
||||
return checkAndIncStage(str, ":");
|
||||
case 9:
|
||||
type = Type.get(str);
|
||||
if (typeFilter!=null && !typeFilter.apply(type)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 10:
|
||||
return checkAndIncStage(str, "Severity");
|
||||
case 11:
|
||||
return checkAndIncStage(str, ":");
|
||||
case 12:
|
||||
severity = Severity.get(str);
|
||||
if (severityFilter!=null && !severityFilter.apply(severity)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 13:
|
||||
return checkAndIncStage(str, "Message");
|
||||
case 14:
|
||||
return checkAndIncStage(str, ":");
|
||||
case 15:
|
||||
message = str;
|
||||
stage++;
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkAndIncStage(String str, String comp) {
|
||||
boolean result = str.equals(comp);
|
||||
if (result) stage++;
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class GLMessageOutputStream extends OutputStream
|
||||
{
|
||||
final Consumer<GLMessage> func;
|
||||
final GLMessage.Builder builder;
|
||||
|
||||
|
||||
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
public GLMessageOutputStream(Consumer<GLMessage> func, GLMessage.Builder builder)
|
||||
{
|
||||
this.func = func;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b)
|
||||
{
|
||||
buffer.write(b);
|
||||
if (b=='\n') flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
String str = buffer.toString();
|
||||
GLMessage msg = builder.add(str);
|
||||
if (msg != null) func.accept(msg);
|
||||
buffer.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
flush();
|
||||
buffer.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user