From 7b66b83ccb818f6d389bf74777f166612a711ff7 Mon Sep 17 00:00:00 2001 From: dsplayerX Date: Mon, 27 May 2024 13:47:06 +0530 Subject: [PATCH] Refactor transaction log managers to use singleton pattern --- .../runtime/transactions/FileRecoveryLog.java | 25 +++++++++++-------- .../transactions/InMemoryRecoveryLog.java | 18 ++++++++----- .../runtime/transactions/LogManager.java | 6 +++-- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/FileRecoveryLog.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/FileRecoveryLog.java index 290929427a6c..7bce25d7ee38 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/FileRecoveryLog.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/FileRecoveryLog.java @@ -21,8 +21,6 @@ import io.ballerina.runtime.internal.diagnostics.RuntimeDiagnosticLog; import io.ballerina.runtime.internal.errors.ErrorCodes; import io.ballerina.runtime.internal.util.RuntimeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.File; @@ -35,6 +33,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; +import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -46,9 +45,8 @@ * * @since 2201.9.0 */ -public class FileRecoveryLog implements RecoveryLog { +public final class FileRecoveryLog implements RecoveryLog { - private static final Logger log = LoggerFactory.getLogger(FileRecoveryLog.class); private static final String LOG_FILE_NUMBER = "(\\d+)"; private static final String LOG_FILE_EXTENSION = ".log"; private final String baseFileName; @@ -61,6 +59,7 @@ public class FileRecoveryLog implements RecoveryLog { private Map existingLogs; private static final PrintStream stderr = System.err; private final RuntimeDiagnosticLog diagnosticLog = new RuntimeDiagnosticLog(); + private static FileRecoveryLog instance; /** * Initializes a new FileRecoveryLog instance with the given base file name. @@ -70,16 +69,25 @@ public class FileRecoveryLog implements RecoveryLog { * @param recoveryLogDir The directory to store the recovery log files in. * @param deleteOldLogs Whether to delete old log files when creating a new one. */ - public FileRecoveryLog(String baseFileName, int checkpointInterval, Path recoveryLogDir, boolean deleteOldLogs) { + private FileRecoveryLog(String baseFileName, int checkpointInterval, Path recoveryLogDir, boolean deleteOldLogs) { this.baseFileName = baseFileName; this.recoveryLogDir = recoveryLogDir; this.deleteOldLogs = deleteOldLogs; this.checkpointInterval = checkpointInterval; this.existingLogs = new HashMap<>(); - this.logFile = createNextVersion(); this.numOfPutsSinceLastCheckpoint = 0; } + public static FileRecoveryLog getInstance(String baseFileName, int checkpointInterval, Path recoveryLogDir, + boolean deleteOldLogs) { + if (instance != null) { + throw new IllegalStateException("instance already exists"); + } + instance = new FileRecoveryLog(baseFileName, checkpointInterval, recoveryLogDir, deleteOldLogs); + instance.logFile = instance.createNextVersion(); + return instance; + } + /** * Creates the next version of the recovery log file, cleaning up the previous one. * @@ -194,9 +202,6 @@ public void putAll(Map trxRecords) { public Map getPendingLogs() { Map pendingTransactions = new HashMap<>(); Map transactionLogs = readLogsFromFile(logFile); - if (transactionLogs == null) { - return null; - } for (Map.Entry entry : transactionLogs.entrySet()) { String trxId = entry.getKey(); TransactionLogRecord trxRecord = entry.getValue(); @@ -234,7 +239,7 @@ private void writeToFile(String str, boolean force) { */ private Map readLogsFromFile(File file) { if (!file.exists() || file.length() == 0) { - return null; + return Collections.emptyMap(); } if (fileLockAndChannel != null) { closeEverything(); diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/InMemoryRecoveryLog.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/InMemoryRecoveryLog.java index 85b0b94011a7..0c640c62a3de 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/InMemoryRecoveryLog.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/InMemoryRecoveryLog.java @@ -28,14 +28,20 @@ * * @since 2201.9.0 */ -public class InMemoryRecoveryLog implements RecoveryLog { +public final class InMemoryRecoveryLog implements RecoveryLog { - private final Map transactionLogs; - private int numOfPutsSinceLastCheckpoint; + private final Map transactionLogs = new ConcurrentHashMap<>(); + private int numOfPutsSinceLastCheckpoint = 0; + private static InMemoryRecoveryLog instance; - public InMemoryRecoveryLog() { - this.transactionLogs = new ConcurrentHashMap<>(); - this.numOfPutsSinceLastCheckpoint = 0; + private InMemoryRecoveryLog() { + } + + public static InMemoryRecoveryLog getInstance() { + if (instance == null) { + instance = new InMemoryRecoveryLog(); + } + return instance; } @Override diff --git a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/LogManager.java b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/LogManager.java index a4a6a81e2c28..adae7e25969a 100644 --- a/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/LogManager.java +++ b/bvm/ballerina-runtime/src/main/java/io/ballerina/runtime/transactions/LogManager.java @@ -27,6 +27,7 @@ * @since 2201.9.0 */ public class LogManager { + private final FileRecoveryLog fileRecoveryLog; private final InMemoryRecoveryLog inMemoryRecoveryLog; @@ -40,8 +41,9 @@ public class LogManager { * @param deleteOldLogs the delete old logs flag */ public LogManager(String baseFileName, int checkpointInterval, Path recoveryLogDir, boolean deleteOldLogs) { - this.fileRecoveryLog = new FileRecoveryLog(baseFileName, checkpointInterval, recoveryLogDir, deleteOldLogs); - this.inMemoryRecoveryLog = new InMemoryRecoveryLog(); + this.fileRecoveryLog = + FileRecoveryLog.getInstance(baseFileName, checkpointInterval, recoveryLogDir, deleteOldLogs); + this.inMemoryRecoveryLog = InMemoryRecoveryLog.getInstance(); init(); }