mirror of
https://github.com/Qortal/AT.git
synced 2025-02-01 03:32:13 +00:00
Improved logging support
We now use a logger factory, which means loggers can be created per class. This allows use of 'wrapped' Apache log4j2 loggers with the added benefit of more accurate class/line-number reporting.
This commit is contained in:
parent
ee2a81430c
commit
466ffa4d4d
11
Java/src/main/java/org/ciyam/at/AtLogger.java
Normal file
11
Java/src/main/java/org/ciyam/at/AtLogger.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package org.ciyam.at;
|
||||||
|
|
||||||
|
public interface AtLogger {
|
||||||
|
|
||||||
|
void error(final String message);
|
||||||
|
|
||||||
|
void debug(final String message);
|
||||||
|
|
||||||
|
void echo(final String message);
|
||||||
|
|
||||||
|
}
|
7
Java/src/main/java/org/ciyam/at/AtLoggerFactory.java
Normal file
7
Java/src/main/java/org/ciyam/at/AtLoggerFactory.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package org.ciyam.at;
|
||||||
|
|
||||||
|
public interface AtLoggerFactory {
|
||||||
|
|
||||||
|
AtLogger create(final Class<?> loggerName);
|
||||||
|
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
package org.ciyam.at;
|
|
||||||
|
|
||||||
public interface LoggerInterface {
|
|
||||||
|
|
||||||
public void error(String message);
|
|
||||||
|
|
||||||
public void debug(String message);
|
|
||||||
|
|
||||||
public void echo(String message);
|
|
||||||
|
|
||||||
}
|
|
@ -126,7 +126,8 @@ public class MachineState {
|
|||||||
private boolean isFirstOpCodeAfterSleeping;
|
private boolean isFirstOpCodeAfterSleeping;
|
||||||
|
|
||||||
private API api;
|
private API api;
|
||||||
private LoggerInterface logger;
|
private AtLoggerFactory loggerFactory;
|
||||||
|
private AtLogger logger;
|
||||||
|
|
||||||
// NOTE: These are package-scope to allow easy access/operations in Opcode/FunctionCode.
|
// NOTE: These are package-scope to allow easy access/operations in Opcode/FunctionCode.
|
||||||
/* package */ ByteBuffer codeByteBuffer;
|
/* package */ ByteBuffer codeByteBuffer;
|
||||||
@ -137,7 +138,7 @@ public class MachineState {
|
|||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
/** For internal use when recreating a machine state */
|
/** For internal use when recreating a machine state */
|
||||||
private MachineState(API api, LoggerInterface logger, byte[] headerBytes) {
|
private MachineState(byte[] headerBytes, API api, AtLoggerFactory loggerFactory) {
|
||||||
if (headerBytes.length != HEADER_LENGTH)
|
if (headerBytes.length != HEADER_LENGTH)
|
||||||
throw new IllegalArgumentException("headerBytes length " + headerBytes.length + " incorrect, expected " + HEADER_LENGTH);
|
throw new IllegalArgumentException("headerBytes length " + headerBytes.length + " incorrect, expected " + HEADER_LENGTH);
|
||||||
|
|
||||||
@ -190,12 +191,13 @@ public class MachineState {
|
|||||||
this.currentBalance = 0;
|
this.currentBalance = 0;
|
||||||
this.previousBalance = 0;
|
this.previousBalance = 0;
|
||||||
this.steps = 0;
|
this.steps = 0;
|
||||||
this.logger = logger;
|
this.loggerFactory = loggerFactory;
|
||||||
|
this.logger = loggerFactory.create(MachineState.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For creating a new machine state */
|
/** For creating a new machine state */
|
||||||
public MachineState(API api, byte[] creationBytes) {
|
public MachineState(API api, AtLoggerFactory loggerFactory, byte[] creationBytes) {
|
||||||
this(api, null, Arrays.copyOfRange(creationBytes, 0, HEADER_LENGTH));
|
this(Arrays.copyOfRange(creationBytes, 0, HEADER_LENGTH), api, loggerFactory);
|
||||||
|
|
||||||
int expectedLength = HEADER_LENGTH + this.numCodePages * this.constants.CODE_PAGE_SIZE + this.numDataPages * this.constants.DATA_PAGE_SIZE;
|
int expectedLength = HEADER_LENGTH + this.numCodePages * this.constants.CODE_PAGE_SIZE + this.numDataPages * this.constants.DATA_PAGE_SIZE;
|
||||||
if (creationBytes.length != expectedLength)
|
if (creationBytes.length != expectedLength)
|
||||||
@ -210,8 +212,8 @@ public class MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** For creating a new machine state - used in tests */
|
/** For creating a new machine state - used in tests */
|
||||||
public MachineState(API api, LoggerInterface logger, byte[] headerBytes, byte[] codeBytes, byte[] dataBytes) {
|
public MachineState(API api, AtLoggerFactory loggerFactory, byte[] headerBytes, byte[] codeBytes, byte[] dataBytes) {
|
||||||
this(api, logger, headerBytes);
|
this(headerBytes, api, loggerFactory);
|
||||||
|
|
||||||
if (codeBytes.length > this.numCodePages * this.constants.CODE_PAGE_SIZE)
|
if (codeBytes.length > this.numCodePages * this.constants.CODE_PAGE_SIZE)
|
||||||
throw new IllegalArgumentException("Number of code pages too small to hold code bytes");
|
throw new IllegalArgumentException("Number of code pages too small to hold code bytes");
|
||||||
@ -342,7 +344,11 @@ public class MachineState {
|
|||||||
return this.api;
|
return this.api;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoggerInterface getLogger() {
|
public AtLoggerFactory getLoggerFactory() {
|
||||||
|
return this.loggerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ AtLogger getLogger() {
|
||||||
return this.logger;
|
return this.logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,13 +522,13 @@ public class MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** For restoring a previously serialized machine state */
|
/** For restoring a previously serialized machine state */
|
||||||
public static MachineState fromBytes(API api, LoggerInterface logger, byte[] bytes, byte[] codeBytes) {
|
public static MachineState fromBytes(API api, AtLoggerFactory loggerFactory, byte[] bytes, byte[] codeBytes) {
|
||||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||||
|
|
||||||
byte[] headerBytes = new byte[HEADER_LENGTH];
|
byte[] headerBytes = new byte[HEADER_LENGTH];
|
||||||
byteBuffer.get(headerBytes);
|
byteBuffer.get(headerBytes);
|
||||||
|
|
||||||
MachineState state = new MachineState(api, logger, headerBytes);
|
MachineState state = new MachineState(headerBytes, api, loggerFactory);
|
||||||
|
|
||||||
if (codeBytes.length != state.codeByteBuffer.capacity())
|
if (codeBytes.length != state.codeByteBuffer.capacity())
|
||||||
throw new IllegalStateException("Passed codeBytes does not match length in header");
|
throw new IllegalStateException("Passed codeBytes does not match length in header");
|
||||||
|
@ -62,7 +62,7 @@ public class MiscTests extends ExecutableTest {
|
|||||||
byte[] codeBytes = codeByteBuffer.array();
|
byte[] codeBytes = codeByteBuffer.array();
|
||||||
byte[] dataBytes = new byte[0];
|
byte[] dataBytes = new byte[0];
|
||||||
|
|
||||||
state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes);
|
state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes);
|
||||||
|
|
||||||
assertTrue(state.isFrozen());
|
assertTrue(state.isFrozen());
|
||||||
assertEquals((Long) (minActivationAmount - 1L), state.getFrozenBalance());
|
assertEquals((Long) (minActivationAmount - 1L), state.getFrozenBalance());
|
||||||
|
@ -102,12 +102,12 @@ public class SerializationTests extends ExecutableTest {
|
|||||||
byte[] codeBytes = codeByteBuffer.array();
|
byte[] codeBytes = codeByteBuffer.array();
|
||||||
byte[] dataBytes = dataByteBuffer.array();
|
byte[] dataBytes = dataByteBuffer.array();
|
||||||
|
|
||||||
state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes);
|
state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes);
|
||||||
packedState = state.toBytes();
|
packedState = state.toBytes();
|
||||||
|
|
||||||
byte[] creationBytes = MachineState.toCreationBytes(TestUtils.VERSION, codeBytes, dataBytes, TestUtils.NUM_CALL_STACK_PAGES, TestUtils.NUM_USER_STACK_PAGES, TestUtils.MIN_ACTIVATION_AMOUNT);
|
byte[] creationBytes = MachineState.toCreationBytes(TestUtils.VERSION, codeBytes, dataBytes, TestUtils.NUM_CALL_STACK_PAGES, TestUtils.NUM_USER_STACK_PAGES, TestUtils.MIN_ACTIVATION_AMOUNT);
|
||||||
|
|
||||||
MachineState restoredState = new MachineState(api, creationBytes);
|
MachineState restoredState = new MachineState(api, loggerFactory, creationBytes);
|
||||||
byte[] packedRestoredSate = restoredState.toBytes();
|
byte[] packedRestoredSate = restoredState.toBytes();
|
||||||
|
|
||||||
assertTrue(Arrays.equals(packedState, packedRestoredSate));
|
assertTrue(Arrays.equals(packedState, packedRestoredSate));
|
||||||
@ -118,14 +118,14 @@ public class SerializationTests extends ExecutableTest {
|
|||||||
byte[] codeBytes = codeByteBuffer.array();
|
byte[] codeBytes = codeByteBuffer.array();
|
||||||
byte[] dataBytes = new byte[0];
|
byte[] dataBytes = new byte[0];
|
||||||
|
|
||||||
state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes);
|
state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes);
|
||||||
|
|
||||||
return executeAndCheck(state);
|
return executeAndCheck(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] continueSimulation(byte[] savedState) {
|
private byte[] continueSimulation(byte[] savedState) {
|
||||||
byte[] codeBytes = codeByteBuffer.array();
|
byte[] codeBytes = codeByteBuffer.array();
|
||||||
state = MachineState.fromBytes(api, logger, savedState, codeBytes);
|
state = MachineState.fromBytes(api, loggerFactory, savedState, codeBytes);
|
||||||
|
|
||||||
// Pretend we're on next block
|
// Pretend we're on next block
|
||||||
api.bumpCurrentBlockHeight();
|
api.bumpCurrentBlockHeight();
|
||||||
@ -141,7 +141,7 @@ public class SerializationTests extends ExecutableTest {
|
|||||||
byte[] codeBytes = state.getCodeBytes();
|
byte[] codeBytes = state.getCodeBytes();
|
||||||
|
|
||||||
// Rebuild new MachineState using fetched state & bytes
|
// Rebuild new MachineState using fetched state & bytes
|
||||||
MachineState restoredState = MachineState.fromBytes(api, logger, stateBytes, codeBytes);
|
MachineState restoredState = MachineState.fromBytes(api, loggerFactory, stateBytes, codeBytes);
|
||||||
// Extract rebuilt state and code bytes
|
// Extract rebuilt state and code bytes
|
||||||
byte[] restoredStateBytes = restoredState.toBytes();
|
byte[] restoredStateBytes = restoredState.toBytes();
|
||||||
byte[] restoredCodeBytes = state.getCodeBytes();
|
byte[] restoredCodeBytes = state.getCodeBytes();
|
||||||
|
@ -14,7 +14,7 @@ public abstract class ExecutableTest {
|
|||||||
private static final int DATA_OFFSET = MachineState.HEADER_LENGTH; // code bytes are not present
|
private static final int DATA_OFFSET = MachineState.HEADER_LENGTH; // code bytes are not present
|
||||||
private static final int CALL_STACK_OFFSET = DATA_OFFSET + TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE;
|
private static final int CALL_STACK_OFFSET = DATA_OFFSET + TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE;
|
||||||
|
|
||||||
public TestLogger logger;
|
public TestLoggerFactory loggerFactory;
|
||||||
public TestAPI api;
|
public TestAPI api;
|
||||||
public MachineState state;
|
public MachineState state;
|
||||||
public ByteBuffer codeByteBuffer;
|
public ByteBuffer codeByteBuffer;
|
||||||
@ -32,7 +32,7 @@ public abstract class ExecutableTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void beforeTest() {
|
public void beforeTest() {
|
||||||
logger = new TestLogger();
|
loggerFactory = new TestLoggerFactory();
|
||||||
api = new TestAPI();
|
api = new TestAPI();
|
||||||
codeByteBuffer = ByteBuffer.allocate(TestUtils.NUM_CODE_PAGES * MachineState.OPCODE_SIZE);
|
codeByteBuffer = ByteBuffer.allocate(TestUtils.NUM_CODE_PAGES * MachineState.OPCODE_SIZE);
|
||||||
dataByteBuffer = ByteBuffer.allocate(TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE);
|
dataByteBuffer = ByteBuffer.allocate(TestUtils.NUM_DATA_PAGES * MachineState.VALUE_SIZE);
|
||||||
@ -47,7 +47,7 @@ public abstract class ExecutableTest {
|
|||||||
codeByteBuffer = null;
|
codeByteBuffer = null;
|
||||||
dataByteBuffer = null;
|
dataByteBuffer = null;
|
||||||
api = null;
|
api = null;
|
||||||
logger = null;
|
loggerFactory = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void execute(boolean onceOnly) {
|
protected void execute(boolean onceOnly) {
|
||||||
@ -58,12 +58,12 @@ public abstract class ExecutableTest {
|
|||||||
if (packedState == null) {
|
if (packedState == null) {
|
||||||
// First time
|
// First time
|
||||||
System.out.println("First execution - deploying...");
|
System.out.println("First execution - deploying...");
|
||||||
state = new MachineState(api, logger, headerBytes, codeBytes, dataBytes);
|
state = new MachineState(api, loggerFactory, headerBytes, codeBytes, dataBytes);
|
||||||
packedState = state.toBytes();
|
packedState = state.toBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
state = MachineState.fromBytes(api, logger, packedState, codeBytes);
|
state = MachineState.fromBytes(api, loggerFactory, packedState, codeBytes);
|
||||||
|
|
||||||
System.out.println("Starting execution round!");
|
System.out.println("Starting execution round!");
|
||||||
System.out.println("Current block height: " + api.getCurrentBlockHeight());
|
System.out.println("Current block height: " + api.getCurrentBlockHeight());
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package org.ciyam.at.test;
|
package org.ciyam.at.test;
|
||||||
|
|
||||||
import org.ciyam.at.LoggerInterface;
|
import org.ciyam.at.AtLogger;
|
||||||
|
|
||||||
|
public class TestLogger implements AtLogger {
|
||||||
|
|
||||||
public class TestLogger implements LoggerInterface {
|
|
||||||
@Override
|
@Override
|
||||||
public void error(String message) {
|
public void error(String message) {
|
||||||
System.err.println("ERROR: " + message);
|
System.err.println("ERROR: " + message);
|
||||||
|
13
Java/src/test/java/org/ciyam/at/test/TestLoggerFactory.java
Normal file
13
Java/src/test/java/org/ciyam/at/test/TestLoggerFactory.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package org.ciyam.at.test;
|
||||||
|
|
||||||
|
import org.ciyam.at.AtLogger;
|
||||||
|
import org.ciyam.at.AtLoggerFactory;
|
||||||
|
|
||||||
|
public class TestLoggerFactory implements AtLoggerFactory {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AtLogger create(Class<?> loggerName) {
|
||||||
|
return new TestLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user