From 37e47370a9d056f903963457c00438ead354ffa0 Mon Sep 17 00:00:00 2001 From: Nick Breitling Date: Wed, 17 Jul 2024 19:18:36 +0200 Subject: [PATCH] removed logging --- src/main/java/org/prlprg/AppConfig.java | 20 --- .../java/org/prlprg/rds/RDSInputStream.java | 11 +- src/main/java/org/prlprg/rds/RDSLogger.java | 121 ---------------- .../java/org/prlprg/rds/RDSOutputStream.java | 10 +- src/main/java/org/prlprg/rds/RDSReader.java | 129 ++---------------- src/main/java/org/prlprg/rds/RDSWriter.java | 109 +-------------- .../java/org/prlprg/rds/RDSWriterTest.java | 45 +++--- 7 files changed, 41 insertions(+), 404 deletions(-) delete mode 100644 src/main/java/org/prlprg/rds/RDSLogger.java diff --git a/src/main/java/org/prlprg/AppConfig.java b/src/main/java/org/prlprg/AppConfig.java index 9566d07d3..d59981766 100644 --- a/src/main/java/org/prlprg/AppConfig.java +++ b/src/main/java/org/prlprg/AppConfig.java @@ -49,14 +49,6 @@ public final class AppConfig extends Config { public static final OptimizationLogLevel OPTIMIZATION_LOG_LEVEL = get("OPTIMIZATION_LOG_LEVEL", OptimizationLogLevel.NONE); - /** - * How to log RDS reads and writes. Useful for diagnosing misalignments between input and output - * streams. - * - *

Default:: {@link RDSLogLevel#NONE} - */ - public static final RDSLogLevel RDS_LOG_LEVEL = get("RDS_LOG_LEVEL", RDSLogLevel.NONE); - public enum CfgDebugLevel { /** No extra checks. */ NONE, @@ -82,18 +74,6 @@ public enum OptimizationLogLevel implements Comparable { /** Log every optimization pass and every inner {@link CodeObject} it's applied to. */ ALL, } - - public enum RDSLogLevel implements Comparable { - /** Don't log any RDS input or output */ - NONE, - /** Only log RDS input and output directly from tests */ - TEST, - /** - * Log general RDS input and output, such as from base initialization (WARNING: logging general - * output may cause very large files to be generated, or even lead to out-of-memory errors) - */ - GENERAL, - } } /** diff --git a/src/main/java/org/prlprg/rds/RDSInputStream.java b/src/main/java/org/prlprg/rds/RDSInputStream.java index f1a905851..e05f13ce1 100644 --- a/src/main/java/org/prlprg/rds/RDSInputStream.java +++ b/src/main/java/org/prlprg/rds/RDSInputStream.java @@ -8,11 +8,9 @@ class RDSInputStream implements Closeable { private final DataInputStream in; - private final RDSLogger logger; - RDSInputStream(InputStream in, RDSLogger logger) { + RDSInputStream(InputStream in) { this.in = new DataInputStream(in); - this.logger = logger; } @Override @@ -28,25 +26,21 @@ public void close() throws IOException { */ public int readRaw() throws IOException { var input = in.read(); - logger.log(input); return input; } public byte readByte() throws IOException { var input = in.readByte(); - logger.log(input); return input; } public int readInt() throws IOException { var input = in.readInt(); - logger.log(input); return input; } public double readDouble() throws IOException { var input = in.readDouble(); - logger.log(input); return input; } @@ -54,7 +48,6 @@ public String readString(int natEncSize, Charset charset) throws IOException { var buf = new byte[natEncSize]; in.readFully(buf, 0, natEncSize); var input = new String(buf, charset); - logger.log(input); return input; } @@ -64,7 +57,6 @@ public int[] readInts(int length) throws IOException { var n = in.readInt(); ints[i] = n; } - logger.logInts(ints); return ints; } @@ -74,7 +66,6 @@ public double[] readDoubles(int length) throws IOException { var n = in.readDouble(); doubles[i] = n; } - logger.logDoubles(doubles); return doubles; } } diff --git a/src/main/java/org/prlprg/rds/RDSLogger.java b/src/main/java/org/prlprg/rds/RDSLogger.java deleted file mode 100644 index c311a10f6..000000000 --- a/src/main/java/org/prlprg/rds/RDSLogger.java +++ /dev/null @@ -1,121 +0,0 @@ -package org.prlprg.rds; - -import java.util.*; -import java.util.function.Supplier; -import java.util.logging.*; -import org.prlprg.AppConfig; - -final class RDSLogger { - private final StringBuilder output = new StringBuilder(); - private final boolean shouldLog; - private int indentLevel; - - /** - * @param name a description of the read or write, printed at the start of logging - */ - RDSLogger(String name, AppConfig.RDSLogLevel logLevel) { - this.indentLevel = 0; - this.shouldLog = AppConfig.RDS_LOG_LEVEL.compareTo(logLevel) >= 0; - logString(() -> name); - } - - /** Globally enables log output to the provided handler */ - public static void addHandler(Handler handler) { - var logger = Logger.getLogger(RDSLogger.class.getName()); - logger.addHandler(handler); - handler.setLevel(Level.FINE); - } - - /** - * Logs a lazily-evaluated String with the current indent level with Level.FINE. - * - * @param msg a thunk supplying the String to be logged. - */ - private void logString(Supplier msg) { - if (shouldLog) { - int level = this.indentLevel; - String indent = String.join("", Collections.nCopies(level, " ")); - output.append(indent).append(msg.get()).append("\n"); - } - } - - // public void setOpLabel(String opLabel) { - // this.opLabel = opLabel; - // } - - /** - * Logs the reading or writing of a new SEXP by printing an identifier and increasing the - * indentation level by 1 - * - * @param sexpIdent a String identifying the SEXP being logged - */ - public void push(String sexpIdent) { - logString(() -> sexpIdent + " {"); - indentLevel++; - } - - /** - * Logs the end of the reading or writing of a SEXP by printing a closing brace and decreasing the - * indentation level by 1 - */ - public void pop() { - indentLevel--; - logString(() -> "}"); - } - - /** - * Lazily logs a value read from the input stream or written to the output stream - * - * @param the type of the value to be logged - * @param value the value to be logged - */ - public void log(T value) { - logString( - () -> - switch (value) { - case Integer i -> String.format("%d (%s)", i, Integer.toBinaryString(i)); - case Byte b -> String.format("%d (%s)", b, Integer.toBinaryString(b)); - default -> String.format("%s: %s", value); - }); - } - - /** - * Lazily logs an array of ints read from the input stream or written to the output stream - * - * @param ints the array to be logged - */ - public void logInts(int[] ints) { - logString(() -> String.format("%s", Arrays.toString(ints))); - } - - /** - * Lazily logs an array of doubles read from the input stream or written to the output stream - * - * @param doubles the array to be logged - */ - public void logDoubles(double[] doubles) { - logString(() -> String.format("%s", Arrays.toString(doubles))); - } - - /** - * Lazily logs an array of doubles read from the input stream or written to the output stream - * - * @param doubles the array to be logged - */ - public void logBytes(byte[] bytes) { - logString(() -> String.format("%s", Arrays.toString(bytes))); - } - - /** - * Writes the RDS output collected thus far to the system logger at level {@code Level.FINE}. This - * is written in one go rather than in individual messages to preserve formatting and reduce - * metadata stored with each message. - */ - public void finish() { - if (shouldLog) { - Logger logger = Logger.getLogger(RDSLogger.class.getName()); - logger.setLevel(Level.FINE); - logger.fine(output.toString()); - } - } -} diff --git a/src/main/java/org/prlprg/rds/RDSOutputStream.java b/src/main/java/org/prlprg/rds/RDSOutputStream.java index d687d3e5c..dccd27c1e 100644 --- a/src/main/java/org/prlprg/rds/RDSOutputStream.java +++ b/src/main/java/org/prlprg/rds/RDSOutputStream.java @@ -7,11 +7,9 @@ public class RDSOutputStream implements Closeable { private final DataOutputStream out; - private final RDSLogger logger; - RDSOutputStream(OutputStream out, RDSLogger logger) { + RDSOutputStream(OutputStream out) { this.out = new DataOutputStream(out); - this.logger = logger; } @Override @@ -21,17 +19,14 @@ public void close() throws IOException { public void writeByte(byte v) throws IOException { out.writeByte(v); - logger.log(v); } public void writeInt(int v) throws IOException { out.writeInt(v); - logger.log(v); } public void writeDouble(double v) throws IOException { out.writeDouble(v); - logger.log(v); } /** @@ -43,20 +38,17 @@ public void writeDouble(double v) throws IOException { */ public void writeBytes(byte[] v) throws IOException { out.write(v); - logger.logBytes(v); } public void writeInts(int[] v) throws IOException { for (int e : v) { out.writeInt(e); } - logger.logInts(v); } public void writeDoubles(double[] v) throws IOException { for (double e : v) { out.writeDouble(e); } - logger.logDoubles(v); } } diff --git a/src/main/java/org/prlprg/rds/RDSReader.java b/src/main/java/org/prlprg/rds/RDSReader.java index 0ff2f35e3..1406ac0d3 100644 --- a/src/main/java/org/prlprg/rds/RDSReader.java +++ b/src/main/java/org/prlprg/rds/RDSReader.java @@ -12,7 +12,6 @@ import java.nio.charset.Charset; import java.util.*; import javax.annotation.Nullable; -import org.prlprg.AppConfig; import org.prlprg.RSession; import org.prlprg.bc.Bc; import org.prlprg.primitive.Complex; @@ -46,7 +45,6 @@ public class RDSReader implements Closeable { private final RSession rsession; private final RDSInputStream in; private final List refTable = new ArrayList<>(128); - private final RDSLogger logger; // FIXME: this should include the logic from platform.c // or should we individually read the charset property of each SEXP? this will require @@ -54,21 +52,9 @@ public class RDSReader implements Closeable { // builtin/special? private final Charset nativeEncoding = Charset.defaultCharset(); - private RDSReader(RSession session, InputStream in, AppConfig.RDSLogLevel level) { + private RDSReader(RSession session, InputStream in) { this.rsession = session; - this.logger = new RDSLogger("=========== READING STREAM ===========", level); - this.in = new RDSInputStream(in, logger); - } - - /** - * Reads a SEXP from the provided file. By default, logs details at {@code RDSLogLevel.GENERAL}. - * - * @param session The current R session, used to supply special constructs such as the base - * environment and namespace - * @param file The file to read from - */ - public static SEXP readFile(RSession session, File file) throws IOException { - return readFile(session, file, AppConfig.RDSLogLevel.GENERAL); + this.in = new RDSInputStream(in); } /** @@ -77,44 +63,27 @@ public static SEXP readFile(RSession session, File file) throws IOException { * @param session The current R session, used to supply special constructs such as the base * environment and namespace * @param file The file to read from - * @param level The logging level details will be written at */ - public static SEXP readFile(RSession session, File file, AppConfig.RDSLogLevel level) - throws IOException { + public static SEXP readFile(RSession session, File file) throws IOException { try (var input = new FileInputStream(file)) { - return readStream(session, IO.maybeDecompress(input), level); + return readStream(session, IO.maybeDecompress(input)); } } - /** - * Reads a SEXP from the provided {@code InputStream}. By default, logs details at {@code - * RDSLogLevel.GENERAL}. - * - * @param session The current R session, used to supply special constructs such as the base - * environment and namespace - * @param input The stream to read from - */ - public static SEXP readStream(RSession session, InputStream input) throws IOException { - return readStream(session, input, AppConfig.RDSLogLevel.GENERAL); - } - /** * Reads a SEXP from the provided {@code InputStream}. * * @param session The current R session, used to supply special constructs such as the base * environment and namespace * @param input The stream to read from - * @param level The logging level details will be written at */ - public static SEXP readStream(RSession session, InputStream input, AppConfig.RDSLogLevel level) - throws IOException { - try (var reader = new RDSReader(session, input, level)) { + public static SEXP readStream(RSession session, InputStream input) throws IOException { + try (var reader = new RDSReader(session, input)) { return reader.read(); } } private void readHeader() throws IOException { - logger.push("Header"); if (in.readByte() != 'X') { throw new RDSException("Unsupported type (possibly compressed)"); @@ -131,8 +100,6 @@ private void readHeader() throws IOException { in.readInt(); // minimal reader version in.readInt(); - - logger.pop(); } public SEXP read() throws IOException { @@ -165,8 +132,8 @@ private SEXP readItem() throws IOException { case BCODE -> readByteCode(); case EXPR -> readExpr(flags); case PROM -> readPromise(flags); - case BUILTIN -> readBuiltin(false); - case SPECIAL -> readBuiltin(true); + case BUILTIN -> readBuiltinOrSpecial(); + case SPECIAL -> readBuiltinOrSpecial(); case CPLX -> readComplex(flags); default -> throw new RDSException("Unsupported SEXP type: " + s.sexp()); }; @@ -191,8 +158,6 @@ private SEXP readItem() throws IOException { } private SEXP readComplex(Flags flags) throws IOException { - logger.push("ComplexSXP"); - var length = in.readInt(); var cplx = ImmutableList.builder(); for (int i = 0; i < length; i++) { @@ -202,13 +167,10 @@ private SEXP readComplex(Flags flags) throws IOException { } var attributes = readAttributes(flags); - logger.pop(); return SEXPs.complex(cplx.build(), attributes); } - private SEXP readBuiltin(boolean special) throws IOException { - logger.push(special ? "SpecialSXP" : "BuiltinSXP"); - + private SEXP readBuiltinOrSpecial() throws IOException { var length = in.readInt(); var name = in.readString(length, nativeEncoding); @@ -222,15 +184,12 @@ private SEXP readBuiltin(boolean special) throws IOException { } private SEXP readPromise(Flags flags) throws IOException { - logger.push("PromiseSXP"); - // FIXME: do something with the attributes here? readAttributes(flags); var tag = flags.hasTag() ? readItem() : SEXPs.NULL; var val = readItem(); var expr = readItem(); - logger.pop(); if (tag instanceof NilSXP) { // If the tag is nil, the promise is evaluated return new PromSXP(expr, val, SEXPs.EMPTY_ENV); @@ -244,8 +203,6 @@ private SEXP readPromise(Flags flags) throws IOException { } private SEXP readNamespace() throws IOException { - logger.push("NamespaceSXP"); - var namespaceInfo = readStringVec(); if (namespaceInfo.size() != 2) { throw new RDSException("Expected 2-element list, got: " + namespaceInfo); @@ -254,14 +211,11 @@ private SEXP readNamespace() throws IOException { var namespace = rsession.getNamespace(namespaceInfo.get(0), namespaceInfo.get(1)); refTable.add(namespace); - logger.pop(); return namespace; } // Note that this method is not used to StringSXPs. private StrSXP readStringVec() throws IOException { - logger.push("String Vector"); - if (in.readInt() != 0) { // cf. InStringVec throw new RDSException("names in persistent strings are not supported yet"); @@ -273,13 +227,10 @@ private StrSXP readStringVec() throws IOException { strings.add(readChars()); } - logger.pop(); return SEXPs.string(strings); } private ExprSXP readExpr(Flags flags) throws IOException { - logger.push("ExprSXP"); - var length = in.readInt(); var sexps = new ArrayList(length); for (int i = 0; i < length; i++) { @@ -288,24 +239,18 @@ private ExprSXP readExpr(Flags flags) throws IOException { Attributes attributes = readAttributes(flags); - logger.pop(); return SEXPs.expr(sexps, attributes); } private BCodeSXP readByteCode() throws IOException { - logger.push("BCodeSXP"); - var length = in.readInt(); var reps = new SEXP[length]; var bc = readByteCode1(reps); - logger.pop(); return bc; } private BCodeSXP readByteCode1(SEXP[] reps) throws IOException { - logger.push("BCodeSXP (1)"); - @SuppressWarnings("SwitchStatementWithTooFewBranches") var code = switch (readItem()) { @@ -320,13 +265,10 @@ private BCodeSXP readByteCode1(SEXP[] reps) throws IOException { var consts = readByteCodeConsts(reps); var factory = new GNURByteCodeDecoderFactory(code.data(), consts); - logger.pop(); return SEXPs.bcode(factory.create()); } private List readByteCodeConsts(SEXP[] reps) throws IOException { - logger.push("BCodeSXP (consts)"); - var length = in.readInt(); var consts = new ArrayList(length); @@ -351,7 +293,6 @@ private List readByteCodeConsts(SEXP[] reps) throws IOException { } } - logger.pop(); return consts; } @@ -360,13 +301,10 @@ private List readByteCodeConsts(SEXP[] reps) throws IOException { // include a padding int so the next SEXP can be read in full. This is why the function accepts // an integer instead of an RDSItemType. private SEXP readByteCodeLang(int type, SEXP[] reps) throws IOException { - logger.push("BCodeSXP (lang)"); - // If the type is 0, we encountered a padding bit, meaning we jump back to "regular" SEXP // processing. if (type == 0) { var item = readItem(); - logger.pop(); return item; } @@ -399,7 +337,6 @@ private SEXP readByteCodeLang(int type, SEXP[] reps) throws IOException { }; }; - logger.pop(); return res; } @@ -480,8 +417,6 @@ private SEXP readByteCodeLang1(RDSItemType type, SEXP[] reps) throws IOException } private SEXP readRef(Flags flags) throws IOException { - logger.push("Reference"); - var index = flags.unpackRefIndex(); // if index is 0, it was too large to be packed with the flags and was therefore written // afterward @@ -491,15 +426,11 @@ private SEXP readRef(Flags flags) throws IOException { // since index is 1-based var ref = refTable.get(index - 1); - logger.log("REF: " + ref); - logger.pop(); return ref; } private LangSXP readLang(Flags flags) throws IOException { - logger.push("LangSXP"); - var attributes = readAttributes(flags); // We do not support tags for LangSXPs. It is technically possible to have a tag on a LangSXP @@ -518,8 +449,6 @@ private LangSXP readLang(Flags flags) throws IOException { } private String readChars() throws IOException { - logger.push("Chars"); - var flags = readFlags(); if (!flags.getType().isSexp(SEXPType.CHAR)) { throw new RDSException("Expected CHAR"); @@ -536,13 +465,10 @@ private String readChars() throws IOException { out = in.readString(length, encoding); } - logger.pop(); return out; } private StrSXP readStrs(Flags flags) throws IOException { - logger.push("StrSXP"); - var length = in.readInt(); var strings = ImmutableList.builderWithExpectedSize(length); for (int i = 0; i < length; i++) { @@ -551,14 +477,11 @@ private StrSXP readStrs(Flags flags) throws IOException { var attributes = readAttributes(flags); - logger.pop(); return SEXPs.string(strings.build(), attributes); } @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") private UserEnvSXP readEnv() throws IOException { - logger.push("UserEnvSXP"); - var item = new UserEnvSXP(); refTable.add(item); @@ -608,8 +531,6 @@ private UserEnvSXP readEnv() throws IOException { } private VecSXP readVec(Flags flags) throws IOException { - logger.push("VecSXP"); - var length = in.readInt(); var data = ImmutableList.builderWithExpectedSize(length); for (int i = 0; i < length; i++) { @@ -617,48 +538,36 @@ private VecSXP readVec(Flags flags) throws IOException { } var attributes = readAttributes(flags); - logger.pop(); return SEXPs.vec(data.build(), attributes); } private LglSXP readLogicals(Flags flags) throws IOException { - logger.push("LglSXP"); - var length = in.readInt(); var data = in.readInts(length); var attributes = readAttributes(flags); - logger.pop(); return SEXPs.logical( Arrays.stream(data).mapToObj(Logical::valueOf).collect(ImmutableList.toImmutableList()), attributes); } private RealSXP readReals(Flags flags) throws IOException { - logger.push("RealSXP"); - var length = in.readInt(); var data = in.readDoubles(length); var attributes = readAttributes(flags); - logger.pop(); return SEXPs.real(data, attributes); } private IntSXP readInts(Flags flags) throws IOException { - logger.push("IntSXP"); - var length = in.readInt(); var data = in.readInts(length); var attributes = readAttributes(flags); - logger.pop(); return SEXPs.integer(data, attributes); } private ListSXP readList(Flags flags) throws IOException { - logger.push("ListSXP"); - var data = ImmutableList.builder(); Attributes attributes = null; @@ -682,14 +591,11 @@ private ListSXP readList(Flags flags) throws IOException { flags = readFlags(); } - logger.pop(); // TODO: add the attributes here? return SEXPs.list(data.build()); } private CloSXP readClosure(Flags flags) throws IOException { - logger.push("CloSXP"); - var attributes = readAttributes(flags); if (!(readItem() instanceof EnvSXP env)) { throw new RDSException("Expected CLOENV to be environment"); @@ -699,20 +605,17 @@ private CloSXP readClosure(Flags flags) throws IOException { } var body = readItem(); - logger.pop(); return SEXPs.closure(formals, body, env, attributes); } private @Nullable String readTag(Flags flags) throws IOException { String tagVal; if (flags.hasTag()) { - logger.push("Tag"); if (readItem() instanceof RegSymSXP s) { tagVal = s.name(); } else { throw new RDSException("Expected tag to be a symbol"); } - logger.pop(); } else { tagVal = null; } @@ -733,8 +636,6 @@ private Attributes readAttributes(Flags flags) throws IOException { } private Attributes readAttributes() throws IOException { - logger.push("Attributes"); - if (readItem() instanceof ListSXP xs) { var attrs = new Attributes.Builder(); @@ -746,7 +647,6 @@ private Attributes readAttributes() throws IOException { attrs.put(attr, x.value()); } - logger.pop(); return attrs.build(); } else { throw new RDSException("Expected list"); @@ -754,27 +654,21 @@ private Attributes readAttributes() throws IOException { } private RegSymSXP readSymbol() throws IOException { - logger.push("RegSymSXP"); - var flags = readFlags(); - var s = readString(flags); + var s = readChars(flags); var item = SEXPs.symbol(s); refTable.add(item); - logger.pop(); return item; } - private String readString(Flags flags) throws IOException { - logger.push("String"); - + private String readChars(Flags flags) throws IOException { var len = in.readInt(); // charset should never be null for strings var charset = requireNonNull(flags.getLevels().encoding()); var data = in.readString(len, charset); - logger.pop(); return data; } @@ -786,6 +680,5 @@ private Flags readFlags() throws IOException { @Override public void close() throws IOException { in.close(); - logger.finish(); } } diff --git a/src/main/java/org/prlprg/rds/RDSWriter.java b/src/main/java/org/prlprg/rds/RDSWriter.java index 89d43d355..17808eff7 100644 --- a/src/main/java/org/prlprg/rds/RDSWriter.java +++ b/src/main/java/org/prlprg/rds/RDSWriter.java @@ -6,7 +6,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.DoubleStream; import java.util.stream.StreamSupport; -import org.prlprg.AppConfig; import org.prlprg.RVersion; import org.prlprg.primitive.Logical; import org.prlprg.sexp.*; @@ -18,22 +17,9 @@ public class RDSWriter implements Closeable { // refIndex is 1-based, so the first ref will have index 1 private int refIndex = 1; private final HashMap refTable = new HashMap<>(128); - private final RDSLogger logger; - protected RDSWriter(OutputStream out, AppConfig.RDSLogLevel level) { - this.logger = new RDSLogger("=========== WRITING STREAM ===========", level); - this.out = new RDSOutputStream(out, logger); - } - - /** - * Writes a SEXP to the provided output stream. By default, logs details at {@code - * RDSLogLevel.GENERAL}. - * - * @param output The stream to write to - * @param sexp the SEXP to write - */ - public static void writeStream(OutputStream output, SEXP sexp) throws IOException { - writeStream(output, sexp, AppConfig.RDSLogLevel.GENERAL); + protected RDSWriter(OutputStream out) { + this.out = new RDSOutputStream(out); } /** @@ -41,42 +27,26 @@ public static void writeStream(OutputStream output, SEXP sexp) throws IOExceptio * * @param output The stream to write to * @param sexp the SEXP to write - * @param level the logging level at which to write details */ - public static void writeStream(OutputStream output, SEXP sexp, AppConfig.RDSLogLevel level) - throws IOException { - try (var writer = new RDSWriter(output, level)) { + public static void writeStream(OutputStream output, SEXP sexp) throws IOException { + try (var writer = new RDSWriter(output)) { writer.write(sexp); } } - /** - * Writes a SEXP to the provided file. By default, logs details at {@code RDSLogLevel.GENERAL}. - * - * @param file The file to write to - * @param sexp the SEXP to write - */ - public static void writeFile(File file, SEXP sexp) throws IOException { - writeFile(file, sexp, AppConfig.RDSLogLevel.GENERAL); - } - /** * Writes a SEXP to the provided file. * * @param file The file to write to * @param sexp the SEXP to write - * @param level the logging level at which to write details */ - public static void writeFile(File file, SEXP sexp, AppConfig.RDSLogLevel level) - throws IOException { + public static void writeFile(File file, SEXP sexp) throws IOException { try (var output = new FileOutputStream(file)) { - writeStream(output, sexp, level); + writeStream(output, sexp); } } public void writeHeader() throws IOException { - logger.push("Header"); - // Could also be "B" (binary) and "A" (ASCII) but we only support XDR. // XDR just means big endian and DataInputStream/DataOutputStream from Java use BigEndian out.writeByte((byte) 'X'); @@ -92,8 +62,6 @@ public void writeHeader() throws IOException { // Minimal version of R required to read back out.writeInt(new RVersion(2, 3, 0, null).encode()); - - logger.pop(); } public void write(SEXP sexp) throws IOException { @@ -114,23 +82,18 @@ public void writeItem(SEXP s) throws IOException { case RDSItemType.Special special -> { switch (special) { case RDSItemType.Special.NAMESPACESXP -> { - logger.push("NamespaceSXP"); // add to the ref table refAdd(s); // write details about the namespace var namespace = (NamespaceEnvSXP) s; writeStringVec(SEXPs.string(namespace.name(), namespace.version())); - logger.pop(); } case RDSItemType.Special.REFSXP -> { // If the flags encoded a reference, then we may need to write the ref index (only if // it was too large to be packed in the flags) - logger.push("Reference"); if (flags.unpackRefIndex() == 0) { out.writeInt(refIndex); } - logger.log("REF: " + s); - logger.pop(); } default -> { /* nothing to write */ @@ -242,16 +205,12 @@ private Flags flags(SEXP s) { * such, it is essential to check if an object has attributes before invoking this method. */ private void writeAttributes(Attributes attrs) throws IOException { - logger.push("Attributes"); - if (attrs.isEmpty()) throw new IllegalArgumentException("Cannot write an empty set of attributes"); // convert to ListSXP var l = attrs.entrySet().stream().map(e -> new TaggedElem(e.getKey(), e.getValue())).toList(); // Write it writeItem(SEXPs.list(l)); - - logger.pop(); } private void writeAttributesIfPresent(SEXP s) throws IOException { @@ -261,10 +220,8 @@ private void writeAttributesIfPresent(SEXP s) throws IOException { /** Writes the tag of the provided TaggedElem, if one exists. If none exists, does nothing. */ private void writeTagIfPresent(TaggedElem elem) throws IOException { if (elem.hasTag()) { - logger.push("Tag"); // Convert the tag to a symbol, since we need to add it to the ref table writeItem(Objects.requireNonNull(elem.tagAsSymbol())); - logger.pop(); } } @@ -273,8 +230,6 @@ private void writeTagIfPresent(TaggedElem elem) throws IOException { * CHARSXP, we need to write metadata like flags. */ private void writeChars(String s) throws IOException { - logger.push("Chars"); - var flags = new Flags( RDSItemType.valueOf(SEXPType.CHAR.i), @@ -294,8 +249,6 @@ private void writeChars(String s) throws IOException { var bytes = s.getBytes(Charset.defaultCharset()); out.writeInt(bytes.length); out.writeBytes(bytes); - - logger.pop(); } /** @@ -305,23 +258,17 @@ private void writeChars(String s) throws IOException { * namespace and package environment spec. */ private void writeStringVec(StrSXP s) throws IOException { - logger.push("String Vector"); - out.writeInt(0); out.writeInt(s.size()); for (String str : s) { writeChars(str); } - - logger.pop(); } // STANDARD SEXPs ------------------------------------------------------------------------------- private void writeEnv(EnvSXP env) throws IOException { - logger.push("EnvSXP"); - // Add to the ref table refAdd(env); @@ -348,13 +295,9 @@ private void writeEnv(EnvSXP env) throws IOException { } else { throw new UnreachableError("Implemented as special RDS type: " + env.type()); } - - logger.pop(); } private void writeSymbol(SymSXP s) throws IOException { - logger.push("SymSXP"); - switch (s) { case RegSymSXP rs -> { // Add to the ref table @@ -368,8 +311,6 @@ private void writeSymbol(SymSXP s) throws IOException { default -> throw new UnsupportedOperationException("Unreachable: implemented in special sexps."); } - - logger.pop(); } private void writeBuiltinOrSpecialSXP(BuiltinOrSpecialSXP bos) throws IOException { @@ -384,8 +325,6 @@ private void writeBuiltinOrSpecialSXP(BuiltinOrSpecialSXP bos) throws IOExceptio } private void writeListSXP(ListSXP lsxp) throws IOException { - logger.push("ListSXP"); - Flags listFlags = flags(lsxp); // Write the first element. This case is separate because: @@ -410,24 +349,16 @@ private void writeListSXP(ListSXP lsxp) throws IOException { // Write a NilSXP to end the list writeItem(SEXPs.NULL); - - logger.pop(); } private void writeLangSXP(LangSXP lang) throws IOException { - logger.push("LangSXP"); - writeAttributesIfPresent(lang); // LangSXPs can have tags, but we don't support them, so no tag is written here writeItem(lang.fun()); writeItem(lang.args()); - - logger.pop(); } private void writePromSXP(PromSXP prom) throws IOException { - logger.push("PromSXP"); - writeAttributesIfPresent(prom); // TODO: test that this is the correct order of arguments @@ -439,25 +370,17 @@ private void writePromSXP(PromSXP prom) throws IOException { writeItem(prom.val()); writeItem(prom.expr()); - - logger.pop(); } private void writeCloSXP(CloSXP clo) throws IOException { - logger.push("CloSXP"); - writeAttributesIfPresent(clo); // a closure has the environment, formals, and then body writeItem(clo.env()); writeItem(clo.parameters()); writeItem(clo.body()); - - logger.pop(); } private void writeVectorSXP(VectorSXP s) throws IOException { - logger.push("VectorSXP"); - var length = s.size(); out.writeInt(length); @@ -511,8 +434,6 @@ private void writeVectorSXP(VectorSXP s) throws IOException { } writeAttributesIfPresent(s); - - logger.pop(); } // BYTECODE ------------------------------------------------------------------------------------- @@ -553,8 +474,6 @@ private void scanForCircles(SEXP sexp, HashMap reps, HashSet reps, AtomicInteger nextRepIndex) throws IOException { - logger.push("BCodeSXP (lang)"); - if (s instanceof LangOrListSXP lol && lol.type() != SEXPType.NIL) { var assignedRepIndex = reps.get(lol); if (assignedRepIndex != null) { @@ -573,7 +492,6 @@ private void writeByteCodeLang(SEXP s, HashMap reps, AtomicIntege out.writeInt(assignedRepIndex); // We also return, since the child nodes have already been written, and we don't want // to write them again - logger.pop(); return; } } @@ -622,14 +540,10 @@ private void writeByteCodeLang(SEXP s, HashMap reps, AtomicIntege out.writeInt(0); writeItem(s); } - - logger.pop(); } private void writeByteCode1(BCodeSXP s, HashMap reps, AtomicInteger nextRepIndex) throws IOException { - logger.push("BCodeSXP (1)"); - // Decode the bytecode (we will get a vector of integers) // write the vector of integers var encoder = new GNURByteCodeEncoderFactory(s.bc()); @@ -637,15 +551,11 @@ private void writeByteCode1(BCodeSXP s, HashMap reps, AtomicInteg var code_bytes = encoder.buildRaw(); writeItem(SEXPs.integer(code_bytes.getInstructions())); writeByteCodeConsts(code_bytes.getConsts(), reps, nextRepIndex); - - logger.pop(); } private void writeByteCodeConsts( List consts, HashMap reps, AtomicInteger nextRepIndex) throws IOException { - logger.push("BCodeSXP (consts)"); - // write the number of consts in the bytecode // iterate the consts: if it s bytecode, write the type and recurse // if it is langsxp or listsxp, write them , using the BCREDPEF, ATTRALANGSXP and ATTRLISTSXP @@ -669,13 +579,9 @@ private void writeByteCodeConsts( } } } - - logger.pop(); } private void writeByteCode(BCodeSXP s) throws IOException { - logger.push("BCodeSXP"); - // Scan for circles var reps = new HashMap(); var seen = new HashSet(); @@ -684,13 +590,10 @@ private void writeByteCode(BCodeSXP s) throws IOException { var nextRepIndex = new AtomicInteger(0); writeByteCode1(s, reps, nextRepIndex); - - logger.pop(); } @Override public void close() throws IOException { out.close(); - logger.finish(); } } diff --git a/src/test/java/org/prlprg/rds/RDSWriterTest.java b/src/test/java/org/prlprg/rds/RDSWriterTest.java index a3a55a991..5f70a56a5 100644 --- a/src/test/java/org/prlprg/rds/RDSWriterTest.java +++ b/src/test/java/org/prlprg/rds/RDSWriterTest.java @@ -10,7 +10,6 @@ import java.util.logging.*; import org.junit.jupiter.api.Test; import org.prlprg.AbstractGNURBasedTest; -import org.prlprg.AppConfig; import org.prlprg.bc.Compiler; import org.prlprg.primitive.Complex; import org.prlprg.primitive.Constants; @@ -23,10 +22,10 @@ public void testInts() throws Exception { var ints = SEXPs.integer(5, 4, 3, 2, 1); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, ints, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, ints); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof IntSXP read_ints) { assertEquals(5, read_ints.size()); @@ -63,10 +62,10 @@ public void testComplex() throws Exception { var complexes = SEXPs.complex(new Complex(0, 0), new Complex(1, 2), new Complex(-2, -1)); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, complexes, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, complexes); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof ComplexSXP read_complexes) { assertEquals(3, read_complexes.size()); @@ -104,10 +103,10 @@ public void testLang() throws Exception { new TaggedElem("arg", SEXPs.integer(1)), new TaggedElem(SEXPs.integer(2))))); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, lang, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, lang); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof LangSXP read_lang) { var name = read_lang.funName(); @@ -133,10 +132,10 @@ public void testVecAttributes() throws Exception { var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, ints, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, ints); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof IntSXP read_ints) { assertEquals(1, read_ints.size()); @@ -152,10 +151,10 @@ public void testLgls() throws Exception { var lgls = SEXPs.logical(Logical.TRUE, Logical.FALSE, Logical.NA); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, lgls, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, lgls); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof LglSXP read_lgls) { assertEquals(3, read_lgls.size()); @@ -172,10 +171,10 @@ public void testReals() throws Exception { var reals = SEXPs.real(5.2, 4.0, Constants.NA_REAL, 2.0, NaN, 1.0); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, reals, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, reals); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof RealSXP read_reals) { assertEquals(6, read_reals.size()); @@ -194,10 +193,10 @@ public void testReals() throws Exception { public void testNull() throws Exception { var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, SEXPs.NULL, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, SEXPs.NULL); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); assertEquals(SEXPs.NULL, sexp); } @@ -208,10 +207,10 @@ public void testVec() throws Exception { SEXPs.vec(SEXPs.integer(1, 2, 3), SEXPs.logical(Logical.TRUE, Logical.FALSE, Logical.NA)); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, vec, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, vec); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof VecSXP read_vec) { assertEquals(2, read_vec.size()); @@ -247,10 +246,10 @@ public void testList() throws Exception { var list = SEXPs.list(elems, Attributes.NONE); var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, list, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, list); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof ListSXP l) { assertEquals(3, l.size()); @@ -289,10 +288,10 @@ public void testEnv() throws Exception { var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, env, AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, env); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); if (sexp instanceof UserEnvSXP read_env) { assertEquals(4, read_env.size()); @@ -387,10 +386,10 @@ public void testClosureWithBC() throws Exception { var output = new ByteArrayOutputStream(); - RDSWriter.writeStream(output, SEXPs.bcode(bc), AppConfig.RDSLogLevel.TEST); + RDSWriter.writeStream(output, SEXPs.bcode(bc)); var input = new ByteArrayInputStream(output.toByteArray()); - var sexp = RDSReader.readStream(rsession, input, AppConfig.RDSLogLevel.TEST); + var sexp = RDSReader.readStream(rsession, input); assertEquals(sexp, SEXPs.bcode(bc)); }