From 4443d193a923b98a582ecb0e6ba4df8e9666f5e2 Mon Sep 17 00:00:00 2001 From: Tu Huynh <13906546+tuhuynh27@users.noreply.github.com> Date: Sun, 7 Mar 2021 02:13:30 +0700 Subject: [PATCH] Keva: Refactor Internal (#53) * rename keva socket * init initial * impl store * add publish --- keva/client/build.gradle | 8 +-- keva/server/build.gradle | 8 +-- .../keva/server/command/Del.java | 2 +- .../keva/server/command/Expire.java | 2 +- .../keva/server/command/Get.java | 2 +- .../keva/server/command/Set.java | 2 +- .../keva/server/core/ConnectionService.java | 2 +- .../server/core/ConnectionServiceImpl.java | 30 ++++----- .../keva/server/core/Server.java | 7 +- .../{KevaSocket.java => ServerSocket.java} | 2 +- .../keva/server/storage/StorageFactory.java | 12 ++-- keva/store/build.gradle | 67 +++++++++++++++++++ .../jinyframework/keva/store}/IndexStore.java | 2 +- .../keva/store}/IndexStoreImpl.java | 2 +- .../keva/store}/NoHeapStore.java | 2 +- .../keva/store}/NoHeapStoreImpl.java | 2 +- .../keva/store}/NoHeapStoreManager.java | 20 +++--- settings.gradle | 2 +- 18 files changed, 114 insertions(+), 60 deletions(-) rename keva/server/src/main/java/com/jinyframework/keva/server/core/{KevaSocket.java => ServerSocket.java} (95%) create mode 100644 keva/store/build.gradle rename keva/{server/src/main/java/com/jinyframework/keva/server/noheap => store/src/main/java/com/jinyframework/keva/store}/IndexStore.java (81%) rename keva/{server/src/main/java/com/jinyframework/keva/server/noheap => store/src/main/java/com/jinyframework/keva/store}/IndexStoreImpl.java (99%) rename keva/{server/src/main/java/com/jinyframework/keva/server/noheap => store/src/main/java/com/jinyframework/keva/store}/NoHeapStore.java (96%) rename keva/{server/src/main/java/com/jinyframework/keva/server/noheap => store/src/main/java/com/jinyframework/keva/store}/NoHeapStoreImpl.java (99%) rename keva/{server/src/main/java/com/jinyframework/keva/server/noheap => store/src/main/java/com/jinyframework/keva/store}/NoHeapStoreManager.java (74%) diff --git a/keva/client/build.gradle b/keva/client/build.gradle index 345c683..4224841 100644 --- a/keva/client/build.gradle +++ b/keva/client/build.gradle @@ -1,6 +1,4 @@ plugins { - id 'java' - id 'idea' id 'application' id 'com.github.johnrengelman.shadow' version '6.0.0' id 'com.adarshr.test-logger' version '2.1.0' @@ -12,14 +10,10 @@ version '1.0-SNAPSHOT' repositories { mavenCentral() } -dependencies { - compileOnly 'org.projectlombok:lombok:1.18.12' - implementation 'com.google.code.gson:gson:2.8.6' +dependencies { compile group: 'ch.qos.logback', name:'logback-classic', version: '1.0.9' compile group: 'ch.qos.logback', name:'logback-core', version: '1.0.9' - - annotationProcessor 'org.projectlombok:lombok:1.18.12' } shadowJar { diff --git a/keva/server/build.gradle b/keva/server/build.gradle index 6b0b076..03e99c5 100644 --- a/keva/server/build.gradle +++ b/keva/server/build.gradle @@ -1,6 +1,4 @@ plugins { - id 'java' - id 'idea' id 'application' id 'com.github.johnrengelman.shadow' version '6.0.0' id 'com.adarshr.test-logger' version '2.1.0' @@ -12,14 +10,12 @@ version '1.0-SNAPSHOT' repositories { mavenCentral() } + dependencies { - compileOnly 'org.projectlombok:lombok:1.18.12' - implementation 'com.google.code.gson:gson:2.8.6' + compile project(':keva:store') compile group: 'ch.qos.logback', name:'logback-classic', version: '1.0.9' compile group: 'ch.qos.logback', name:'logback-core', version: '1.0.9' - - annotationProcessor 'org.projectlombok:lombok:1.18.12' } shadowJar { diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/command/Del.java b/keva/server/src/main/java/com/jinyframework/keva/server/command/Del.java index b9291b9..9e2ef20 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/command/Del.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/command/Del.java @@ -1,6 +1,6 @@ package com.jinyframework.keva.server.command; -import com.jinyframework.keva.server.noheap.NoHeapStore; +import com.jinyframework.keva.store.NoHeapStore; import com.jinyframework.keva.server.storage.StorageFactory; import java.util.List; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/command/Expire.java b/keva/server/src/main/java/com/jinyframework/keva/server/command/Expire.java index 1d8c434..18be6ad 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/command/Expire.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/command/Expire.java @@ -1,6 +1,6 @@ package com.jinyframework.keva.server.command; -import com.jinyframework.keva.server.noheap.NoHeapStore; +import com.jinyframework.keva.store.NoHeapStore; import com.jinyframework.keva.server.storage.StorageFactory; import java.util.List; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/command/Get.java b/keva/server/src/main/java/com/jinyframework/keva/server/command/Get.java index ed7817b..1da9898 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/command/Get.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/command/Get.java @@ -1,6 +1,6 @@ package com.jinyframework.keva.server.command; -import com.jinyframework.keva.server.noheap.NoHeapStore; +import com.jinyframework.keva.store.NoHeapStore; import com.jinyframework.keva.server.storage.StorageFactory; import java.util.List; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/command/Set.java b/keva/server/src/main/java/com/jinyframework/keva/server/command/Set.java index de800c2..d7d29de 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/command/Set.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/command/Set.java @@ -1,6 +1,6 @@ package com.jinyframework.keva.server.command; -import com.jinyframework.keva.server.noheap.NoHeapStore; +import com.jinyframework.keva.store.NoHeapStore; import com.jinyframework.keva.server.storage.StorageFactory; import java.util.List; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionService.java b/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionService.java index 62fe49c..76bbe14 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionService.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionService.java @@ -1,7 +1,7 @@ package com.jinyframework.keva.server.core; public interface ConnectionService { - void handleConnection(KevaSocket kevaSocket); + void handleConnection(ServerSocket serverSocket); long getCurrentConnectedClients(); diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionServiceImpl.java b/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionServiceImpl.java index a1afe52..c4f44f1 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionServiceImpl.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/core/ConnectionServiceImpl.java @@ -18,14 +18,14 @@ public class ConnectionServiceImpl implements ConnectionService { private final CommandService commandService = ServiceFactory.getCommandService(); - private final Map socketMap = StorageFactory.getSocketHashMap(); + private final Map socketMap = StorageFactory.getSocketHashMap(); @Override - public void handleConnection(KevaSocket kevaSocket) { - val socketId = kevaSocket.getId(); + public void handleConnection(ServerSocket serverSocket) { + val socketId = serverSocket.getId(); try { - socketMap.put(socketId, kevaSocket); - val socket = kevaSocket.getSocket(); + socketMap.put(socketId, serverSocket); + val socket = serverSocket.getSocket(); val remoteAddr = socket.getRemoteSocketAddress(); log.info("{} {} connected", remoteAddr, socketId); @@ -33,15 +33,15 @@ public void handleConnection(KevaSocket kevaSocket) { val socketIn = new BufferedReader(new InputStreamReader(socket.getInputStream())); @Cleanup val socketOut = new PrintWriter(socket.getOutputStream()); - while (kevaSocket.isAlive()) { + while (serverSocket.isAlive()) { val line = socketIn.readLine(); if (line == null) { socketMap.remove(socketId); log.info("{} {} disconnected", remoteAddr, socketId); break; } - kevaSocket.getLastOnlineLong().set(System.currentTimeMillis()); - log.info("{} sent {}", kevaSocket.getId(), line); + serverSocket.getLastOnlineLong().set(System.currentTimeMillis()); + log.info("{} sent {}", serverSocket.getId(), line); commandService.handleCommand(socketOut, line); } } catch (SocketException e) { @@ -61,16 +61,16 @@ public Runnable getHeartbeatRunnable(long sockTimeout) { return () -> { log.info("Running heartbeat"); val now = System.currentTimeMillis(); - socketMap.values().forEach(kevaSocket -> { - if (kevaSocket.getLastOnline() + sockTimeout < now) { - kevaSocket.getAlive().set(false); + socketMap.values().forEach(serverSocket -> { + if (serverSocket.getLastOnline() + sockTimeout < now) { + serverSocket.getAlive().set(false); try { - kevaSocket.getSocket().close(); + serverSocket.getSocket().close(); } catch (IOException e) { - log.error("Error while closing socket {}: {}", kevaSocket.getId(), e); + log.error("Error while closing socket {}: {}", serverSocket.getId(), e); } - socketMap.remove(kevaSocket.getId()); - log.info("{} {} closed from timeout", kevaSocket.getSocket().getRemoteSocketAddress(), kevaSocket.getId()); + socketMap.remove(serverSocket.getId()); + log.info("{} {} closed from timeout", serverSocket.getSocket().getRemoteSocketAddress(), serverSocket.getId()); } }); }; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/core/Server.java b/keva/server/src/main/java/com/jinyframework/keva/server/core/Server.java index 476cae8..5b3d220 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/core/Server.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/core/Server.java @@ -7,7 +7,6 @@ import java.io.IOException; import java.net.InetSocketAddress; -import java.net.ServerSocket; import java.net.SocketException; import java.net.SocketTimeoutException; import java.util.UUID; @@ -26,7 +25,7 @@ public class Server { private final AtomicBoolean serverStopped = new AtomicBoolean(false); private final ConfigHolder config; - private ServerSocket serverSocket; + private java.net.ServerSocket serverSocket; private ExecutorService executor; public Server(ConfigHolder config) { @@ -39,7 +38,7 @@ private void startServer() throws IOException { executor = Executors.newCachedThreadPool(); val socketAddress = new InetSocketAddress(host, port); if (serverSocket == null) { - serverSocket = new ServerSocket(); + serverSocket = new java.net.ServerSocket(); } serverSocket.bind(socketAddress); @@ -73,7 +72,7 @@ public void run() throws IOException { break; } executor.execute(() -> { - val kevaSocket = KevaSocket.builder() + val kevaSocket = ServerSocket.builder() .socket(socket) .id(UUID.randomUUID().toString()) .lastOnlineLong(new AtomicLong(System.currentTimeMillis())) diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/core/KevaSocket.java b/keva/server/src/main/java/com/jinyframework/keva/server/core/ServerSocket.java similarity index 95% rename from keva/server/src/main/java/com/jinyframework/keva/server/core/KevaSocket.java rename to keva/server/src/main/java/com/jinyframework/keva/server/core/ServerSocket.java index 59ce21c..6cf89db 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/core/KevaSocket.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/core/ServerSocket.java @@ -11,7 +11,7 @@ @Builder @Getter @Setter -public class KevaSocket { +public class ServerSocket { private final Socket socket; private final String id; private AtomicLong lastOnlineLong; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/storage/StorageFactory.java b/keva/server/src/main/java/com/jinyframework/keva/server/storage/StorageFactory.java index bb04b10..091c3d8 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/storage/StorageFactory.java +++ b/keva/server/src/main/java/com/jinyframework/keva/server/storage/StorageFactory.java @@ -1,9 +1,9 @@ package com.jinyframework.keva.server.storage; +import com.jinyframework.keva.store.NoHeapStore; +import com.jinyframework.keva.store.NoHeapStoreManager; import com.jinyframework.keva.server.config.ConfigManager; -import com.jinyframework.keva.server.core.KevaSocket; -import com.jinyframework.keva.server.noheap.NoHeapStore; -import com.jinyframework.keva.server.noheap.NoHeapStoreManager; +import com.jinyframework.keva.server.core.ServerSocket; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import lombok.val; @@ -14,7 +14,7 @@ @Slf4j public final class StorageFactory { private static NoHeapStore noHeapStore; - private static ConcurrentHashMap socketHashMap; + private static ConcurrentHashMap socketHashMap; public synchronized static NoHeapStore getNoHeapDBStore() { if (noHeapStore == null) { @@ -24,7 +24,7 @@ public synchronized static NoHeapStore getNoHeapDBStore() { val heapSizeInMegabytes = ConfigManager.getConfig().getHeapSize(); db.createStore("Keva", shouldPersist ? NoHeapStore.Storage.PERSISTED : NoHeapStore.Storage.IN_MEMORY, - heapSizeInMegabytes); + heapSizeInMegabytes, ConfigManager.getConfig().getSnapshotLocation()); noHeapStore = db.getStore("Keva"); } catch (Exception ex) { log.error(ex.getMessage(), ex); @@ -36,7 +36,7 @@ public synchronized static NoHeapStore getNoHeapDBStore() { return noHeapStore; } - public synchronized static ConcurrentHashMap getSocketHashMap() { + public synchronized static ConcurrentHashMap getSocketHashMap() { if (socketHashMap == null) { socketHashMap = new ConcurrentHashMap<>(); } diff --git a/keva/store/build.gradle b/keva/store/build.gradle new file mode 100644 index 0000000..e11416b --- /dev/null +++ b/keva/store/build.gradle @@ -0,0 +1,67 @@ +plugins { + id 'com.adarshr.test-logger' version '2.1.0' +} + +java { + withJavadocJar() + withSourcesJar() +} + +publishing { + publications { + mavenJava(MavenPublication) { + artifactId = 'keva-store' + from components.java + versionMapping { + usage('java-api') { + fromResolutionOf('runtimeClasspath') + } + usage('java-runtime') { + fromResolutionResult() + } + } + pom { + name = 'Jiny Keva' + description = 'Performant & low-latency in-memory data structure store, used as a database or cache' + url = 'https://jinyframework.com/' + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'https://github.com/huynhminhtufu/jiny/blob/master/LICENSE' + } + } + developers { + developer { + id = 'tuhuynh27' + name = 'Tu Huynh' + email = 'huynhminhtufu@gmail.com' + } + } + scm { + connection = 'scm:git:git://github.com/huynhminhtufu/jiny.git' + developerConnection = 'scm:git:ssh://github.com:huynhminhtu/jiny.git' + url = 'https://github.com/huynhminhtufu/jiny/' + } + } + } + } +} + +javadoc { + if (JavaVersion.current().isJava9Compatible()) { + options.addBooleanOption('html5', true) + } +} + +signing { + sign publishing.publications.mavenJava +} + +test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + outputs.upToDateWhen { false } + showStandardStreams = true + } +} diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStore.java b/keva/store/src/main/java/com/jinyframework/keva/store/IndexStore.java similarity index 81% rename from keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStore.java rename to keva/store/src/main/java/com/jinyframework/keva/store/IndexStore.java index 2da9dda..b084f2d 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStore.java +++ b/keva/store/src/main/java/com/jinyframework/keva/store/IndexStore.java @@ -1,4 +1,4 @@ -package com.jinyframework.keva.server.noheap; +package com.jinyframework.keva.store; public interface IndexStore { void put(String k, Long v); diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStoreImpl.java b/keva/store/src/main/java/com/jinyframework/keva/store/IndexStoreImpl.java similarity index 99% rename from keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStoreImpl.java rename to keva/store/src/main/java/com/jinyframework/keva/store/IndexStoreImpl.java index ca9f331..1e55db4 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/IndexStoreImpl.java +++ b/keva/store/src/main/java/com/jinyframework/keva/store/IndexStoreImpl.java @@ -1,4 +1,4 @@ -package com.jinyframework.keva.server.noheap; +package com.jinyframework.keva.store; import lombok.extern.slf4j.Slf4j; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStore.java b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStore.java similarity index 96% rename from keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStore.java rename to keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStore.java index 3a3c685..699abe9 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStore.java +++ b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStore.java @@ -1,4 +1,4 @@ -package com.jinyframework.keva.server.noheap; +package com.jinyframework.keva.store; public interface NoHeapStore { byte INACTIVE_RECORD = 0; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreImpl.java b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreImpl.java similarity index 99% rename from keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreImpl.java rename to keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreImpl.java index c3d7758..fdccc81 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreImpl.java +++ b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreImpl.java @@ -1,4 +1,4 @@ -package com.jinyframework.keva.server.noheap; +package com.jinyframework.keva.store; import lombok.extern.slf4j.Slf4j; diff --git a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreManager.java b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreManager.java similarity index 74% rename from keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreManager.java rename to keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreManager.java index 97040d2..a62ab10 100644 --- a/keva/server/src/main/java/com/jinyframework/keva/server/noheap/NoHeapStoreManager.java +++ b/keva/store/src/main/java/com/jinyframework/keva/store/NoHeapStoreManager.java @@ -1,6 +1,4 @@ -package com.jinyframework.keva.server.noheap; - -import com.jinyframework.keva.server.config.ConfigManager; +package com.jinyframework.keva.store; import java.util.HashMap; @@ -10,17 +8,10 @@ public class NoHeapStoreManager { HashMap stores = new HashMap<>(); - String snapshotConnection = ConfigManager.getConfig().getSnapshotLocation(); - String homeDirectory = snapshotConnection.length() == 0 ? System.getProperty("user.dir") : snapshotConnection; - public NoHeapStoreManager() { } - public NoHeapStoreManager(String homeDirectory) { - this.homeDirectory = homeDirectory; - } - - public boolean createStore(String name) throws Exception { + public boolean createStore(String name) { return createStore(name, NoHeapStore.Storage.IN_MEMORY, 100); @@ -36,6 +27,13 @@ public boolean createStore(String name, public boolean createStore(String name, NoHeapStore.Storage storageType, int size) { + return createStore(name, storageType, size, System.getProperty("user.dir")); + } + + public boolean createStore(String name, + NoHeapStore.Storage storageType, + int size, + String homeDirectory) { NoHeapStoreImpl noHeapDB = new NoHeapStoreImpl(homeDirectory, name, storageType, size * MEGABYTE, true); diff --git a/settings.gradle b/settings.gradle index 68fca22..8893355 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,9 +4,9 @@ include 'core' include 'middlewares:cors' include 'middlewares:jwt' include 'websocket' +include 'keva:store' include 'keva:server' include 'keva:client' // Test only (with gitignore) include 'testproject' -