mirror of
https://github.com/wassname/ray.git
synced 2026-07-27 11:26:41 +08:00
Streaming state (#7348)
This commit is contained in:
@@ -6,6 +6,7 @@ exports_files([
|
||||
])
|
||||
|
||||
all_modules = [
|
||||
"streaming-state",
|
||||
"streaming-api",
|
||||
"streaming-runtime",
|
||||
]
|
||||
@@ -35,6 +36,7 @@ define_java_module(
|
||||
define_test_lib = True,
|
||||
test_deps = [
|
||||
"//java:io_ray_ray_api",
|
||||
":io_ray_ray_streaming-state",
|
||||
":io_ray_ray_streaming-api",
|
||||
"@ray_streaming_maven//:com_google_guava_guava",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_api",
|
||||
@@ -43,12 +45,37 @@ define_java_module(
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":io_ray_ray_streaming-state",
|
||||
"@ray_streaming_maven//:com_google_guava_guava",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_api",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_log4j12",
|
||||
],
|
||||
)
|
||||
|
||||
define_java_module(
|
||||
name = "streaming-state",
|
||||
define_test_lib = True,
|
||||
test_deps = [
|
||||
":io_ray_ray_streaming-state",
|
||||
"@ray_streaming_maven//:com_google_guava_guava",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_api",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_log4j12",
|
||||
"@ray_streaming_maven//:org_testng_testng",
|
||||
"@ray_streaming_maven//:org_mockito_mockito_all",
|
||||
"@ray_streaming_maven//:de_ruedigermoeller_fst",
|
||||
"@ray_streaming_maven//:org_apache_commons_commons_lang3",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@ray_streaming_maven//:com_google_guava_guava",
|
||||
"@ray_streaming_maven//:de_ruedigermoeller_fst",
|
||||
"@ray_streaming_maven//:log4j_log4j",
|
||||
"@ray_streaming_maven//:org_apache_commons_commons_lang3",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_api",
|
||||
"@ray_streaming_maven//:org_slf4j_slf4j_log4j12",
|
||||
],
|
||||
)
|
||||
|
||||
# `//streaming:streaming_java` will be located in jar `streaming` directory,
|
||||
# but we need it located in jar root path.
|
||||
# resource_strip_prefix = "streaming" will make other resources file located in wrong path.
|
||||
@@ -98,6 +125,7 @@ define_java_module(
|
||||
test_deps = [
|
||||
"//java:io_ray_ray_api",
|
||||
"//java:io_ray_ray_runtime",
|
||||
":io_ray_ray_streaming-state",
|
||||
":io_ray_ray_streaming-api",
|
||||
":io_ray_ray_streaming-runtime",
|
||||
"@ray_streaming_maven//:com_google_guava_guava",
|
||||
@@ -114,6 +142,7 @@ define_java_module(
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
":io_ray_ray_streaming-api",
|
||||
":io_ray_ray_streaming-state",
|
||||
"//java:io_ray_ray_api",
|
||||
"//java:io_ray_ray_runtime",
|
||||
"@ray_streaming_maven//:com_github_davidmoten_flatbuffers_java",
|
||||
@@ -136,6 +165,7 @@ java_binary(
|
||||
":io_ray_ray_streaming-api_test",
|
||||
":io_ray_ray_streaming-runtime",
|
||||
":io_ray_ray_streaming-runtime_test",
|
||||
":io_ray_ray_streaming-state",
|
||||
"//java:io_ray_ray_runtime",
|
||||
"@ray_streaming_maven//:com_beust_jcommander",
|
||||
"@ray_streaming_maven//:org_mockito_mockito_all",
|
||||
|
||||
@@ -13,6 +13,10 @@ def gen_streaming_java_deps():
|
||||
"org.slf4j:slf4j-api:1.7.12",
|
||||
"org.slf4j:slf4j-log4j12:1.7.25",
|
||||
"org.apache.logging.log4j:log4j-core:2.8.2",
|
||||
"org.testng:testng:6.9.10",
|
||||
"log4j:log4j:1.2.17",
|
||||
"org.mockito:mockito-all:1.10.19",
|
||||
"org.apache.commons:commons-lang3:3.3.2",
|
||||
"org.msgpack:msgpack-core:0.8.20",
|
||||
"org.testng:testng:6.9.10",
|
||||
"org.mockito:mockito-all:1.10.19",
|
||||
|
||||
+11
-4
@@ -16,34 +16,41 @@
|
||||
<modules>
|
||||
<module>streaming-api</module>
|
||||
<module>streaming-runtime</module>
|
||||
<module>streaming-state</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<projetct.version>0.1-SNAPSHOT</projetct.version>
|
||||
<slf4j.version>1.7.25</slf4j.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
<testng.version>6.9.10</testng.version>
|
||||
<mockito.version>1.10.19</mockito.version>
|
||||
<guava.version>27.0.1-jre</guava.version>
|
||||
<fst.version>2.57</fst.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>27.0.1-jre</version>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>6.9.10</version>
|
||||
<version>${testng.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
Executable → Regular
+6
-1
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This file is auto-generated by Bazel from pom_template.xml, do not modify it. -->
|
||||
<!-- This file is auto-generated by Bazel from pom_template.xml, do not modify it. -->
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
@@ -23,6 +23,11 @@
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ray</groupId>
|
||||
<artifactId>streaming-state</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>27.0.1-jre</version>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
{auto_gen_header}
|
||||
{auto_gen_header}
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
@@ -22,6 +22,11 @@
|
||||
<artifactId>ray-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ray</groupId>
|
||||
<artifactId>streaming-state</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
{generated_bzl_deps}
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
+25
-1
@@ -1,5 +1,14 @@
|
||||
package io.ray.streaming.api.context;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Encapsulate the runtime information of a streaming task.
|
||||
*/
|
||||
@@ -11,8 +20,23 @@ public interface RuntimeContext {
|
||||
|
||||
int getParallelism();
|
||||
|
||||
Long getBatchId();
|
||||
Long getCheckpointId();
|
||||
|
||||
void setCheckpointId(long checkpointId);
|
||||
|
||||
Long getMaxBatch();
|
||||
|
||||
Map<String, String> getConfig();
|
||||
|
||||
void setCurrentKey(Object key);
|
||||
|
||||
KeyStateBackend getKeyStateBackend();
|
||||
|
||||
void setKeyStateBackend(KeyStateBackend keyStateBackend);
|
||||
|
||||
<T> ValueState<T> getValueState(ValueStateDescriptor<T> stateDescriptor);
|
||||
|
||||
<T> ListState<T> getListState(ListStateDescriptor<T> stateDescriptor);
|
||||
|
||||
<S, T> MapState<S, T> getMapState(MapStateDescriptor<S, T> stateDescriptor);
|
||||
}
|
||||
|
||||
+1
-1
@@ -10,7 +10,6 @@ import io.ray.streaming.operator.StreamOperator;
|
||||
import java.util.List;
|
||||
|
||||
public class SourceOperator<T> extends StreamOperator<SourceFunction<T>> {
|
||||
|
||||
private SourceContextImpl sourceContext;
|
||||
|
||||
public SourceOperator(SourceFunction<T> function) {
|
||||
@@ -38,6 +37,7 @@ public class SourceOperator<T> extends StreamOperator<SourceFunction<T>> {
|
||||
}
|
||||
|
||||
class SourceContextImpl implements SourceContext<T> {
|
||||
|
||||
private List<Collector> collectors;
|
||||
|
||||
public SourceContextImpl(List<Collector> collectors) {
|
||||
|
||||
Executable → Regular
+6
-1
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- This file is auto-generated by Bazel from pom_template.xml, do not modify it. -->
|
||||
<!-- This file is auto-generated by Bazel from pom_template.xml, do not modify it. -->
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
@@ -71,6 +71,11 @@
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-core</artifactId>
|
||||
<version>1.6.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-testng</artifactId>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
{auto_gen_header}
|
||||
{auto_gen_header}
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
+1
@@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory;
|
||||
* @param <P> Type of the specific operator class.
|
||||
*/
|
||||
public abstract class StreamProcessor<T, P extends Operator> implements Processor<T> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StreamProcessor.class);
|
||||
|
||||
protected List<Collector> collectors;
|
||||
|
||||
+78
-6
@@ -2,19 +2,39 @@ package io.ray.streaming.runtime.worker.context;
|
||||
|
||||
import static io.ray.streaming.util.Config.STREAMING_BATCH_MAX_COUNT;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.ray.streaming.api.context.RuntimeContext;
|
||||
import io.ray.streaming.runtime.core.graph.ExecutionTask;
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.OperatorStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Use Ray to implement RuntimeContext.
|
||||
*/
|
||||
public class RayRuntimeContext implements RuntimeContext {
|
||||
|
||||
private final Long maxBatch;
|
||||
/**
|
||||
* Backend for keyed state. This might be empty if we're not on a keyed stream.
|
||||
*/
|
||||
protected transient KeyStateBackend keyStateBackend;
|
||||
/**
|
||||
* Backend for operator state. This might be empty
|
||||
*/
|
||||
protected transient OperatorStateBackend operatorStateBackend;
|
||||
private int taskId;
|
||||
private int taskIndex;
|
||||
private int parallelism;
|
||||
private Long batchId;
|
||||
private final Long maxBatch;
|
||||
private Long checkpointId;
|
||||
private Map<String, String> config;
|
||||
|
||||
public RayRuntimeContext(ExecutionTask executionTask, Map<String, String> config,
|
||||
@@ -46,8 +66,19 @@ public class RayRuntimeContext implements RuntimeContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getBatchId() {
|
||||
return batchId;
|
||||
public Long getCheckpointId() {
|
||||
return checkpointId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCheckpointId(long checkpointId) {
|
||||
if (this.keyStateBackend != null) {
|
||||
this.keyStateBackend.setCheckpointId(checkpointId);
|
||||
}
|
||||
if (this.operatorStateBackend != null) {
|
||||
this.operatorStateBackend.setCheckpointId(checkpointId);
|
||||
}
|
||||
this.checkpointId = checkpointId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,7 +86,48 @@ public class RayRuntimeContext implements RuntimeContext {
|
||||
return maxBatch;
|
||||
}
|
||||
|
||||
public void setBatchId(Long batchId) {
|
||||
this.batchId = batchId;
|
||||
@Override
|
||||
public Map<String, String> getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setCurrentKey(Object key) {
|
||||
this.keyStateBackend.setCurrentKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyStateBackend getKeyStateBackend() {
|
||||
return keyStateBackend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyStateBackend(KeyStateBackend keyStateBackend) {
|
||||
this.keyStateBackend = keyStateBackend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ValueState<T> getValueState(ValueStateDescriptor<T> stateDescriptor) {
|
||||
stateSanityCheck(stateDescriptor, this.keyStateBackend);
|
||||
return this.keyStateBackend.getValueState(stateDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> ListState<T> getListState(ListStateDescriptor<T> stateDescriptor) {
|
||||
stateSanityCheck(stateDescriptor, this.keyStateBackend);
|
||||
return this.keyStateBackend.getListState(stateDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <S, T> MapState<S, T> getMapState(MapStateDescriptor<S, T> stateDescriptor) {
|
||||
stateSanityCheck(stateDescriptor, this.keyStateBackend);
|
||||
return this.keyStateBackend.getMapState(stateDescriptor);
|
||||
}
|
||||
|
||||
protected void stateSanityCheck(AbstractStateDescriptor stateDescriptor,
|
||||
AbstractKeyStateBackend backend) {
|
||||
Preconditions.checkNotNull(stateDescriptor, "The state properties must not be null");
|
||||
Preconditions.checkNotNull(backend, "backend must not be null");
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -26,6 +26,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public abstract class StreamTask implements Runnable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StreamTask.class);
|
||||
|
||||
protected int taskId;
|
||||
@@ -41,8 +42,8 @@ public abstract class StreamTask implements Runnable {
|
||||
this.worker = worker;
|
||||
prepareTask();
|
||||
|
||||
this.thread = new Thread(Ray.wrapRunnable(this), this.getClass().getName()
|
||||
+ "-" + System.currentTimeMillis());
|
||||
this.thread = new Thread(Ray.wrapRunnable(this),
|
||||
this.getClass().getName() + "-" + System.currentTimeMillis());
|
||||
this.thread.setDaemon(true);
|
||||
}
|
||||
|
||||
@@ -105,8 +106,8 @@ public abstract class StreamTask implements Runnable {
|
||||
reader = new DataReader(channelIDs, inputActors, queueConf);
|
||||
}
|
||||
|
||||
RuntimeContext runtimeContext = new RayRuntimeContext(
|
||||
worker.getExecutionTask(), worker.getConfig(), executionNode.getParallelism());
|
||||
RuntimeContext runtimeContext = new RayRuntimeContext(worker.getExecutionTask(),
|
||||
worker.getConfig(), executionNode.getParallelism());
|
||||
|
||||
processor.open(collectors, runtimeContext);
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ray-streaming</artifactId>
|
||||
<groupId>io.ray</groupId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.ray</groupId>
|
||||
<artifactId>streaming-state</artifactId>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<version>${testng.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
<artifactId>log4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.ruedigermoeller</groupId>
|
||||
<artifactId>fst</artifactId>
|
||||
<version>${fst.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.3.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.beust</groupId>
|
||||
<artifactId>jcommander</artifactId>
|
||||
<version>1.27</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
{auto_gen_header}
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>ray-streaming</artifactId>
|
||||
<groupId>io.ray</groupId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>streaming-state</artifactId>
|
||||
<name>ray streaming state</name>
|
||||
<description>ray streaming state</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
{generated_bzl_deps}
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state;
|
||||
|
||||
/**
|
||||
* Key Value State interface.
|
||||
*/
|
||||
public interface KeyValueState<K, V> {
|
||||
|
||||
/**
|
||||
* get value from state
|
||||
*/
|
||||
V get(K key);
|
||||
|
||||
/**
|
||||
* put key and value into state
|
||||
*/
|
||||
void put(K k, V v);
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* value record for partition.
|
||||
*/
|
||||
public class PartitionRecord<T> implements Serializable {
|
||||
|
||||
/**
|
||||
* The partition number of the partitioned value.
|
||||
*/
|
||||
private int partitionID;
|
||||
private T value;
|
||||
|
||||
public PartitionRecord() {
|
||||
}
|
||||
|
||||
public PartitionRecord(int partitionID, T value) {
|
||||
this.partitionID = partitionID;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getPartitionID() {
|
||||
return partitionID;
|
||||
}
|
||||
|
||||
public void setPartitionID(int partitionID) {
|
||||
this.partitionID = partitionID;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state;
|
||||
|
||||
/**
|
||||
* RuntimeException wrapper, indicating the exceptions occurs in states.
|
||||
*/
|
||||
public class StateException extends RuntimeException {
|
||||
|
||||
public StateException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
||||
public StateException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state;
|
||||
|
||||
/**
|
||||
* TransactionState interface.
|
||||
* <p>
|
||||
* Streaming State should implement transaction in case of failure,
|
||||
* which in our case is four default method, finish, commit, ackCommit, rollback.
|
||||
*/
|
||||
public interface StateStoreManager {
|
||||
|
||||
/**
|
||||
* The finish method is used when the batched data is all saved in state.
|
||||
* Normally, serialization job is done here.
|
||||
*/
|
||||
void finish(long checkpointId);
|
||||
|
||||
/**
|
||||
* The commit method is used for persistent, and can be used in another thread to reach async
|
||||
* state commit.
|
||||
* Normally, data persistent is done here.
|
||||
*/
|
||||
void commit(long checkpointId);
|
||||
|
||||
/**
|
||||
* The ackCommit method is used for cleaning the last checkpoint, and must be called after commit
|
||||
* in the same thread.
|
||||
*/
|
||||
void ackCommit(long checkpointId, long timeStamp);
|
||||
|
||||
/**
|
||||
* The rollback method is used for recovering the checkpoint.
|
||||
*/
|
||||
void rollBack(long checkpointId);
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This Class contains a record with some checkpointId.
|
||||
*/
|
||||
public class StorageRecord<T> implements Serializable {
|
||||
|
||||
private long checkpointId;
|
||||
private T value;
|
||||
|
||||
public StorageRecord() {
|
||||
}
|
||||
|
||||
public StorageRecord(long checkpointId, T value) {
|
||||
this.checkpointId = checkpointId;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getCheckpointId() {
|
||||
return checkpointId;
|
||||
}
|
||||
|
||||
public void setCheckpointId(long checkpointId) {
|
||||
this.checkpointId = checkpointId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (value != null) {
|
||||
return "checkpointId:" + checkpointId + ", value:" + value;
|
||||
} else {
|
||||
return "checkpointId:" + checkpointId + ", value:null";
|
||||
}
|
||||
}
|
||||
}
|
||||
+211
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import io.ray.streaming.state.StateStoreManager;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor.StateType;
|
||||
import io.ray.streaming.state.keystate.state.proxy.ListStateStoreManagerProxy;
|
||||
import io.ray.streaming.state.keystate.state.proxy.MapStateStoreManagerProxy;
|
||||
import io.ray.streaming.state.keystate.state.proxy.ValueStateStoreManagerProxy;
|
||||
import io.ray.streaming.state.store.KeyMapStore;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Transaction support primitive operations like finish, commit, ackcommit and rollback.
|
||||
* <p>
|
||||
* State value modification is not thread safe! By default, every processing thread has its own
|
||||
* space to handle state.
|
||||
*/
|
||||
public abstract class AbstractKeyStateBackend implements StateStoreManager {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractKeyStateBackend.class);
|
||||
|
||||
protected long currentCheckpointId;
|
||||
protected Object currentKey;
|
||||
protected int keyGroupIndex = -1;
|
||||
protected Map<String, ValueStateStoreManagerProxy> valueManagerProxyHashMap = new HashMap<>();
|
||||
protected Map<String, ListStateStoreManagerProxy> listManagerProxyHashMap = new HashMap<>();
|
||||
protected Map<String, MapStateStoreManagerProxy> mapManagerProxyHashMap = new HashMap<>();
|
||||
protected Set<String> descNamespace;
|
||||
|
||||
/**
|
||||
* tablename, KeyValueStore key, checkpointId, content
|
||||
*/
|
||||
protected Map<String, KeyValueStore<String, Map<Long, byte[]>>> backStorageCache;
|
||||
private AbstractStateBackend backend;
|
||||
|
||||
public AbstractKeyStateBackend(AbstractStateBackend backend) {
|
||||
this.backStorageCache = new HashMap<>();
|
||||
this.backend = backend;
|
||||
this.descNamespace = new HashSet<>();
|
||||
}
|
||||
|
||||
public <K, T> void put(AbstractStateDescriptor descriptor, K key, T value) {
|
||||
String desc = descriptor.getIdentify();
|
||||
if (descriptor.getStateType() == StateType.VALUE) {
|
||||
if (this.valueManagerProxyHashMap.containsKey(desc)) {
|
||||
valueManagerProxyHashMap.get(desc).put((String) key, value);
|
||||
}
|
||||
} else if (descriptor.getStateType() == StateType.LIST) {
|
||||
if (this.listManagerProxyHashMap.containsKey(desc)) {
|
||||
listManagerProxyHashMap.get(desc).put((String) key, value);
|
||||
}
|
||||
} else if (descriptor.getStateType() == StateType.MAP) {
|
||||
if (this.mapManagerProxyHashMap.containsKey(desc)) {
|
||||
mapManagerProxyHashMap.get(desc).put((String) key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public <K, T> T get(AbstractStateDescriptor descriptor, K key) {
|
||||
String desc = descriptor.getIdentify();
|
||||
if (descriptor.getStateType() == StateType.VALUE) {
|
||||
if (this.valueManagerProxyHashMap.containsKey(desc)) {
|
||||
return (T) valueManagerProxyHashMap.get(desc).get((String) key);
|
||||
}
|
||||
} else if (descriptor.getStateType() == StateType.LIST) {
|
||||
if (this.listManagerProxyHashMap.containsKey(desc)) {
|
||||
return (T) listManagerProxyHashMap.get(desc).get((String) key);
|
||||
}
|
||||
} else if (descriptor.getStateType() == StateType.MAP) {
|
||||
if (this.mapManagerProxyHashMap.containsKey(desc)) {
|
||||
return (T) mapManagerProxyHashMap.get(desc).get((String) key);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(long checkpointId) {
|
||||
for (Entry<String, ValueStateStoreManagerProxy> entry : valueManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().finish(checkpointId);
|
||||
}
|
||||
for (Entry<String, ListStateStoreManagerProxy> entry : listManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().finish(checkpointId);
|
||||
}
|
||||
for (Entry<String, MapStateStoreManagerProxy> entry : mapManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().finish(checkpointId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(long checkpointId) {
|
||||
for (Entry<String, ValueStateStoreManagerProxy> entry : valueManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().commit(checkpointId);
|
||||
}
|
||||
for (Entry<String, ListStateStoreManagerProxy> entry : listManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().commit(checkpointId);
|
||||
}
|
||||
for (Entry<String, MapStateStoreManagerProxy> entry : mapManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().commit(checkpointId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ackCommit(long checkpointId, long timeStamp) {
|
||||
for (Entry<String, ValueStateStoreManagerProxy> entry : valueManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().ackCommit(checkpointId, timeStamp);
|
||||
}
|
||||
for (Entry<String, ListStateStoreManagerProxy> entry : listManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().ackCommit(checkpointId, timeStamp);
|
||||
}
|
||||
for (Entry<String, MapStateStoreManagerProxy> entry : mapManagerProxyHashMap.entrySet()) {
|
||||
entry.getValue().ackCommit(checkpointId, timeStamp);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollBack(long checkpointId) {
|
||||
for (Entry<String, ValueStateStoreManagerProxy> entry : valueManagerProxyHashMap.entrySet()) {
|
||||
LOG.warn("backend rollback:{},{}", entry.getKey(), checkpointId);
|
||||
entry.getValue().rollBack(checkpointId);
|
||||
}
|
||||
for (Entry<String, ListStateStoreManagerProxy> entry : listManagerProxyHashMap.entrySet()) {
|
||||
LOG.warn("backend rollback:{},{}", entry.getKey(), checkpointId);
|
||||
entry.getValue().rollBack(checkpointId);
|
||||
}
|
||||
for (Entry<String, MapStateStoreManagerProxy> entry : mapManagerProxyHashMap.entrySet()) {
|
||||
LOG.warn("backend rollback:{},{}", entry.getKey(), checkpointId);
|
||||
entry.getValue().rollBack(checkpointId);
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValueStore<String, Map<Long, byte[]>> getBackStorage(String tableName) {
|
||||
if (this.backStorageCache.containsKey(tableName)) {
|
||||
return this.backStorageCache.get(tableName);
|
||||
} else {
|
||||
KeyMapStore<String, Long, byte[]> ikvStore = this.backend.getKeyMapStore(tableName);
|
||||
this.backStorageCache.put(tableName, ikvStore);
|
||||
return ikvStore;
|
||||
}
|
||||
}
|
||||
|
||||
public KeyValueStore<String, Map<Long, byte[]>> getBackStorage(
|
||||
AbstractStateDescriptor stateDescriptor) {
|
||||
String tableName = this.backend.getTableName(stateDescriptor);
|
||||
return getBackStorage(tableName);
|
||||
}
|
||||
|
||||
public StateStrategy getStateStrategy() {
|
||||
return this.backend.getStateStrategy();
|
||||
}
|
||||
|
||||
public BackendType getBackendType() {
|
||||
return this.backend.getBackendType();
|
||||
}
|
||||
|
||||
public Object getCurrentKey() {
|
||||
return this.currentKey;
|
||||
}
|
||||
|
||||
public abstract void setCurrentKey(Object currentKey);
|
||||
|
||||
public long getCheckpointId() {
|
||||
return this.currentCheckpointId;
|
||||
}
|
||||
|
||||
public void setCheckpointId(long checkpointId) {
|
||||
this.currentCheckpointId = checkpointId;
|
||||
}
|
||||
|
||||
public void setContext(long checkpointId, Object currentKey) {
|
||||
setCheckpointId(checkpointId);
|
||||
setCurrentKey(currentKey);
|
||||
}
|
||||
|
||||
public AbstractStateBackend getBackend() {
|
||||
return backend;
|
||||
}
|
||||
|
||||
public int getKeyGroupIndex() {
|
||||
return this.keyGroupIndex;
|
||||
}
|
||||
|
||||
public void setKeyGroupIndex(int keyGroupIndex) {
|
||||
this.keyGroupIndex = keyGroupIndex;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import static io.ray.streaming.state.config.ConfigKey.DELIMITER;
|
||||
|
||||
import io.ray.streaming.state.config.ConfigKey;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor;
|
||||
import io.ray.streaming.state.serialization.KeyMapStoreSerializer;
|
||||
import io.ray.streaming.state.store.KeyMapStore;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class is the abstract class for different kinds of StateBackend.
|
||||
*/
|
||||
public abstract class AbstractStateBackend implements Serializable {
|
||||
|
||||
protected final Map<String, String> config;
|
||||
protected final StateStrategy stateStrategy;
|
||||
|
||||
protected final BackendType backendType;
|
||||
protected int keyGroupIndex = -1;
|
||||
|
||||
protected AbstractStateBackend(Map<String, String> config) {
|
||||
this.stateStrategy = StateStrategy.getEnum(ConfigKey.getStateStrategyEnum(config));
|
||||
this.backendType = BackendType.getEnum(ConfigKey.getBackendType(config));
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public abstract <K, V> KeyValueStore<K, V> getKeyValueStore(String tableName);
|
||||
|
||||
public abstract <K, S, T> KeyMapStore<K, S, T> getKeyMapStore(String tableName);
|
||||
|
||||
public abstract <K, S, T> KeyMapStore<K, S, T> getKeyMapStore(
|
||||
String tableName, KeyMapStoreSerializer keyMapStoreSerializer);
|
||||
|
||||
public BackendType getBackendType() {
|
||||
return backendType;
|
||||
}
|
||||
|
||||
public StateStrategy getStateStrategy() {
|
||||
return stateStrategy;
|
||||
}
|
||||
|
||||
public String getTableName(AbstractStateDescriptor stateDescriptor) {
|
||||
return stateDescriptor.getTableName();
|
||||
}
|
||||
|
||||
public String getStateKey(String descName, String currentKey) {
|
||||
return descName + DELIMITER + currentKey;
|
||||
}
|
||||
|
||||
public void setKeyGroupIndex(int keyGroupIndex) {
|
||||
this.keyGroupIndex = keyGroupIndex;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
/**
|
||||
* Backend Types.
|
||||
*/
|
||||
public enum BackendType {
|
||||
/**
|
||||
* Saving the state values in memory
|
||||
*/
|
||||
MEMORY;
|
||||
|
||||
/**
|
||||
* get the enum from input string value, ignoring the case
|
||||
*/
|
||||
public static BackendType getEnum(String value) {
|
||||
for (BackendType v : values()) {
|
||||
if (v.name().equalsIgnoreCase(value)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
return MEMORY;
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.KeyGroupAssignment;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import io.ray.streaming.state.keystate.state.proxy.ListStateStoreManagerProxy;
|
||||
import io.ray.streaming.state.keystate.state.proxy.MapStateStoreManagerProxy;
|
||||
import io.ray.streaming.state.keystate.state.proxy.ValueStateStoreManagerProxy;
|
||||
|
||||
/**
|
||||
* key state backend manager, managing different kinds of states in different thread.
|
||||
* This class is not thread safe.
|
||||
*/
|
||||
public class KeyStateBackend extends AbstractKeyStateBackend {
|
||||
|
||||
protected final int numberOfKeyGroups;
|
||||
protected final KeyGroup keyGroup;
|
||||
|
||||
public KeyStateBackend(int numberOfKeyGroups, KeyGroup keyGroup,
|
||||
AbstractStateBackend abstractStateBackend) {
|
||||
super(abstractStateBackend);
|
||||
this.numberOfKeyGroups = numberOfKeyGroups;
|
||||
this.keyGroup = keyGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* get new value state proxy
|
||||
*/
|
||||
protected <T> ValueStateStoreManagerProxy<T> newValueStateProxy(
|
||||
ValueStateDescriptor<T> stateDescriptor) {
|
||||
return new ValueStateStoreManagerProxy<>(this, stateDescriptor);
|
||||
}
|
||||
|
||||
public <T> ValueState<T> getValueState(ValueStateDescriptor<T> stateDescriptor) {
|
||||
String desc = stateDescriptor.getIdentify();
|
||||
if (valueManagerProxyHashMap.containsKey(desc)) {
|
||||
return valueManagerProxyHashMap.get(desc).getValueState();
|
||||
} else {
|
||||
ValueStateStoreManagerProxy<T> valueStateProxy = newValueStateProxy(stateDescriptor);
|
||||
valueManagerProxyHashMap.put(desc, valueStateProxy);
|
||||
return valueStateProxy.getValueState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get new list state proxy
|
||||
*/
|
||||
protected <T> ListStateStoreManagerProxy<T> newListStateProxy(
|
||||
ListStateDescriptor<T> stateDescriptor) {
|
||||
return new ListStateStoreManagerProxy<>(this, stateDescriptor);
|
||||
}
|
||||
|
||||
public <T> ListState<T> getListState(ListStateDescriptor<T> stateDescriptor) {
|
||||
String desc = stateDescriptor.getIdentify();
|
||||
if (listManagerProxyHashMap.containsKey(desc)) {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = listManagerProxyHashMap.get(desc);
|
||||
return listStateProxy.getListState();
|
||||
} else {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = newListStateProxy(stateDescriptor);
|
||||
listManagerProxyHashMap.put(desc, listStateProxy);
|
||||
return listStateProxy.getListState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get map state proxy
|
||||
*/
|
||||
protected <S, T> MapStateStoreManagerProxy<S, T> newMapStateProxy(
|
||||
MapStateDescriptor<S, T> stateDescriptor) {
|
||||
return new MapStateStoreManagerProxy<>(this, stateDescriptor);
|
||||
}
|
||||
|
||||
public <S, T> MapState<S, T> getMapState(MapStateDescriptor<S, T> stateDescriptor) {
|
||||
String desc = stateDescriptor.getIdentify();
|
||||
if (mapManagerProxyHashMap.containsKey(desc)) {
|
||||
MapStateStoreManagerProxy<S, T> mapStateProxy = mapManagerProxyHashMap.get(desc);
|
||||
return mapStateProxy.getMapState();
|
||||
} else {
|
||||
MapStateStoreManagerProxy<S, T> mapStateProxy = newMapStateProxy(stateDescriptor);
|
||||
mapManagerProxyHashMap.put(desc, mapStateProxy);
|
||||
return mapStateProxy.getMapState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
super.keyGroupIndex = KeyGroupAssignment
|
||||
.assignKeyGroupIndexForKey(currentKey, numberOfKeyGroups);
|
||||
super.currentKey = currentKey;
|
||||
}
|
||||
|
||||
public int getNumberOfKeyGroups() {
|
||||
return numberOfKeyGroups;
|
||||
}
|
||||
|
||||
public KeyGroup getKeyGroup() {
|
||||
return keyGroup;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
for (ValueStateStoreManagerProxy proxy : valueManagerProxyHashMap.values()) {
|
||||
proxy.close();
|
||||
}
|
||||
for (ListStateStoreManagerProxy proxy : listManagerProxyHashMap.values()) {
|
||||
proxy.close();
|
||||
}
|
||||
for (MapStateStoreManagerProxy proxy : mapManagerProxyHashMap.values()) {
|
||||
proxy.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.impl.OperatorStateImpl;
|
||||
import io.ray.streaming.state.keystate.state.proxy.ListStateStoreManagerProxy;
|
||||
|
||||
/**
|
||||
* OperatorState manager for getting split or union list state.
|
||||
*/
|
||||
public class OperatorStateBackend extends AbstractKeyStateBackend {
|
||||
|
||||
public OperatorStateBackend(AbstractStateBackend backend) {
|
||||
super(backend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
super.currentKey = currentKey;
|
||||
}
|
||||
|
||||
protected <T> ListStateStoreManagerProxy<T> newListStateStoreManagerProxy(
|
||||
ListStateDescriptor<T> stateDescriptor) {
|
||||
return new ListStateStoreManagerProxy<>(this, stateDescriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* get spitted List for different operator instance.
|
||||
*/
|
||||
public <T> ListState<T> getSplitListState(ListStateDescriptor<T> stateDescriptor) {
|
||||
String desc = stateDescriptor.getIdentify();
|
||||
if (listManagerProxyHashMap.containsKey(desc)) {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = listManagerProxyHashMap.get(desc);
|
||||
return listStateProxy.getListState();
|
||||
} else {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = newListStateStoreManagerProxy(stateDescriptor);
|
||||
listManagerProxyHashMap.put(desc, listStateProxy);
|
||||
((OperatorStateImpl) (listStateProxy.getListState())).setSplit(true);
|
||||
return listStateProxy.getListState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a union List for different operator instance.
|
||||
*/
|
||||
public <T> ListState<T> getUnionListState(ListStateDescriptor<T> stateDescriptor) {
|
||||
String desc = stateDescriptor.getIdentify();
|
||||
if (listManagerProxyHashMap.containsKey(desc)) {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = listManagerProxyHashMap.get(desc);
|
||||
return listStateProxy.getListState();
|
||||
} else {
|
||||
ListStateStoreManagerProxy<T> listStateProxy = newListStateStoreManagerProxy(stateDescriptor);
|
||||
listManagerProxyHashMap.put(desc, listStateProxy);
|
||||
((OperatorStateImpl) (listStateProxy.getListState())).init();
|
||||
return listStateProxy.getListState();
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.config.ConfigKey;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* State Backend Builder.
|
||||
*/
|
||||
public class StateBackendBuilder {
|
||||
|
||||
private static AbstractStateBackend getStateBackend(Map<String, String> config,
|
||||
BackendType type) {
|
||||
switch (type) {
|
||||
case MEMORY:
|
||||
return new MemoryStateBackend(config);
|
||||
default:
|
||||
throw new RuntimeException(type.name() + " not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static AbstractStateBackend buildStateBackend(Map<String, String> config) {
|
||||
BackendType type;
|
||||
if (config == null) {
|
||||
type = BackendType.MEMORY;
|
||||
} else {
|
||||
type = BackendType.getEnum(config.get(ConfigKey.STATE_BACKEND_TYPE));
|
||||
}
|
||||
|
||||
return getStateBackend(config, type);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
/**
|
||||
* This class describe State Saving Model.
|
||||
*/
|
||||
public enum StateStrategy {
|
||||
/**
|
||||
* save two version together in case of rollback.
|
||||
*/
|
||||
DUAL_VERSION,
|
||||
|
||||
/**
|
||||
* for storage supporting mvcc, we save only current version.
|
||||
*/
|
||||
SINGLE_VERSION;
|
||||
|
||||
|
||||
public static StateStrategy getEnum(String value) {
|
||||
for (StateStrategy v : values()) {
|
||||
if (v.name().equalsIgnoreCase(value)) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(value + " strategy is not supported");
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.AbstractStateBackend;
|
||||
import io.ray.streaming.state.serialization.KeyMapStoreSerializer;
|
||||
import io.ray.streaming.state.store.KeyMapStore;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import io.ray.streaming.state.store.impl.MemoryKeyMapStore;
|
||||
import io.ray.streaming.state.store.impl.MemoryKeyValueStore;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MemoryStateBackend. Supporting memory store.
|
||||
*/
|
||||
public class MemoryStateBackend extends AbstractStateBackend {
|
||||
|
||||
public MemoryStateBackend(Map<String, String> config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, V> KeyValueStore<K, V> getKeyValueStore(String tableName) {
|
||||
return new MemoryKeyValueStore<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, S, T> KeyMapStore<K, S, T> getKeyMapStore(String tableName) {
|
||||
return new MemoryKeyMapStore<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, S, T> KeyMapStore<K, S, T> getKeyMapStore(
|
||||
String tableName, KeyMapStoreSerializer keyMapStoreSerializer) {
|
||||
return new MemoryKeyMapStore<>();
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Config Helper figure out the config info.
|
||||
* Todo replace this to config module.
|
||||
*/
|
||||
public class ConfigHelper {
|
||||
|
||||
public static int getIntegerOrDefault(Map config, String configKey, int defaultValue) {
|
||||
if (config.containsKey(configKey)) {
|
||||
return Integer.valueOf(String.valueOf(config.get(configKey)));
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getStringOrDefault(Map config, String configKey, String defaultValue) {
|
||||
if (config.containsKey(configKey)) {
|
||||
return String.valueOf(config.get(configKey));
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* state config keys.
|
||||
* Todo replace this to config module.
|
||||
*/
|
||||
public final class ConfigKey {
|
||||
|
||||
/**
|
||||
* backend
|
||||
*/
|
||||
public static final String STATE_BACKEND_TYPE = "state.backend.type";
|
||||
public static final String STATE_TABLE_NAME = "state.table.name";
|
||||
public static final String STATE_STRATEGY_MODE = "state.strategy.mode";
|
||||
public static final String NUMBER_PER_CHECKPOINT = "number.per.checkpoint";
|
||||
public static final String JOB_MAX_PARALLEL = "job.max.parallel";
|
||||
public static final String DELIMITER = "\u0001\u0008"; // for String delimiter
|
||||
|
||||
private ConfigKey() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static String getStateStrategyEnum(Map<String, String> config) {
|
||||
return ConfigHelper.getStringOrDefault(config, STATE_STRATEGY_MODE, "DUAL_VERSION");
|
||||
}
|
||||
|
||||
public static String getBackendType(Map<String, String> config) {
|
||||
return ConfigHelper.getStringOrDefault(config, STATE_BACKEND_TYPE, "MEMORY");
|
||||
}
|
||||
|
||||
public static int getNumberPerCheckpoint(Map<String, String> config) {
|
||||
return ConfigHelper.getIntegerOrDefault(config, NUMBER_PER_CHECKPOINT, 5);
|
||||
}
|
||||
|
||||
public static String getStateTableName(Map<String, String> config) {
|
||||
return ConfigHelper.getStringOrDefault(config, STATE_TABLE_NAME, "table");
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* This class defines key-groups. Key-groups is
|
||||
* the key space in a job, which is partitioned for keyed state processing in state backend.
|
||||
* The boundaries of the key-group are inclusive.
|
||||
*/
|
||||
public class KeyGroup implements Serializable {
|
||||
|
||||
private final int startIndex;
|
||||
private final int endIndex;
|
||||
|
||||
/**
|
||||
* Defines the range [startIndex, endIndex]
|
||||
*
|
||||
* @param startIndex start of the range (inclusive)
|
||||
* @param endIndex end of the range (inclusive)
|
||||
*/
|
||||
public KeyGroup(int startIndex, int endIndex) {
|
||||
Preconditions.checkArgument(startIndex >= 0 && startIndex <= endIndex);
|
||||
this.startIndex = startIndex;
|
||||
this.endIndex = endIndex;
|
||||
Preconditions.checkArgument(size() >= 0, "overflow detected.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of key-group in the range
|
||||
*/
|
||||
public int size() {
|
||||
return 1 + endIndex - startIndex;
|
||||
}
|
||||
|
||||
public int getStartIndex() {
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
public int getEndIndex() {
|
||||
return endIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KeyGroup{" + "startIndex=" + startIndex + ", endIndex=" + endIndex + '}';
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This class defines key-group assignment algorithm。
|
||||
*/
|
||||
public final class KeyGroupAssignment {
|
||||
|
||||
/**
|
||||
* Computes the range of key-groups that are assigned for a given operator instance.
|
||||
*
|
||||
* @param maxParallelism Maximal parallelism of the job.
|
||||
* @param parallelism Parallelism for the job. <= maxParallelism.
|
||||
* @param index index of the operator instance.
|
||||
*/
|
||||
public static KeyGroup getKeyGroup(int maxParallelism, int parallelism, int index) {
|
||||
Preconditions.checkArgument(maxParallelism >= parallelism,
|
||||
"Maximum parallelism (%s) must not be smaller than parallelism(%s)", maxParallelism,
|
||||
parallelism);
|
||||
|
||||
int start = index == 0 ? 0 : ((index * maxParallelism - 1) / parallelism) + 1;
|
||||
int end = ((index + 1) * maxParallelism - 1) / parallelism;
|
||||
return new KeyGroup(start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigning the key to a key-group index.
|
||||
*
|
||||
* @param key the key to assign.
|
||||
* @param maxParallelism the maximum parallelism.
|
||||
* @return the key-group index to which the given key is assigned.
|
||||
*/
|
||||
public static int assignKeyGroupIndexForKey(Object key, int maxParallelism) {
|
||||
return Math.abs(key.hashCode() % maxParallelism);
|
||||
}
|
||||
|
||||
public static Map<Integer, List<Integer>> computeKeyGroupToTask(int maxParallelism,
|
||||
List<Integer> targetTasks) {
|
||||
Map<Integer, List<Integer>> keyGroupToTask = new ConcurrentHashMap<>();
|
||||
for (int index = 0; index < targetTasks.size(); index++) {
|
||||
KeyGroup taskKeyGroup = getKeyGroup(maxParallelism, targetTasks.size(), index);
|
||||
for (int groupId = taskKeyGroup.getStartIndex(); groupId <= taskKeyGroup.getEndIndex();
|
||||
groupId++) {
|
||||
keyGroupToTask.put(groupId, ImmutableList.of(targetTasks.get(index)));
|
||||
}
|
||||
}
|
||||
return keyGroupToTask;
|
||||
}
|
||||
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.ray.streaming.state.keystate.state.State;
|
||||
|
||||
/**
|
||||
* This class defines basic data structures of StateDescriptor.
|
||||
*/
|
||||
public abstract class AbstractStateDescriptor<S extends State, T> {
|
||||
|
||||
private final String name;
|
||||
private String tableName;
|
||||
private Class<T> type;
|
||||
|
||||
protected AbstractStateDescriptor(String name, Class<T> type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
protected Class<T> setType(Class<T> type) {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public abstract StateType getStateType();
|
||||
|
||||
public String getIdentify() {
|
||||
Preconditions.checkArgument(this.tableName != null, "table name must not be null.");
|
||||
Preconditions.checkArgument(this.name != null, "table name must not be null.");
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AbstractStateDescriptor{" + "tableName='" + tableName + '\'' + ", name='" + name + '\''
|
||||
+ ", type=" + type + '}';
|
||||
}
|
||||
|
||||
public enum StateType {
|
||||
/**
|
||||
* value state
|
||||
*/
|
||||
VALUE,
|
||||
|
||||
/**
|
||||
* list state
|
||||
*/
|
||||
LIST,
|
||||
|
||||
/**
|
||||
* map state
|
||||
*/
|
||||
MAP
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
|
||||
import static io.ray.streaming.state.config.ConfigKey.DELIMITER;
|
||||
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
|
||||
/**
|
||||
* ListStateDescriptor.
|
||||
*/
|
||||
public class ListStateDescriptor<T> extends AbstractStateDescriptor<ListState<T>, T> {
|
||||
|
||||
private final boolean isOperatorList;
|
||||
private int index;
|
||||
private int partitionNum;
|
||||
|
||||
private ListStateDescriptor(String name, Class<T> type, boolean isOperatorList) {
|
||||
super(name, type);
|
||||
this.isOperatorList = isOperatorList;
|
||||
}
|
||||
|
||||
public static <T> ListStateDescriptor<T> build(String name, Class<T> type) {
|
||||
return build(name, type, false);
|
||||
}
|
||||
|
||||
public static <T> ListStateDescriptor<T> build(String name, Class<T> type,
|
||||
boolean isOperatorList) {
|
||||
return new ListStateDescriptor<>(name, type, isOperatorList);
|
||||
}
|
||||
|
||||
public boolean isOperatorList() {
|
||||
return isOperatorList;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public int getPartitionNumber() {
|
||||
return partitionNum;
|
||||
}
|
||||
|
||||
public void setPartitionNumber(int number) {
|
||||
this.partitionNum = number;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateType getStateType() {
|
||||
return StateType.LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentify() {
|
||||
if (isOperatorList) {
|
||||
return String
|
||||
.format("%s%s%d%s%d", super.getIdentify(), DELIMITER, partitionNum, DELIMITER, index);
|
||||
} else {
|
||||
return super.getIdentify();
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MapStateDescriptor.
|
||||
*/
|
||||
public class MapStateDescriptor<K, V> extends AbstractStateDescriptor<MapState<K, V>, Map<K, V>> {
|
||||
|
||||
public MapStateDescriptor(String name, Class<K> keyType, Class<V> valueType) {
|
||||
super(name, null);
|
||||
// TODO: use the types to help serde
|
||||
}
|
||||
|
||||
public static <K, V> MapStateDescriptor<K, V> build(String name, Class<K> keyType,
|
||||
Class<V> valueType) {
|
||||
return new MapStateDescriptor<>(name, keyType, valueType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateType getStateType() {
|
||||
return StateType.MAP;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
|
||||
/**
|
||||
* ValueStateDescriptor.
|
||||
*/
|
||||
public class ValueStateDescriptor<T> extends AbstractStateDescriptor<ValueState<T>, T> {
|
||||
|
||||
private final T defaultValue;
|
||||
|
||||
public ValueStateDescriptor(String name, Class<T> type, T defaultValue) {
|
||||
super(name, type);
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public static <T> ValueStateDescriptor<T> build(String name, Class<T> type, T defaultValue) {
|
||||
return new ValueStateDescriptor<>(name, type, defaultValue);
|
||||
}
|
||||
|
||||
public T getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateType getStateType() {
|
||||
return StateType.VALUE;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ListState interface.
|
||||
*/
|
||||
public interface ListState<T> extends UnaryState<List<T>> {
|
||||
|
||||
/**
|
||||
* add the value to list
|
||||
*
|
||||
* @param value the new value
|
||||
*/
|
||||
void add(T value);
|
||||
|
||||
/**
|
||||
* update list state
|
||||
*
|
||||
* @param list the new value
|
||||
*/
|
||||
void update(List<T> list);
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* MapState interface.
|
||||
*/
|
||||
public interface MapState<K, V> extends UnaryState<Map<K, V>> {
|
||||
|
||||
/**
|
||||
* Returns the current value associated with the given key.
|
||||
*
|
||||
* @param key The key of the mapping
|
||||
* @return The value of the mapping with the given key
|
||||
*/
|
||||
V get(K key);
|
||||
|
||||
/**
|
||||
* Associates a new value with the given key.
|
||||
*
|
||||
* @param key The key of the mapping
|
||||
* @param value The new value of the mapping
|
||||
*/
|
||||
void put(K key, V value);
|
||||
|
||||
/**
|
||||
* Resets the state value.
|
||||
*
|
||||
* @param map The mappings for reset in this state
|
||||
*/
|
||||
void update(Map<K, V> map);
|
||||
|
||||
/**
|
||||
* Copies all of the mappings from the given map into the state.
|
||||
*
|
||||
* @param map The mappings to be stored in this state
|
||||
*/
|
||||
void putAll(Map<K, V> map);
|
||||
|
||||
/**
|
||||
* Deletes the mapping of the given key.
|
||||
*
|
||||
* @param key The key of the mapping
|
||||
*/
|
||||
void remove(K key);
|
||||
|
||||
/**
|
||||
* Returns whether there exists the given mapping.
|
||||
*
|
||||
* @param key The key of the mapping
|
||||
* @return True if there exists a mapping whose key equals to the given key
|
||||
*/
|
||||
default boolean contains(K key) {
|
||||
return get().containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the mappings in the state
|
||||
*
|
||||
* @return An iterable view of all the key-value pairs in the state.
|
||||
*/
|
||||
default Iterable<Entry<K, V>> entries() {
|
||||
return get().entrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the keys in the state
|
||||
*
|
||||
* @return An iterable view of all the keys in the state.
|
||||
*/
|
||||
default Iterable<K> keys() {
|
||||
return get().keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the values in the state.
|
||||
*
|
||||
* @return An iterable view of all the values in the state.
|
||||
*/
|
||||
default Iterable<V> values() {
|
||||
return get().values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over all the mappings in the state.
|
||||
*
|
||||
* @return An iterator over all the mappings in the state
|
||||
*/
|
||||
default Iterator<Entry<K, V>> iterator() {
|
||||
return get().entrySet().iterator();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state;
|
||||
|
||||
/**
|
||||
* State interface.
|
||||
*/
|
||||
public interface State {
|
||||
|
||||
/**
|
||||
* set current key of the state
|
||||
*/
|
||||
void setCurrentKey(Object currentKey);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state;
|
||||
|
||||
/**
|
||||
* one value per state.
|
||||
*/
|
||||
public interface UnaryState<O> extends State {
|
||||
|
||||
/**
|
||||
* get the value in state
|
||||
*
|
||||
* @return the value in state
|
||||
*/
|
||||
O get();
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state;
|
||||
|
||||
/**
|
||||
* ValueState interface.
|
||||
*/
|
||||
public interface ValueState<T> extends UnaryState<T> {
|
||||
|
||||
/**
|
||||
* update the value
|
||||
*
|
||||
* @param value the new value
|
||||
*/
|
||||
void update(T value);
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ListState implementation.
|
||||
*/
|
||||
public class ListStateImpl<V> implements ListState<V> {
|
||||
|
||||
private final StateHelper<List<V>> helper;
|
||||
|
||||
public ListStateImpl(ListStateDescriptor<V> descriptor, AbstractKeyStateBackend backend) {
|
||||
this.helper = new StateHelper<>(backend, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<V> get() {
|
||||
List<V> list = helper.get();
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(V value) {
|
||||
List<V> list = helper.get();
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(value);
|
||||
helper.put(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(List<V> list) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
helper.put(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
helper.setCurrentKey(currentKey);
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* MapState implementation.
|
||||
*/
|
||||
public class MapStateImpl<K, V> implements MapState<K, V> {
|
||||
|
||||
private final StateHelper<Map<K, V>> helper;
|
||||
|
||||
public MapStateImpl(MapStateDescriptor<K, V> descriptor, KeyStateBackend backend) {
|
||||
this.helper = new StateHelper<>(backend, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> get() {
|
||||
Map<K, V> map = helper.get();
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) {
|
||||
Map<K, V> map = get();
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) {
|
||||
Map<K, V> map = get();
|
||||
|
||||
map.put(key, value);
|
||||
helper.put(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Map<K, V> map) {
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
helper.put(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(Map<K, V> newMap) {
|
||||
Map<K, V> map = get();
|
||||
|
||||
map.putAll(newMap);
|
||||
helper.put(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) {
|
||||
Map<K, V> map = get();
|
||||
|
||||
map.remove(key);
|
||||
helper.put(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* set current key of the state
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
helper.setCurrentKey(currentKey);
|
||||
}
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import static io.ray.streaming.state.config.ConfigKey.DELIMITER;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.ray.streaming.state.PartitionRecord;
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This class defines the implementation of operator state.
|
||||
* When the state is initialized, we must scan the whole table.
|
||||
* And if the state type is splitList, all the records must be spitted.
|
||||
*/
|
||||
public class OperatorStateImpl<V> implements ListState<V> {
|
||||
|
||||
private final ListStateDescriptor<V> descriptor;
|
||||
private StateHelper<List<PartitionRecord<V>>> helper;
|
||||
private List<PartitionRecord<V>> allList;
|
||||
|
||||
private AtomicBoolean hasInit;
|
||||
private boolean isSplit;
|
||||
|
||||
public OperatorStateImpl(ListStateDescriptor<V> descriptor, AbstractKeyStateBackend backend) {
|
||||
this.descriptor = descriptor;
|
||||
this.helper = new StateHelper<>(backend, descriptor);
|
||||
this.isSplit = false;
|
||||
this.hasInit = new AtomicBoolean(false);
|
||||
this.allList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void splitList() {
|
||||
// fetch target list and save
|
||||
List<PartitionRecord<V>> list = new ArrayList<>();
|
||||
int step = descriptor.getPartitionNumber();
|
||||
Preconditions.checkArgument(step > 0);
|
||||
|
||||
for (int round = 0; round * step <= allList.size(); round++) {
|
||||
int m = round * step + descriptor.getIndex();
|
||||
if (m < allList.size()) {
|
||||
PartitionRecord<V> tmp = allList.get(m);
|
||||
tmp.setPartitionID(descriptor.getPartitionNumber());
|
||||
list.add(tmp);
|
||||
}
|
||||
}
|
||||
helper.put(list, getStateKey());
|
||||
allList.clear();
|
||||
}
|
||||
|
||||
private void scan() {
|
||||
int partitionNum = -1;
|
||||
int index = 0;
|
||||
while (true) {
|
||||
List<PartitionRecord<V>> list = helper.getBackend()
|
||||
.get(descriptor, getKey(descriptor.getIdentify(), index));
|
||||
if (list != null && !list.isEmpty()) {
|
||||
partitionNum = list.get(0).getPartitionID();
|
||||
allList.addAll(list);
|
||||
}
|
||||
if (++index >= partitionNum) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void init() {
|
||||
scan();
|
||||
|
||||
if (isSplit) {
|
||||
splitList();
|
||||
}
|
||||
}
|
||||
|
||||
private String getKey(String descName, int index) {
|
||||
String[] stringList = descName.split(DELIMITER);
|
||||
return String.format("%s%s%s%s%d", stringList[0], DELIMITER, stringList[1], DELIMITER, index);
|
||||
}
|
||||
|
||||
protected String getStateKey() {
|
||||
return getKey(this.descriptor.getIdentify(), this.descriptor.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
throw new UnsupportedOperationException("OperatorState cannot set current key");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<V> get() {
|
||||
if (!hasInit.getAndSet(true)) {
|
||||
init();
|
||||
}
|
||||
List<PartitionRecord<V>> prList = helper.get(getStateKey());
|
||||
List<V> list = new ArrayList<>();
|
||||
for (PartitionRecord<V> pr : prList) {
|
||||
list.add(pr.getValue());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(V value) {
|
||||
if (!hasInit.getAndSet(true)) {
|
||||
init();
|
||||
}
|
||||
List<PartitionRecord<V>> list = helper.get(getStateKey());
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(new PartitionRecord<>(descriptor.getPartitionNumber(), value));
|
||||
helper.put(list, getStateKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(List<V> list) {
|
||||
List<PartitionRecord<V>> prList = new ArrayList<>();
|
||||
if (list != null) {
|
||||
for (V value : list) {
|
||||
prList.add(new PartitionRecord<>(descriptor.getPartitionNumber(), value));
|
||||
}
|
||||
}
|
||||
helper.put(prList);
|
||||
}
|
||||
|
||||
public void setSplit(boolean split) {
|
||||
this.isSplit = split;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor;
|
||||
|
||||
/**
|
||||
* State Helper Class.
|
||||
*/
|
||||
public class StateHelper<T> {
|
||||
|
||||
private final AbstractKeyStateBackend backend;
|
||||
private final AbstractStateDescriptor descriptor;
|
||||
|
||||
public StateHelper(AbstractKeyStateBackend backend, AbstractStateDescriptor descriptor) {
|
||||
this.backend = backend;
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
protected String getStateKey(String descName) {
|
||||
Preconditions.checkNotNull(backend, "KeyedBackend must not be null");
|
||||
Preconditions.checkNotNull(backend.getCurrentKey(), "currentKey must not be null");
|
||||
return this.backend.getBackend().getStateKey(descName, backend.getCurrentKey().toString());
|
||||
}
|
||||
|
||||
public void put(T value, String key) {
|
||||
backend.put(descriptor, key, value);
|
||||
}
|
||||
|
||||
public void put(T value) {
|
||||
put(value, getStateKey(descriptor.getIdentify()));
|
||||
}
|
||||
|
||||
public T get(String key) {
|
||||
return backend.get(descriptor, key);
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return get(getStateKey(descriptor.getIdentify()));
|
||||
}
|
||||
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
Preconditions.checkNotNull(backend, "KeyedBackend must not be null");
|
||||
this.backend.setCurrentKey(currentKey);
|
||||
}
|
||||
|
||||
public void setKeyGroupIndex(int keyGroupIndex) {
|
||||
this.backend.setKeyGroupIndex(keyGroupIndex);
|
||||
}
|
||||
|
||||
public void resetKeyGroupIndex() {
|
||||
this.backend.setKeyGroupIndex(-1);
|
||||
}
|
||||
|
||||
public AbstractStateDescriptor getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
public AbstractKeyStateBackend getBackend() {
|
||||
return backend;
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
|
||||
/**
|
||||
* ValueState implementation.
|
||||
*/
|
||||
public class ValueStateImpl<T> implements ValueState<T> {
|
||||
|
||||
private final StateHelper<T> helper;
|
||||
|
||||
public ValueStateImpl(ValueStateDescriptor<T> descriptor, KeyStateBackend backend) {
|
||||
this.helper = new StateHelper<>(backend, descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(T value) {
|
||||
helper.put(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() {
|
||||
T value = helper.get();
|
||||
if (null == value) {
|
||||
return ((ValueStateDescriptor<T>) helper.getDescriptor()).getDefaultValue();
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set current key of the state
|
||||
*/
|
||||
@Override
|
||||
public void setCurrentKey(Object currentKey) {
|
||||
helper.setCurrentKey(currentKey);
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.KeyValueState;
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.impl.ListStateImpl;
|
||||
import io.ray.streaming.state.keystate.state.impl.OperatorStateImpl;
|
||||
import io.ray.streaming.state.strategy.StateStoreManagerProxy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class defines ListState Wrapper, connecting state and backend.
|
||||
*/
|
||||
public class ListStateStoreManagerProxy<T> extends StateStoreManagerProxy<List<T>> implements
|
||||
KeyValueState<String, List<T>> {
|
||||
|
||||
private final ListState<T> listState;
|
||||
|
||||
public ListStateStoreManagerProxy(AbstractKeyStateBackend keyStateBackend,
|
||||
ListStateDescriptor<T> stateDescriptor) {
|
||||
super(keyStateBackend, stateDescriptor);
|
||||
if (stateDescriptor.isOperatorList()) {
|
||||
this.listState = new OperatorStateImpl<>(stateDescriptor, keyStateBackend);
|
||||
} else {
|
||||
this.listState = new ListStateImpl<>(stateDescriptor, keyStateBackend);
|
||||
}
|
||||
}
|
||||
|
||||
public ListState<T> getListState() {
|
||||
return this.listState;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.KeyValueState;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.impl.MapStateImpl;
|
||||
import io.ray.streaming.state.strategy.StateStoreManagerProxy;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class defines MapState Wrapper, connecting state and backend.
|
||||
*/
|
||||
public class MapStateStoreManagerProxy<K, V> extends StateStoreManagerProxy<Map<K, V>> implements
|
||||
KeyValueState<String, Map<K, V>> {
|
||||
|
||||
private final MapStateImpl<K, V> mapState;
|
||||
|
||||
public MapStateStoreManagerProxy(KeyStateBackend keyStateBackend,
|
||||
MapStateDescriptor<K, V> stateDescriptor) {
|
||||
super(keyStateBackend, stateDescriptor);
|
||||
this.mapState = new MapStateImpl<>(stateDescriptor, keyStateBackend);
|
||||
}
|
||||
|
||||
public MapState<K, V> getMapState() {
|
||||
return this.mapState;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.KeyValueState;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import io.ray.streaming.state.keystate.state.impl.ValueStateImpl;
|
||||
import io.ray.streaming.state.strategy.StateStoreManagerProxy;
|
||||
|
||||
/**
|
||||
* This class defines ValueState Wrapper, connecting state and backend.
|
||||
*/
|
||||
public class ValueStateStoreManagerProxy<T> extends StateStoreManagerProxy<T> implements
|
||||
KeyValueState<String, T> {
|
||||
|
||||
private final ValueStateImpl<T> valueState;
|
||||
|
||||
public ValueStateStoreManagerProxy(KeyStateBackend keyStateBackend,
|
||||
ValueStateDescriptor<T> stateDescriptor) {
|
||||
super(keyStateBackend, stateDescriptor);
|
||||
this.valueState = new ValueStateImpl<>(stateDescriptor, keyStateBackend);
|
||||
}
|
||||
|
||||
public ValueState<T> getValueState() {
|
||||
return this.valueState;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization;
|
||||
|
||||
/**
|
||||
* Key Map Serialization and Deserialization.
|
||||
*/
|
||||
public interface KeyMapStoreSerializer<K, S, T> {
|
||||
|
||||
byte[] serializeKey(K key);
|
||||
|
||||
byte[] serializeUKey(S uk);
|
||||
|
||||
S deserializeUKey(byte[] ukArray);
|
||||
|
||||
byte[] serializeUValue(T uv);
|
||||
|
||||
T deserializeUValue(byte[] uvArray);
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization;
|
||||
|
||||
/**
|
||||
* Key Value Serialization and Deserialization.
|
||||
*/
|
||||
public interface KeyValueStoreSerialization<K, V> {
|
||||
|
||||
byte[] serializeKey(K key);
|
||||
|
||||
byte[] serializeValue(V value);
|
||||
|
||||
V deserializeValue(byte[] valueArray);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization;
|
||||
|
||||
import org.nustaq.serialization.FSTConfiguration;
|
||||
|
||||
/**
|
||||
* fst wrapper.
|
||||
*/
|
||||
public class Serializer {
|
||||
|
||||
private static final ThreadLocal<FSTConfiguration> conf = ThreadLocal
|
||||
.withInitial(FSTConfiguration::createDefaultConfiguration);
|
||||
|
||||
public static byte[] object2Bytes(Object value) {
|
||||
return conf.get().asByteArray(value);
|
||||
}
|
||||
|
||||
public static Object bytes2Object(byte[] buffer) {
|
||||
return conf.get().asObject(buffer);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization.impl;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import io.ray.streaming.state.StateException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* AbstractSerialization. Generate row key.
|
||||
*/
|
||||
public abstract class AbstractSerialization {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractSerialization.class);
|
||||
|
||||
public String generateRowKeyPrefix(String key) {
|
||||
if (StringUtils.isNotEmpty(key)) {
|
||||
String md5 = Hashing.md5().hashUnencodedChars(key).toString();
|
||||
if ("".equals(md5)) {
|
||||
throw new StateException("Invalid value to md5:" + key);
|
||||
}
|
||||
return StringUtils.substring(md5, 0, 4) + ":" + key;
|
||||
} else {
|
||||
LOG.warn("key is empty");
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization.impl;
|
||||
|
||||
import io.ray.streaming.state.serialization.KeyMapStoreSerializer;
|
||||
import io.ray.streaming.state.serialization.Serializer;
|
||||
|
||||
/**
|
||||
* Default Key Map Serialization and Deserialization.
|
||||
*/
|
||||
public class DefaultKeyMapStoreSerializer<K, S, T> extends AbstractSerialization implements
|
||||
KeyMapStoreSerializer<K, S, T> {
|
||||
|
||||
@Override
|
||||
public byte[] serializeKey(K key) {
|
||||
String keyWithPrefix = generateRowKeyPrefix(key.toString());
|
||||
return keyWithPrefix.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializeUKey(S uk) {
|
||||
return Serializer.object2Bytes(uk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public S deserializeUKey(byte[] ukArray) {
|
||||
return (S) Serializer.bytes2Object(ukArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializeUValue(T uv) {
|
||||
return Serializer.object2Bytes(uv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserializeUValue(byte[] uvArray) {
|
||||
return (T) Serializer.bytes2Object(uvArray);
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.serialization.impl;
|
||||
|
||||
import io.ray.streaming.state.serialization.KeyValueStoreSerialization;
|
||||
import io.ray.streaming.state.serialization.Serializer;
|
||||
|
||||
/**
|
||||
* KV Store Serialization and Deserialization.
|
||||
*/
|
||||
public class DefaultKeyValueStoreSerialization<K, V> extends AbstractSerialization implements
|
||||
KeyValueStoreSerialization<K, V> {
|
||||
|
||||
@Override
|
||||
public byte[] serializeKey(K key) {
|
||||
String keyWithPrefix = generateRowKeyPrefix(key.toString());
|
||||
return keyWithPrefix.getBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serializeValue(V value) {
|
||||
return Serializer.object2Bytes(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V deserializeValue(byte[] valueArray) {
|
||||
return (V) Serializer.bytes2Object(valueArray);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.store;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Key Map Store interface.
|
||||
*/
|
||||
public interface KeyMapStore<K, S, T> extends KeyValueStore<K, Map<S, T>> {
|
||||
|
||||
/**
|
||||
* put sub key value into the store incrementally.
|
||||
*/
|
||||
void put(K key, S subKey, T value) throws IOException;
|
||||
|
||||
/**
|
||||
* get subValue from store.
|
||||
*/
|
||||
T get(K key, S subKey) throws IOException;
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.store;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Key Value Store interface.
|
||||
*/
|
||||
public interface KeyValueStore<K, V> extends Serializable {
|
||||
|
||||
/**
|
||||
* put key value into store.
|
||||
*/
|
||||
void put(K key, V value) throws IOException;
|
||||
|
||||
/**
|
||||
* get value from store.
|
||||
*/
|
||||
V get(K key) throws IOException;
|
||||
|
||||
/**
|
||||
* remove key in the store.
|
||||
*/
|
||||
void remove(K key) throws IOException;
|
||||
|
||||
/**
|
||||
* flush to disk.
|
||||
*/
|
||||
void flush() throws IOException;
|
||||
|
||||
/**
|
||||
* clear all cache.
|
||||
*/
|
||||
void clearCache();
|
||||
|
||||
/**
|
||||
* close the store.
|
||||
*/
|
||||
void close() throws IOException;
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.store.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.ray.streaming.state.store.KeyMapStore;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Memory Key Map Store.
|
||||
*/
|
||||
public class MemoryKeyMapStore<K, S, T> implements KeyMapStore<K, S, T> {
|
||||
|
||||
private Map<K, Map<S, T>> memoryStore;
|
||||
|
||||
public MemoryKeyMapStore() {
|
||||
this.memoryStore = Maps.newConcurrentMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, Map<S, T> value) throws IOException {
|
||||
this.memoryStore.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, S subKey, T value) throws IOException {
|
||||
if (memoryStore.containsKey(key)) {
|
||||
memoryStore.get(key).put(subKey, value);
|
||||
} else {
|
||||
Map<S, T> map = new HashMap<>();
|
||||
map.put(subKey, value);
|
||||
memoryStore.put(key, map);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<S, T> get(K key) throws IOException {
|
||||
return this.memoryStore.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(K key, S subKey) throws IOException {
|
||||
if (memoryStore.containsKey(key)) {
|
||||
return memoryStore.get(key).get(subKey);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) throws IOException {
|
||||
this.memoryStore.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (memoryStore != null) {
|
||||
memoryStore.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.store.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Memory Key Value Store.
|
||||
*/
|
||||
public class MemoryKeyValueStore<K, V> implements KeyValueStore<K, V> {
|
||||
|
||||
private Map<K, V> memoryStore;
|
||||
|
||||
public MemoryKeyValueStore() {
|
||||
this.memoryStore = Maps.newConcurrentMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(K key, V value) throws IOException {
|
||||
this.memoryStore.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(K key) throws IOException {
|
||||
return this.memoryStore.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(K key) throws IOException {
|
||||
this.memoryStore.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCache() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (memoryStore != null) {
|
||||
memoryStore.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import io.ray.streaming.state.StateException;
|
||||
import io.ray.streaming.state.StateStoreManager;
|
||||
import io.ray.streaming.state.StorageRecord;
|
||||
import io.ray.streaming.state.serialization.Serializer;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* This class defines the StoreManager Abstract class.
|
||||
* We use three layer to store the state, frontStore, middleStore and keyValueStore(remote).
|
||||
*/
|
||||
public abstract class AbstractStateStoreManager<V> implements StateStoreManager {
|
||||
|
||||
/**
|
||||
* read-write
|
||||
*/
|
||||
protected Map<String, StorageRecord<V>> frontStore = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* remote-storage
|
||||
*/
|
||||
protected KeyValueStore<String, Map<Long, byte[]>> kvStore;
|
||||
|
||||
/**
|
||||
* read-only
|
||||
*/
|
||||
protected Map<Long, Map<String, byte[]>> middleStore = new ConcurrentHashMap<>();
|
||||
protected int keyGroupIndex = -1;
|
||||
|
||||
public AbstractStateStoreManager(KeyValueStore<String, Map<Long, byte[]>> backStore) {
|
||||
kvStore = backStore;
|
||||
}
|
||||
|
||||
public byte[] toBytes(StorageRecord storageRecord) {
|
||||
return Serializer.object2Bytes(storageRecord);
|
||||
}
|
||||
|
||||
public StorageRecord<V> toStorageRecord(byte[] data) {
|
||||
return (StorageRecord<V>) Serializer.bytes2Object(data);
|
||||
}
|
||||
|
||||
public abstract V get(long checkpointId, String key);
|
||||
|
||||
public void put(long checkpointId, String k, V v) {
|
||||
frontStore.put(k, new StorageRecord<>(checkpointId, v));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ackCommit(long checkpointId, long timeStamp) {
|
||||
ackCommit(checkpointId);
|
||||
}
|
||||
|
||||
public abstract void ackCommit(long checkpointId);
|
||||
|
||||
public void setKeyGroupIndex(int keyGroupIndex) {
|
||||
this.keyGroupIndex = keyGroupIndex;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
frontStore.clear();
|
||||
middleStore.clear();
|
||||
if (kvStore != null) {
|
||||
kvStore.clearCache();
|
||||
try {
|
||||
kvStore.close();
|
||||
} catch (IOException e) {
|
||||
throw new StateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import com.google.common.primitives.Longs;
|
||||
import io.ray.streaming.state.StateException;
|
||||
import io.ray.streaming.state.StorageRecord;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class define the checkpoint store strategy, which saves two-version data once.
|
||||
*/
|
||||
public class DualStateStoreManager<V> extends AbstractStateStoreManager<V> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DualStateStoreManager.class);
|
||||
|
||||
public DualStateStoreManager(KeyValueStore<String, Map<Long, byte[]>> backStore) {
|
||||
super(backStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(long checkpointId) {
|
||||
LOG.info("do finish checkpointId:{}", checkpointId);
|
||||
Map<String, byte[]> cpStore = new HashMap<>();
|
||||
for (Entry<String, StorageRecord<V>> entry : frontStore.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
StorageRecord<V> value = entry.getValue();
|
||||
cpStore.put(key, toBytes(value));
|
||||
}
|
||||
middleStore.put(checkpointId, cpStore);
|
||||
frontStore.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(long checkpointId) {
|
||||
try {
|
||||
LOG.info("do commit checkpointId:{}", checkpointId);
|
||||
Map<String, byte[]> cpStore = middleStore.get(checkpointId);
|
||||
if (cpStore == null) {
|
||||
throw new StateException("why cp store is null");
|
||||
}
|
||||
for (Entry<String, byte[]> entry : cpStore.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
byte[] value = entry.getValue();
|
||||
|
||||
/**
|
||||
* 2 is specific key in kv store and indicates that new value
|
||||
* should be stored with this key after overwriting old value in key 1. i.e.
|
||||
*
|
||||
* -2 -1 1 2
|
||||
* k1 6 5 a b
|
||||
* k2 9 7 d e
|
||||
*
|
||||
* k1's value for checkpoint 5 is a, and b for checkpoint 6.
|
||||
*/
|
||||
Map<Long, byte[]> remoteData = super.kvStore.get(key);
|
||||
if (remoteData == null || remoteData.size() == 0) {
|
||||
remoteData = new HashMap<>();
|
||||
remoteData.put(2L, value);
|
||||
remoteData.put(-2L, Longs.toByteArray(checkpointId));
|
||||
} else {
|
||||
long oldBatchId = Longs.fromByteArray(remoteData.get(-2L));
|
||||
if (oldBatchId < checkpointId) {
|
||||
//move the old data
|
||||
remoteData.put(1L, remoteData.get(2L));
|
||||
remoteData.put(-1L, remoteData.get(-2L));
|
||||
}
|
||||
|
||||
//put the new data here
|
||||
remoteData.put(2L, value);
|
||||
remoteData.put(-2L, Longs.toByteArray(checkpointId));
|
||||
}
|
||||
super.kvStore.put(key, remoteData);
|
||||
}
|
||||
super.kvStore.flush();
|
||||
} catch (Exception e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
throw new StateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollBack(long checkpointId) {
|
||||
LOG.info("do rollBack checkpointId:{}", checkpointId);
|
||||
this.frontStore.clear();
|
||||
this.middleStore.clear();
|
||||
this.kvStore.clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(long checkpointId, String key) {
|
||||
// get from current cp cache
|
||||
StorageRecord<V> storageRecord = frontStore.get(key);
|
||||
if (storageRecord != null) {
|
||||
return storageRecord.getValue();
|
||||
}
|
||||
|
||||
//get from not commit cp info
|
||||
List<Long> checkpointIds = new ArrayList<>(middleStore.keySet());
|
||||
Collections.sort(checkpointIds);
|
||||
for (int i = checkpointIds.size() - 1; i >= 0; i--) {
|
||||
Map<String, byte[]> cpStore = middleStore.get(checkpointIds.get(i));
|
||||
if (cpStore != null) {
|
||||
if (cpStore.containsKey(key)) {
|
||||
byte[] cpData = cpStore.get(key);
|
||||
storageRecord = toStorageRecord(cpData);
|
||||
return storageRecord.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Map<Long, byte[]> remoteData = super.kvStore.get(key);
|
||||
if (remoteData != null) {
|
||||
for (Entry<Long, byte[]> entry : remoteData.entrySet()) {
|
||||
if (entry.getKey() > 0) {
|
||||
StorageRecord<V> tmp = toStorageRecord(entry.getValue());
|
||||
if (tmp.getCheckpointId() < checkpointId) {
|
||||
if (storageRecord == null) {
|
||||
storageRecord = tmp;
|
||||
} else if (storageRecord.getCheckpointId() < tmp.getCheckpointId()) {
|
||||
storageRecord = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (storageRecord != null) {
|
||||
return storageRecord.getValue();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("get checkpointId:" + checkpointId + " key:" + key, e);
|
||||
throw new StateException(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ackCommit(long checkpointId) {
|
||||
LOG.info("do ackCommit checkpointId:{}", checkpointId);
|
||||
middleStore.remove(checkpointId);
|
||||
}
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import io.ray.streaming.state.StateException;
|
||||
import io.ray.streaming.state.StorageRecord;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* This class define the multi-version store strategy, which leverages external storage's mvcc.
|
||||
*/
|
||||
public class MVStateStoreManager<V> extends AbstractStateStoreManager<V> {
|
||||
|
||||
public MVStateStoreManager(KeyValueStore<String, Map<Long, byte[]>> kvStore) {
|
||||
super(kvStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(long checkpointId) {
|
||||
Map<String, byte[]> currentStateRecords = new HashMap<>();
|
||||
for (Entry<String, StorageRecord<V>> entry : frontStore.entrySet()) {
|
||||
currentStateRecords.put(entry.getKey(), toBytes(entry.getValue()));
|
||||
}
|
||||
|
||||
middleStore.put(checkpointId, currentStateRecords);
|
||||
frontStore.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit(long checkpointId) {
|
||||
// write to external storage
|
||||
List<Long> checkpointIds = new ArrayList<>(middleStore.keySet());
|
||||
Collections.sort(checkpointIds);
|
||||
|
||||
for (int i = checkpointIds.size() - 1; i >= 0; i--) {
|
||||
long commitBatchId = checkpointIds.get(i);
|
||||
if (commitBatchId > checkpointId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, byte[]> commitRecords = middleStore.get(commitBatchId);
|
||||
|
||||
try {
|
||||
for (Entry<String, byte[]> entry : commitRecords.entrySet()) {
|
||||
|
||||
Map<Long, byte[]> remoteData = this.kvStore.get(entry.getKey());
|
||||
if (remoteData == null) {
|
||||
remoteData = new HashMap<>();
|
||||
}
|
||||
|
||||
remoteData.put(commitBatchId, entry.getValue());
|
||||
|
||||
this.kvStore.put(entry.getKey(), remoteData);
|
||||
}
|
||||
this.kvStore.flush();
|
||||
} catch (Exception e) {
|
||||
throw new StateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollBack(long checkpointId) {
|
||||
this.frontStore.clear();
|
||||
this.middleStore.clear();
|
||||
this.kvStore.clearCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(long checkpointId, String key) {
|
||||
StorageRecord<V> valueArray = frontStore.get(key);
|
||||
if (valueArray != null) {
|
||||
return valueArray.getValue();
|
||||
} else {
|
||||
List<Long> checkpointIds = new ArrayList<>(middleStore.keySet());
|
||||
Collections.sort(checkpointIds);
|
||||
|
||||
for (int i = checkpointIds.size() - 1; i >= 0; i--) {
|
||||
if (checkpointIds.get(i) > checkpointId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<String, byte[]> records = middleStore.get(checkpointIds.get(i));
|
||||
if (records != null) {
|
||||
if (records.containsKey(key)) {
|
||||
byte[] bytes = records.get(key);
|
||||
return toStorageRecord(bytes).getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get from external storage
|
||||
try {
|
||||
Map<Long, byte[]> remoteData = this.kvStore.get(key);
|
||||
if (remoteData != null) {
|
||||
checkpointIds = new ArrayList<>(remoteData.keySet());
|
||||
Collections.sort(checkpointIds);
|
||||
|
||||
for (int i = checkpointIds.size() - 1; i >= 0; i--) {
|
||||
if (checkpointIds.get(i) > checkpointId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] bytes = remoteData.get(checkpointIds.get(i));
|
||||
return toStorageRecord(bytes).getValue();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new StateException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(long checkpointId, String k, V v) {
|
||||
frontStore.put(k, new StorageRecord<>(checkpointId, v));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ackCommit(long checkpointId) {
|
||||
List<Long> checkpointIds = new ArrayList<>(middleStore.keySet());
|
||||
Collections.sort(checkpointIds);
|
||||
|
||||
for (int i = checkpointIds.size() - 1; i >= 0; i--) {
|
||||
long commitBatchId = checkpointIds.get(i);
|
||||
if (commitBatchId > checkpointId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.middleStore.remove(commitBatchId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import io.ray.streaming.state.StateStoreManager;
|
||||
import io.ray.streaming.state.backend.AbstractKeyStateBackend;
|
||||
import io.ray.streaming.state.backend.StateStrategy;
|
||||
import io.ray.streaming.state.keystate.desc.AbstractStateDescriptor;
|
||||
import io.ray.streaming.state.store.KeyValueStore;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* This class support ITransactionState.
|
||||
* <p>
|
||||
* Based on the given StorageMode, different implementation instance of the AbstractStateStrategy
|
||||
* class will be created. All method calls will be delegated to the strategy instance.
|
||||
*/
|
||||
|
||||
public abstract class StateStoreManagerProxy<V> implements StateStoreManager {
|
||||
|
||||
protected final AbstractStateStoreManager<V> stateStrategy;
|
||||
private final AbstractKeyStateBackend keyStateBackend;
|
||||
|
||||
public StateStoreManagerProxy(AbstractKeyStateBackend keyStateBackend,
|
||||
AbstractStateDescriptor stateDescriptor) {
|
||||
this.keyStateBackend = keyStateBackend;
|
||||
KeyValueStore<String, Map<Long, byte[]>> backStorage = keyStateBackend
|
||||
.getBackStorage(stateDescriptor);
|
||||
StateStrategy stateStrategy = keyStateBackend.getStateStrategy();
|
||||
switch (stateStrategy) {
|
||||
case DUAL_VERSION:
|
||||
this.stateStrategy = new DualStateStoreManager<>(backStorage);
|
||||
break;
|
||||
case SINGLE_VERSION:
|
||||
this.stateStrategy = new MVStateStoreManager<>(backStorage);
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("store vertexType not support");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setKeyGroupIndex(int index) {
|
||||
this.stateStrategy.setKeyGroupIndex(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(long checkpointId) {
|
||||
this.stateStrategy.finish(checkpointId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The commit can be used in another thread to reach async state commit.
|
||||
*/
|
||||
@Override
|
||||
public void commit(long checkpointId) {
|
||||
this.stateStrategy.commit(checkpointId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ackCommit must be called after commit in the same thread.
|
||||
*/
|
||||
@Override
|
||||
public void ackCommit(long checkpointId, long timeStamp) {
|
||||
this.stateStrategy.ackCommit(checkpointId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollBack(long checkpointId) {
|
||||
this.stateStrategy.rollBack(checkpointId);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
this.stateStrategy.close();
|
||||
}
|
||||
|
||||
public V get(String key) {
|
||||
this.stateStrategy.setKeyGroupIndex(keyStateBackend.getKeyGroupIndex());
|
||||
return this.stateStrategy.get(this.keyStateBackend.getCheckpointId(), key);
|
||||
}
|
||||
|
||||
public void put(String key, V value) {
|
||||
this.stateStrategy.setKeyGroupIndex(keyStateBackend.getKeyGroupIndex());
|
||||
this.stateStrategy.put(this.keyStateBackend.getCheckpointId(), key, value);
|
||||
}
|
||||
}
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.backend;
|
||||
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class KeyStateBackendTest {
|
||||
|
||||
private AbstractStateBackend stateBackend;
|
||||
private KeyStateBackend keyStateBackend;
|
||||
|
||||
public void testGetValueState() {
|
||||
keyStateBackend.setCheckpointId(1L);
|
||||
ValueStateDescriptor<String> valueStateDescriptor = ValueStateDescriptor
|
||||
.build("value", String.class, null);
|
||||
valueStateDescriptor.setTableName("kepler_hlg_ut");
|
||||
ValueState<String> valueState = keyStateBackend.getValueState(valueStateDescriptor);
|
||||
|
||||
valueState.setCurrentKey("1");
|
||||
valueState.update("hello");
|
||||
Assert.assertEquals(valueState.get(), "hello");
|
||||
|
||||
valueState.update("hello1");
|
||||
Assert.assertEquals(valueState.get(), "hello1");
|
||||
|
||||
valueState.setCurrentKey("2");
|
||||
Assert.assertEquals(valueState.get(), null);
|
||||
|
||||
valueState.update("eagle");
|
||||
Assert.assertEquals(valueState.get(), "eagle");
|
||||
|
||||
keyStateBackend.rollBack(1);
|
||||
valueState.setCurrentKey("1");
|
||||
Assert.assertEquals(valueState.get(), null);
|
||||
valueState.setCurrentKey("2");
|
||||
Assert.assertEquals(valueState.get(), null);
|
||||
|
||||
valueState.setCurrentKey("1");
|
||||
valueState.update("eagle");
|
||||
keyStateBackend.finish(1);
|
||||
|
||||
keyStateBackend.setCheckpointId(2);
|
||||
valueState.setCurrentKey("2");
|
||||
valueState.update("tim");
|
||||
|
||||
valueState.setCurrentKey("2-1");
|
||||
valueState.update("jim");
|
||||
keyStateBackend.finish(2);
|
||||
|
||||
keyStateBackend.setCheckpointId(3);
|
||||
valueState.setCurrentKey("3");
|
||||
valueState.update("lucy");
|
||||
keyStateBackend.finish(3);
|
||||
|
||||
keyStateBackend.setCheckpointId(4);
|
||||
valueState.setCurrentKey("4");
|
||||
valueState.update("eric");
|
||||
keyStateBackend.finish(4);
|
||||
|
||||
keyStateBackend.setCheckpointId(5);
|
||||
valueState.setCurrentKey("4");
|
||||
valueState.update("eric-1");
|
||||
valueState.setCurrentKey("5");
|
||||
valueState.update("jack");
|
||||
keyStateBackend.finish(5);
|
||||
keyStateBackend.commit(5);
|
||||
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
valueState.setCurrentKey("5");
|
||||
Assert.assertEquals(valueState.get(), "jack");
|
||||
|
||||
valueState.setCurrentKey("4");
|
||||
Assert.assertEquals(valueState.get(), "eric-1");
|
||||
|
||||
valueState.setCurrentKey(4);
|
||||
valueState.update("if-ttt");
|
||||
Assert.assertEquals(valueState.get(), "if-ttt");
|
||||
|
||||
keyStateBackend.setCheckpointId(7);
|
||||
valueState.setCurrentKey(9);
|
||||
valueState.update("6666");
|
||||
|
||||
keyStateBackend.rollBack(5);
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
valueState.setCurrentKey("4");
|
||||
Assert.assertEquals(valueState.get(), "eric-1");
|
||||
valueState.setCurrentKey("5");
|
||||
Assert.assertEquals(valueState.get(), "jack");
|
||||
valueState.setCurrentKey("9");
|
||||
Assert.assertNull(valueState.get());
|
||||
|
||||
}
|
||||
|
||||
public void testGetListState() {
|
||||
keyStateBackend.setCheckpointId(1l);
|
||||
ListStateDescriptor<String> listStateDescriptor = ListStateDescriptor
|
||||
.build("list", String.class);
|
||||
listStateDescriptor.setTableName("kepler_hlg_ut");
|
||||
ListState<String> listState = keyStateBackend.getListState(listStateDescriptor);
|
||||
|
||||
listState.setCurrentKey("1");
|
||||
listState.add("hello1");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("hello1"));
|
||||
|
||||
listState.add("hello2");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("hello1", "hello2"));
|
||||
|
||||
listState.setCurrentKey("2");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList());
|
||||
|
||||
listState.setCurrentKey("2");
|
||||
listState.add("eagle");
|
||||
listState.setCurrentKey("1");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("hello1", "hello2"));
|
||||
listState.setCurrentKey("2");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("eagle"));
|
||||
|
||||
keyStateBackend.rollBack(1);
|
||||
listState.setCurrentKey("1");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList());
|
||||
listState.setCurrentKey("2");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList());
|
||||
|
||||
listState.setCurrentKey("1");
|
||||
listState.add("eagle");
|
||||
listState.add("eagle-2");
|
||||
keyStateBackend.finish(1);
|
||||
|
||||
keyStateBackend.setCheckpointId(2);
|
||||
listState.setCurrentKey("2");
|
||||
listState.add("tim");
|
||||
|
||||
listState.setCurrentKey("2-1");
|
||||
listState.add("jim");
|
||||
keyStateBackend.finish(2);
|
||||
|
||||
keyStateBackend.setCheckpointId(3);
|
||||
listState.setCurrentKey("3");
|
||||
listState.add("lucy");
|
||||
keyStateBackend.finish(3);
|
||||
|
||||
keyStateBackend.setCheckpointId(4);
|
||||
listState.setCurrentKey("4");
|
||||
listState.add("eric");
|
||||
keyStateBackend.finish(4);
|
||||
|
||||
keyStateBackend.setCheckpointId(5);
|
||||
listState.setCurrentKey("4");
|
||||
listState.add("eric-1");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("eric", "eric-1"));
|
||||
|
||||
listState.setCurrentKey("5");
|
||||
listState.add("jack");
|
||||
keyStateBackend.finish(5);
|
||||
keyStateBackend.commit(5);
|
||||
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
listState.setCurrentKey("5");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("jack"));
|
||||
|
||||
listState.setCurrentKey("4");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("eric", "eric-1"));
|
||||
|
||||
listState.setCurrentKey(4);
|
||||
listState.add("if-ttt");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("eric", "eric-1", "if-ttt"));
|
||||
|
||||
keyStateBackend.setCheckpointId(7);
|
||||
listState.setCurrentKey(9);
|
||||
listState.add("6666");
|
||||
|
||||
keyStateBackend.rollBack(5);
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
listState.setCurrentKey("4");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("eric", "eric-1"));
|
||||
listState.setCurrentKey("5");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList("jack"));
|
||||
listState.setCurrentKey("9");
|
||||
Assert.assertEquals(listState.get(), Arrays.asList());
|
||||
}
|
||||
|
||||
public void testGetMapState() {
|
||||
keyStateBackend.setCheckpointId(1l);
|
||||
MapStateDescriptor<String, String> mapStateDescriptor = MapStateDescriptor
|
||||
.build("map", String.class, String.class);
|
||||
mapStateDescriptor.setTableName("kepler_hlg_ut");
|
||||
MapState<String, String> mapState = keyStateBackend.getMapState(mapStateDescriptor);
|
||||
|
||||
mapState.setCurrentKey("1");
|
||||
mapState.put("hello1", "world1");
|
||||
Assert.assertEquals(mapState.get("hello1"), "world1");
|
||||
|
||||
mapState.put("hello2", "world2");
|
||||
Assert.assertEquals(mapState.get("hello2"), "world2");
|
||||
Assert.assertEquals(mapState.get("hello1"), "world1");
|
||||
Assert.assertEquals(mapState.get("hello3"), null);
|
||||
|
||||
mapState.setCurrentKey("2");
|
||||
//Assert.assertEquals(mapState.iterator(), (new HashMap()));
|
||||
|
||||
mapState.setCurrentKey("2");
|
||||
mapState.put("eagle", "eagle-1");
|
||||
mapState.setCurrentKey("1");
|
||||
Assert.assertEquals(mapState.get("hello1"), "world1");
|
||||
mapState.setCurrentKey("2");
|
||||
Assert.assertEquals(mapState.get("eagle"), "eagle-1");
|
||||
Assert.assertEquals(mapState.get("xxx"), null);
|
||||
|
||||
keyStateBackend.rollBack(1);
|
||||
mapState.setCurrentKey("1");
|
||||
Assert.assertEquals(mapState.iterator(), (new HashMap()).entrySet().iterator());
|
||||
mapState.setCurrentKey("2");
|
||||
Assert.assertEquals(mapState.iterator(), (new HashMap()).entrySet().iterator());
|
||||
|
||||
mapState.setCurrentKey("1");
|
||||
mapState.put("eagle", "eagle-1");
|
||||
mapState.put("eagle-2", "eagle-3");
|
||||
keyStateBackend.finish(1);
|
||||
|
||||
keyStateBackend.setCheckpointId(2);
|
||||
mapState.setCurrentKey("2");
|
||||
mapState.put("tim", "tina");
|
||||
|
||||
mapState.setCurrentKey("2-1");
|
||||
mapState.put("jim", "tick");
|
||||
keyStateBackend.finish(2);
|
||||
|
||||
keyStateBackend.setCheckpointId(3);
|
||||
mapState.setCurrentKey("3");
|
||||
mapState.put("lucy", "ja");
|
||||
keyStateBackend.finish(3);
|
||||
|
||||
keyStateBackend.setCheckpointId(4);
|
||||
mapState.setCurrentKey("4");
|
||||
mapState.put("eric", "sam");
|
||||
keyStateBackend.finish(4);
|
||||
|
||||
keyStateBackend.setCheckpointId(5);
|
||||
mapState.setCurrentKey("4");
|
||||
mapState.put("eric-1", "zxy");
|
||||
Assert.assertEquals(mapState.get("eric-1"), "zxy");
|
||||
Assert.assertEquals(mapState.get("eric"), "sam");
|
||||
|
||||
mapState.setCurrentKey("5");
|
||||
mapState.put("jack", "zhang");
|
||||
keyStateBackend.finish(5);
|
||||
keyStateBackend.commit(5);
|
||||
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
mapState.setCurrentKey("5");
|
||||
Assert.assertEquals(mapState.get("jack"), "zhang");
|
||||
mapState.put("hlll", "gggg");
|
||||
|
||||
mapState.setCurrentKey("4");
|
||||
Assert.assertEquals(mapState.get("eric-1"), "zxy");
|
||||
Assert.assertEquals(mapState.get("eric"), "sam");
|
||||
|
||||
mapState.setCurrentKey(4);
|
||||
mapState.put("if-ttt", "if-ggg");
|
||||
Assert.assertEquals(mapState.get("if-ttt"), "if-ggg");
|
||||
|
||||
keyStateBackend.setCheckpointId(7);
|
||||
mapState.setCurrentKey(9);
|
||||
mapState.put("6666", "7777");
|
||||
|
||||
keyStateBackend.rollBack(5);
|
||||
keyStateBackend.setCheckpointId(6);
|
||||
mapState.setCurrentKey("4");
|
||||
Assert.assertEquals(mapState.get("eric-1"), "zxy");
|
||||
Assert.assertEquals(mapState.get("eric"), "sam");
|
||||
Assert.assertNull(mapState.get("if-ttt"));
|
||||
|
||||
mapState.setCurrentKey("5");
|
||||
Assert.assertNull(mapState.get("hlll"));
|
||||
mapState.setCurrentKey("9");
|
||||
Assert.assertNull(mapState.get("6666"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMem() {
|
||||
stateBackend = StateBackendBuilder.buildStateBackend(new HashMap<>());
|
||||
keyStateBackend = new KeyStateBackend(4, new KeyGroup(2, 3), stateBackend);
|
||||
testGetValueState();
|
||||
testGetListState();
|
||||
testGetMapState();
|
||||
}
|
||||
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.impl;
|
||||
|
||||
import io.ray.streaming.state.serialization.impl.DefaultKeyMapStoreSerializer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class DefaultKeyMapStoreSerializationTest {
|
||||
|
||||
private DefaultKeyMapStoreSerializer<String, String, Map<String, String>> defaultKMapStoreSerDe;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
this.defaultKMapStoreSerDe = new DefaultKeyMapStoreSerializer<>();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerKey() {
|
||||
String key = "hello";
|
||||
byte[] result = this.defaultKMapStoreSerDe.serializeKey(key);
|
||||
String keyWithPrefix = this.defaultKMapStoreSerDe.generateRowKeyPrefix(key.toString());
|
||||
Assert.assertEquals(result, keyWithPrefix.getBytes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerUKey() {
|
||||
String subKey = "hell1";
|
||||
byte[] result = this.defaultKMapStoreSerDe.serializeUKey(subKey);
|
||||
Assert.assertEquals(subKey, this.defaultKMapStoreSerDe.deserializeUKey(result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerUValue() {
|
||||
Map<String, String> value = new HashMap<>();
|
||||
value.put("foo", "bar");
|
||||
byte[] result = this.defaultKMapStoreSerDe.serializeUValue(value);
|
||||
Assert.assertEquals(value, this.defaultKMapStoreSerDe.deserializeUValue(result));
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.impl;
|
||||
|
||||
import io.ray.streaming.state.serialization.impl.DefaultKeyValueStoreSerialization;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class DefaultKeyValueStoreSerializationTest {
|
||||
|
||||
DefaultKeyValueStoreSerialization<String, Integer> serDe = new DefaultKeyValueStoreSerialization<>();
|
||||
byte[] ret;
|
||||
|
||||
@Test
|
||||
public void testSerKey() throws Exception {
|
||||
ret = serDe.serializeKey("key");
|
||||
String key = new String(ret);
|
||||
Assert.assertEquals(key.indexOf("key"), 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerValue() throws Exception {
|
||||
ret = serDe.serializeValue(5);
|
||||
Assert.assertEquals(ret.length, 2);
|
||||
Assert.assertEquals((int) serDe.deserializeValue(ret), 5);
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.impl;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import io.ray.streaming.state.backend.AbstractStateBackend;
|
||||
import io.ray.streaming.state.backend.StateBackendBuilder;
|
||||
import io.ray.streaming.state.store.KeyMapStore;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MemoryKeyMapStoreTest {
|
||||
|
||||
private AbstractStateBackend stateBackend;
|
||||
private KeyMapStore<String, String, String> IKeyMapStore;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
stateBackend = StateBackendBuilder.buildStateBackend(new HashMap<String, String>());
|
||||
IKeyMapStore = stateBackend.getKeyMapStore("test-table");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase() {
|
||||
try {
|
||||
Assert.assertNull(IKeyMapStore.get("hello"));
|
||||
Map<String, String> map = Maps.newHashMap();
|
||||
map.put("1", "1-1");
|
||||
map.put("2", "2-1");
|
||||
|
||||
IKeyMapStore.put("hello", map);
|
||||
Assert.assertEquals(IKeyMapStore.get("hello"), map);
|
||||
|
||||
Map<String, String> map2 = Maps.newHashMap();
|
||||
map.put("3", "3-1");
|
||||
map.put("4", "4-1");
|
||||
IKeyMapStore.put("hello", map2);
|
||||
Assert.assertNotEquals(IKeyMapStore.get("hello"), map);
|
||||
Assert.assertEquals(IKeyMapStore.get("hello"), map2);
|
||||
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.AbstractStateBackend;
|
||||
import io.ray.streaming.state.backend.StateBackendBuilder;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MemoryKeyValueStoreTest {
|
||||
|
||||
private AbstractStateBackend stateBackend;
|
||||
private io.ray.streaming.state.store.KeyValueStore<String, String> KeyValueStore;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
Map<String, String> config = new HashMap<>();
|
||||
stateBackend = StateBackendBuilder.buildStateBackend(config);
|
||||
KeyValueStore = stateBackend.getKeyValueStore("kepler_hlg_ut");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCase() {
|
||||
try {
|
||||
KeyValueStore.put("hello", "world");
|
||||
Assert.assertEquals(KeyValueStore.get("hello"), "world");
|
||||
KeyValueStore.put("hello", "world1");
|
||||
Assert.assertEquals(KeyValueStore.get("hello"), "world1");
|
||||
Assert.assertNull(KeyValueStore.get("hello1"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class KeyGroupAssignmentTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testComputeKeyGroupRangeForOperatorIndex() throws Exception {
|
||||
KeyGroup keyGroup = KeyGroupAssignment.getKeyGroup(4096, 1, 0);
|
||||
assertEquals(keyGroup.getStartIndex(), 0);
|
||||
assertEquals(keyGroup.getEndIndex(), 4095);
|
||||
assertEquals(keyGroup.size(), 4096);
|
||||
|
||||
KeyGroup keyGroup2 = KeyGroupAssignment.getKeyGroup(4096, 2, 0);
|
||||
assertEquals(keyGroup2.getStartIndex(), 0);
|
||||
assertEquals(keyGroup2.getEndIndex(), 2047);
|
||||
assertEquals(keyGroup2.size(), 2048);
|
||||
|
||||
keyGroup = KeyGroupAssignment.getKeyGroup(4096, 3, 0);
|
||||
assertEquals(keyGroup.getStartIndex(), 0);
|
||||
assertEquals(keyGroup.getEndIndex(), 1365);
|
||||
assertEquals(keyGroup.size(), 1366);
|
||||
|
||||
keyGroup2 = KeyGroupAssignment.getKeyGroup(4096, 3, 1);
|
||||
assertEquals(keyGroup2.getStartIndex(), 1366);
|
||||
assertEquals(keyGroup2.getEndIndex(), 2730);
|
||||
assertEquals(keyGroup2.size(), 1365);
|
||||
|
||||
KeyGroup keyGroup3 = KeyGroupAssignment.getKeyGroup(4096, 3, 2);
|
||||
assertEquals(keyGroup3.getStartIndex(), 2731);
|
||||
assertEquals(keyGroup3.getEndIndex(), 4095);
|
||||
assertEquals(keyGroup3.size(), 1365);
|
||||
}
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import io.ray.streaming.state.config.ConfigKey;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ListStateDescriptorTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ListStateDescriptor<Integer> descriptor = ListStateDescriptor
|
||||
.build("lsdTest", Integer.class, true);
|
||||
descriptor.setTableName("table");
|
||||
Assert.assertTrue(descriptor.isOperatorList());
|
||||
|
||||
descriptor.setPartitionNumber(3);
|
||||
descriptor.setIndex(0);
|
||||
|
||||
Assert.assertEquals(descriptor.getPartitionNumber(), 3);
|
||||
Assert.assertEquals(descriptor.getIndex(), 0);
|
||||
|
||||
Assert.assertEquals(descriptor.getIdentify(),
|
||||
"lsdTest" + ConfigKey.DELIMITER + "3" + ConfigKey.DELIMITER + "0");
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MapStateDescriptorTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
MapStateDescriptor<String, Integer> descriptor = MapStateDescriptor
|
||||
.build("msdTest", String.class, Integer.class);
|
||||
|
||||
descriptor.setTableName("table");
|
||||
Assert.assertEquals(descriptor.getTableName(), "table");
|
||||
Assert.assertEquals(descriptor.getName(), "msdTest");
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.desc;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ValueStateDescriptorTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ValueStateDescriptor<Integer> descriptor = ValueStateDescriptor
|
||||
.build("vsdTest", Integer.class, 0);
|
||||
Assert.assertEquals(descriptor.getDefaultValue().intValue(), 0);
|
||||
}
|
||||
}
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ListStateImplTest {
|
||||
|
||||
ListStateImpl<Integer> listState;
|
||||
KeyStateBackend keyStateBackend;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
keyStateBackend = new KeyStateBackend(1, new KeyGroup(1, 2),
|
||||
new MemoryStateBackend(new HashMap<>()));
|
||||
ListStateDescriptor<Integer> descriptor = ListStateDescriptor
|
||||
.build("ListStateImplTest", Integer.class);
|
||||
descriptor.setTableName("table");
|
||||
|
||||
listState = (ListStateImpl<Integer>) keyStateBackend.getListState(descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddGet() throws Exception {
|
||||
keyStateBackend.setContext(1L, 1);
|
||||
List<Integer> list = listState.get();
|
||||
Assert.assertEquals(list.size(), 0);
|
||||
|
||||
listState.add(1);
|
||||
listState.add(2);
|
||||
|
||||
Assert.assertEquals(listState.get(), Arrays.asList(1, 2));
|
||||
|
||||
listState.add(3);
|
||||
Assert.assertEquals(listState.get(), Arrays.asList(1, 2, 3));
|
||||
|
||||
list = listState.get();
|
||||
list.set(1, -1);
|
||||
listState.add(4);
|
||||
Assert.assertEquals(listState.get(), Arrays.asList(1, -1, 3, 4));
|
||||
|
||||
keyStateBackend.setCurrentKey(2);
|
||||
|
||||
listState.add(5);
|
||||
listState.add(6);
|
||||
|
||||
Assert.assertEquals(listState.get(), Arrays.asList(5, 6));
|
||||
}
|
||||
|
||||
|
||||
@Test(dependsOnMethods = {"testAddGet"})
|
||||
public void testUpdate() throws Exception {
|
||||
Assert.assertEquals(listState.get(), Arrays.asList(5, 6));
|
||||
|
||||
listState.update(Arrays.asList(7, 8, 9));
|
||||
|
||||
List<Integer> list = listState.get();
|
||||
Assert.assertEquals(list, Arrays.asList(7, 8, 9));
|
||||
|
||||
list.set(1, 10);
|
||||
listState.update(list);
|
||||
Assert.assertEquals(list, Arrays.asList(7, 10, 9));
|
||||
|
||||
listState.update(null);
|
||||
Assert.assertEquals(listState.get().size(), 0);
|
||||
}
|
||||
}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MapStateImplTest {
|
||||
|
||||
MapStateImpl<Integer, String> mapState;
|
||||
KeyStateBackend keyStateBackend;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
keyStateBackend = new KeyStateBackend(1, new KeyGroup(1, 2),
|
||||
new MemoryStateBackend(new HashMap<>()));
|
||||
MapStateDescriptor<Integer, String> descriptor = MapStateDescriptor
|
||||
.build("MapStateImplTest", Integer.class, String.class);
|
||||
descriptor.setTableName("table");
|
||||
mapState = (MapStateImpl<Integer, String>) keyStateBackend.getMapState(descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPuTGet() throws Exception {
|
||||
keyStateBackend.setContext(1L, 1);
|
||||
|
||||
Assert.assertEquals(mapState.get().size(), 0);
|
||||
|
||||
mapState.put(1, "1");
|
||||
mapState.put(2, "2");
|
||||
|
||||
Assert.assertTrue(mapState.contains(1));
|
||||
Assert.assertTrue(mapState.contains(2));
|
||||
Assert.assertFalse(mapState.contains(3));
|
||||
|
||||
Assert.assertEquals("1", mapState.get(1));
|
||||
Assert.assertEquals("2", mapState.get(2));
|
||||
|
||||
mapState.remove(1);
|
||||
Assert.assertFalse(mapState.contains(1));
|
||||
Assert.assertTrue(mapState.contains(2));
|
||||
|
||||
mapState.remove(2);
|
||||
mapState.putAll(ImmutableMap.of(1, "1", 2, "2"));
|
||||
Assert.assertEquals("1", mapState.get(1));
|
||||
Assert.assertEquals("2", mapState.get(2));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = {"testPuTGet"})
|
||||
public void testUpdate() throws Exception {
|
||||
Assert.assertEquals(mapState.get().size(), 2);
|
||||
|
||||
mapState.update(ImmutableMap.of(3, "3", 4, "4"));
|
||||
Assert.assertEquals(mapState.get(3), "3");
|
||||
Assert.assertEquals(mapState.get(4), "4");
|
||||
Assert.assertEquals(mapState.get().size(), 2);
|
||||
|
||||
Map<Integer, String> map = ImmutableMap.of(5, "5", 6, "6");
|
||||
mapState.update(map);
|
||||
Assert.assertEquals(mapState.get(), map);
|
||||
|
||||
mapState.update(null);
|
||||
Assert.assertEquals(mapState.get().size(), 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFailover() throws Exception {
|
||||
keyStateBackend.setContext(1L, 1);
|
||||
|
||||
Assert.assertEquals(mapState.get().size(), 0);
|
||||
|
||||
mapState.put(1, "1");
|
||||
mapState.put(2, "2");
|
||||
|
||||
Assert.assertTrue(mapState.contains(1));
|
||||
Assert.assertTrue(mapState.contains(2));
|
||||
Assert.assertFalse(mapState.contains(3));
|
||||
|
||||
Assert.assertEquals("1", mapState.get(1));
|
||||
Assert.assertEquals("2", mapState.get(2));
|
||||
|
||||
mapState.remove(1);
|
||||
Assert.assertFalse(mapState.contains(1));
|
||||
Assert.assertTrue(mapState.contains(2));
|
||||
|
||||
mapState.remove(2);
|
||||
mapState.putAll(ImmutableMap.of(1, "1", 2, "2"));
|
||||
Assert.assertEquals("1", mapState.get(1));
|
||||
Assert.assertEquals("2", mapState.get(2));
|
||||
|
||||
keyStateBackend.finish(5);
|
||||
|
||||
Assert.assertEquals("1", mapState.get(1));
|
||||
Assert.assertEquals("2", mapState.get(2));
|
||||
|
||||
mapState.put(2, "3");
|
||||
Assert.assertEquals("3", mapState.get(2));
|
||||
|
||||
keyStateBackend.finish(6);
|
||||
|
||||
keyStateBackend.commit(5);
|
||||
Assert.assertEquals("3", mapState.get(2));
|
||||
|
||||
keyStateBackend.commit(6);
|
||||
keyStateBackend.ackCommit(5, 0);
|
||||
keyStateBackend.ackCommit(6, 1);
|
||||
|
||||
mapState.put(2, "5");
|
||||
Assert.assertEquals("5", mapState.get(2));
|
||||
mapState.update(null);
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.OperatorStateBackend;
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class OperatorStateImplTest {
|
||||
|
||||
OperatorStateImpl<Integer> operatorState;
|
||||
ListStateDescriptor<Integer> descriptor;
|
||||
OperatorStateBackend operatorStateBackend;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
String table_name = "operatorState";
|
||||
Map config = new HashMap<>();
|
||||
|
||||
operatorStateBackend = new OperatorStateBackend(new MemoryStateBackend(config));
|
||||
|
||||
descriptor = ListStateDescriptor
|
||||
.build("OperatorStateImplTest" + System.currentTimeMillis(), Integer.class, true);
|
||||
descriptor.setPartitionNumber(1);
|
||||
descriptor.setIndex(0);
|
||||
descriptor.setTableName(table_name);
|
||||
|
||||
operatorState = (OperatorStateImpl<Integer>) operatorStateBackend.getSplitListState(descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInit() throws Exception {
|
||||
operatorStateBackend.setCheckpointId(1L);
|
||||
List<Integer> list = operatorState.get();
|
||||
Assert.assertEquals(list.size(), 0);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
operatorState.add(i);
|
||||
}
|
||||
Assert.assertEquals(operatorState.get().size(), 100);
|
||||
operatorStateBackend.finish(1L);
|
||||
operatorStateBackend.commit(1L);
|
||||
operatorStateBackend.ackCommit(1L, 0);
|
||||
|
||||
operatorStateBackend.finish(5L);
|
||||
operatorStateBackend.commit(5L);
|
||||
operatorStateBackend.ackCommit(5L, 0);
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.impl;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import java.util.HashMap;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ValueStateImplTest {
|
||||
|
||||
ValueStateImpl<String> valueState;
|
||||
KeyStateBackend keyStateBackend;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() throws Exception {
|
||||
keyStateBackend = new KeyStateBackend(1, new KeyGroup(1, 2),
|
||||
new MemoryStateBackend(new HashMap<>()));
|
||||
ValueStateDescriptor<String> descriptor = ValueStateDescriptor
|
||||
.build("ValueStateImplTest", String.class, "hello");
|
||||
descriptor.setTableName("table");
|
||||
|
||||
valueState = (ValueStateImpl<String>) keyStateBackend.getValueState(descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateGet() throws Exception {
|
||||
keyStateBackend.setContext(1L, 1);
|
||||
|
||||
Assert.assertEquals(valueState.get(), "hello");
|
||||
|
||||
String str = valueState.get();
|
||||
|
||||
valueState.update(str + " world");
|
||||
Assert.assertEquals(valueState.get(), "hello world");
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ListStateStoreManagerTest extends StateStoreManagerTest {
|
||||
|
||||
ListStateStoreManagerProxy<Integer> proxy;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
ListStateDescriptor<Integer> descriptor = ListStateDescriptor.build("list", Integer.class);
|
||||
descriptor.setTableName("tableName");
|
||||
keyStateBackend.setContext(1L, "key");
|
||||
proxy = new ListStateStoreManagerProxy<>(keyStateBackend, descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
Assert.assertEquals(proxy.getListState().get().size(), 0);
|
||||
|
||||
List<Integer> list = Arrays.asList(1, 2, 3);
|
||||
proxy.put("key1", list);
|
||||
Assert.assertEquals(proxy.get("key1"), list);
|
||||
|
||||
proxy.put("key1", Arrays.asList(1, 3));
|
||||
|
||||
proxy.put("key2", Arrays.asList(4, 5));
|
||||
Assert.assertEquals(proxy.get("key2"), Arrays.asList(4, 5));
|
||||
|
||||
Assert.assertEquals(proxy.get("key1"), Arrays.asList(1, 3));
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MapStateStoreManagerTest extends StateStoreManagerTest {
|
||||
|
||||
MapStateStoreManagerProxy<String, Integer> facade;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
MapStateDescriptor<String, Integer> descriptor = MapStateDescriptor
|
||||
.build("map", String.class, Integer.class);
|
||||
descriptor.setTableName("tableName");
|
||||
keyStateBackend.setContext(1L, "key");
|
||||
facade = new MapStateStoreManagerProxy<>(keyStateBackend, descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
Assert.assertEquals(facade.getMapState().get().size(), 0);
|
||||
|
||||
Map<String, Integer> map = new HashMap<>();
|
||||
map.put("key1", 1);
|
||||
map.put("key2", 2);
|
||||
facade.put("key1", map);
|
||||
Assert.assertEquals(facade.get("key1"), map);
|
||||
|
||||
map.remove("key1");
|
||||
facade.put("key2", map);
|
||||
Assert.assertEquals(facade.get("key2"), map);
|
||||
}
|
||||
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.impl.MemoryStateBackend;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class StateStoreManagerTest {
|
||||
|
||||
protected KeyStateBackend keyStateBackend = new KeyStateBackend(1, new KeyGroup(1, 1),
|
||||
new MemoryStateBackend(new HashMap<String, String>()));
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.keystate.state.proxy;
|
||||
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class ValueStateStoreManagerTest extends StateStoreManagerTest {
|
||||
|
||||
ValueStateStoreManagerProxy<Integer> proxy;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
ValueStateDescriptor<Integer> descriptor = ValueStateDescriptor
|
||||
.build("value", Integer.class, 0);
|
||||
descriptor.setTableName("tableName");
|
||||
keyStateBackend.setContext(1L, "key");
|
||||
proxy = new ValueStateStoreManagerProxy<>(keyStateBackend, descriptor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
ValueState<Integer> state = proxy.getValueState();
|
||||
Assert.assertEquals(state.get().intValue(), 0);
|
||||
|
||||
proxy.put("key1", 2);
|
||||
Assert.assertEquals(proxy.get("key1").intValue(), 2);
|
||||
|
||||
proxy.put("key1", 3);
|
||||
Assert.assertEquals(proxy.get("key1").intValue(), 3);
|
||||
|
||||
proxy.put("key2", 9);
|
||||
Assert.assertEquals(proxy.get("key2").intValue(), 9);
|
||||
|
||||
proxy.put("key2", 6);
|
||||
Assert.assertEquals(proxy.get("key2").intValue(), 6);
|
||||
}
|
||||
}
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import io.ray.streaming.state.backend.BackendType;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.StateBackendBuilder;
|
||||
import io.ray.streaming.state.backend.StateStrategy;
|
||||
import io.ray.streaming.state.config.ConfigKey;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class DualStateStrategyTest {
|
||||
|
||||
private final String table = "kepler_cp_store";
|
||||
private final String defaultValue = "default";
|
||||
protected KeyStateBackend keyStateBackend;
|
||||
Map<String, String> config = new HashMap<>();
|
||||
private String currentTime;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
config.put(ConfigKey.STATE_STRATEGY_MODE, StateStrategy.DUAL_VERSION.name());
|
||||
currentTime = Long.toString(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void caseKV() {
|
||||
ValueStateDescriptor<String> valueStateDescriptor = ValueStateDescriptor
|
||||
.build("VALUE-" + currentTime, String.class, defaultValue);
|
||||
valueStateDescriptor.setTableName(table);
|
||||
ValueState<String> state = this.keyStateBackend.getValueState(valueStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.update("hello");
|
||||
state.setCurrentKey("2");
|
||||
state.update("world");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "hello");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "world");
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.update("eagle");
|
||||
state.setCurrentKey(("4"));
|
||||
state.update("alex");
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "eagle");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "alex");
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.update("tim");
|
||||
state.setCurrentKey(("4"));
|
||||
state.update("scala");
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.update("cook");
|
||||
state.setCurrentKey(("2"));
|
||||
state.update("inf");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "inf");
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "cook");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "scala");
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
//do rollback, all memory data is deleted.
|
||||
this.keyStateBackend.rollBack(1);
|
||||
this.keyStateBackend.setCheckpointId(1);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), defaultValue);
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), defaultValue);
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), defaultValue);
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), defaultValue);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.update("tim");
|
||||
this.keyStateBackend.finish(4);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
state.update("info");
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.update("cook");
|
||||
this.keyStateBackend.finish(6);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(7);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(), "cook");
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
|
||||
this.keyStateBackend.rollBack(6);
|
||||
}
|
||||
|
||||
public void caseKVGap() {
|
||||
ValueStateDescriptor<String> valueStateDescriptor = ValueStateDescriptor
|
||||
.build("value2-" + currentTime, String.class, defaultValue);
|
||||
valueStateDescriptor.setTableName(table);
|
||||
ValueState<String> state = this.keyStateBackend.getValueState(valueStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5L);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.update("hello");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "hello");
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.update("info");
|
||||
this.keyStateBackend.finish(5);
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(10);
|
||||
Assert.assertEquals(state.get(), "info");
|
||||
this.keyStateBackend.finish(10);
|
||||
this.keyStateBackend.commit(10);
|
||||
this.keyStateBackend.ackCommit(10, 10);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(15);
|
||||
state.update("world");
|
||||
this.keyStateBackend.finish(15);
|
||||
this.keyStateBackend.commit(15);
|
||||
this.keyStateBackend.ackCommit(15, 15);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(11);
|
||||
this.keyStateBackend.rollBack(11);
|
||||
Assert.assertEquals(state.get(), "info");
|
||||
|
||||
this.keyStateBackend.setCheckpointId(15);
|
||||
state.update("world2");
|
||||
this.keyStateBackend.finish(15);
|
||||
this.keyStateBackend.commit(15);
|
||||
this.keyStateBackend.ackCommit(15, 15);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(11);
|
||||
this.keyStateBackend.rollBack(11);
|
||||
Assert.assertEquals(state.get(), "info");
|
||||
|
||||
}
|
||||
|
||||
public void caseKList() {
|
||||
ListStateDescriptor<Integer> listStateDescriptor = ListStateDescriptor
|
||||
.build("LIST-" + currentTime, Integer.class);
|
||||
listStateDescriptor.setTableName(table);
|
||||
ListState<Integer> state = this.keyStateBackend.getListState(listStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.add(1);
|
||||
state.setCurrentKey("2");
|
||||
state.add(2);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
List<Integer> result = state.get();
|
||||
Assert.assertEquals(result, Arrays.asList(1));
|
||||
state.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2));
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.add(3);
|
||||
state.setCurrentKey(("4"));
|
||||
state.add(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(3));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(4));
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.add(2);
|
||||
state.setCurrentKey(("4"));
|
||||
state.add(5);
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.add(4);
|
||||
state.setCurrentKey(("2"));
|
||||
state.add(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1, 2));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2, 3));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(3, 4));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(4, 5));
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
//do rollback, all memory data is deleted.
|
||||
this.keyStateBackend.rollBack(1);
|
||||
this.keyStateBackend.setCheckpointId(1);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), Lists.newArrayList());
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), Lists.newArrayList());
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Lists.newArrayList());
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Lists.newArrayList());
|
||||
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.add(1);
|
||||
this.keyStateBackend.finish(4);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
state.add(2);
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.add(3);
|
||||
this.keyStateBackend.finish(6);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(7);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2, 2, 3));
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.rollBack(5);
|
||||
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1));
|
||||
}
|
||||
|
||||
public void caseKMap() {
|
||||
MapStateDescriptor<Integer, Integer> mapStateDescriptor = MapStateDescriptor
|
||||
.build("MAP-" + currentTime, Integer.class, Integer.class);
|
||||
mapStateDescriptor.setTableName(table);
|
||||
MapState<Integer, Integer> state = this.keyStateBackend.getMapState(mapStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.put(1, 1);
|
||||
state.setCurrentKey("2");
|
||||
state.put(2, 2);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.put(3, 3);
|
||||
state.setCurrentKey(("4"));
|
||||
state.put(4, 4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(4), Integer.valueOf(4));
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.put(5, 5);
|
||||
state.setCurrentKey(("4"));
|
||||
state.put(6, 6);
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.put(7, 7);
|
||||
state.setCurrentKey(("2"));
|
||||
state.put(8, 8);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
Assert.assertEquals(state.get(5), Integer.valueOf(5));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(8), Integer.valueOf(8));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
Assert.assertEquals(state.get(7), Integer.valueOf(7));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(4), Integer.valueOf(4));
|
||||
Assert.assertEquals(state.get(6), Integer.valueOf(6));
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
//do rollback, memory data is deleted.
|
||||
this.keyStateBackend.rollBack(1);
|
||||
this.keyStateBackend.setCheckpointId(1);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.entries(), (new HashMap()).entrySet());
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.entries(), (new HashMap()).entrySet());
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.entries(), (new HashMap()).entrySet());
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.entries(), (new HashMap()).entrySet());
|
||||
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.put(1, 1);
|
||||
this.keyStateBackend.finish(4);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
state.put(2, 2);
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.put(3, 3);
|
||||
this.keyStateBackend.finish(6);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(7);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.rollBack(5);
|
||||
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(3), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMem() {
|
||||
config.put(ConfigKey.STATE_BACKEND_TYPE, BackendType.MEMORY.name());
|
||||
this.keyStateBackend = new KeyStateBackend(10, new KeyGroup(1, 3),
|
||||
StateBackendBuilder.buildStateBackend(config));
|
||||
caseKV();
|
||||
caseKVGap();
|
||||
caseKList();
|
||||
caseKMap();
|
||||
}
|
||||
}
|
||||
+405
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.ray.streaming.state.strategy;
|
||||
|
||||
import io.ray.streaming.state.backend.BackendType;
|
||||
import io.ray.streaming.state.backend.KeyStateBackend;
|
||||
import io.ray.streaming.state.backend.StateBackendBuilder;
|
||||
import io.ray.streaming.state.backend.StateStrategy;
|
||||
import io.ray.streaming.state.config.ConfigKey;
|
||||
import io.ray.streaming.state.keystate.KeyGroup;
|
||||
import io.ray.streaming.state.keystate.desc.ListStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.MapStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.desc.ValueStateDescriptor;
|
||||
import io.ray.streaming.state.keystate.state.ListState;
|
||||
import io.ray.streaming.state.keystate.state.MapState;
|
||||
import io.ray.streaming.state.keystate.state.ValueState;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class MVStateStrategyTest {
|
||||
|
||||
private final String table = "kepler_hlg_ut";
|
||||
Map<String, String> config = new HashMap<>();
|
||||
private KeyStateBackend keyStateBackend;
|
||||
private String currentTime;
|
||||
|
||||
@BeforeClass
|
||||
public void setUp() {
|
||||
config.put(ConfigKey.STATE_STRATEGY_MODE, StateStrategy.SINGLE_VERSION.name());
|
||||
currentTime = Long.toString(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void caseKV() {
|
||||
|
||||
ValueStateDescriptor<String> valueStateDescriptor = ValueStateDescriptor
|
||||
.build("mvint-" + currentTime, String.class, "");
|
||||
valueStateDescriptor.setTableName(table);
|
||||
ValueState<String> state = this.keyStateBackend.getValueState(valueStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.update("hello");
|
||||
state.setCurrentKey("2");
|
||||
state.update("world");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "hello");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "world");
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.update("eagle");
|
||||
state.setCurrentKey(("4"));
|
||||
state.update("alex");
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "eagle");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "alex");
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.update("tim");
|
||||
state.setCurrentKey(("4"));
|
||||
state.update("scala");
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.update("cook");
|
||||
state.setCurrentKey(("2"));
|
||||
state.update("inf");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "inf");
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "cook");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "scala");
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
this.keyStateBackend.rollBack(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "hello");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "world");
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "eagle");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "alex");
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.update("tim");
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4l);
|
||||
|
||||
state.setCurrentKey(("4"));
|
||||
state.update("scala");
|
||||
this.keyStateBackend.finish(4);
|
||||
this.keyStateBackend.setCheckpointId(5l);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.update("cook");
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
state.setCurrentKey(("2"));
|
||||
state.update("info");
|
||||
this.keyStateBackend.finish(6);
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "info");
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "cook");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "scala");
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.rollBack(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), "tim");
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), "world");
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), "cook");
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), "scala");
|
||||
}
|
||||
|
||||
public void caseKList() {
|
||||
ListStateDescriptor<Integer> listStateDescriptor = ListStateDescriptor
|
||||
.build("mvlist-" + currentTime, Integer.class);
|
||||
listStateDescriptor.setTableName(table);
|
||||
ListState<Integer> state = this.keyStateBackend.getListState(listStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.add(1);
|
||||
state.setCurrentKey("2");
|
||||
state.add(2);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2));
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.add(3);
|
||||
state.setCurrentKey(("4"));
|
||||
state.add(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(3));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(4));
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.add(2);
|
||||
state.setCurrentKey(("4"));
|
||||
state.add(5);
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.add(4);
|
||||
state.setCurrentKey(("2"));
|
||||
state.add(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1, 2));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2, 3));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(3, 4));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(4, 5));
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
this.keyStateBackend.rollBack(2);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(3));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(), Arrays.asList(4));
|
||||
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.add(1);
|
||||
this.keyStateBackend.finish(4);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
state.add(2);
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.add(3);
|
||||
this.keyStateBackend.finish(6);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(7);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1, 1));
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2, 2, 3));
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.rollBack(5);
|
||||
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(1, 1));
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(), Arrays.asList(2, 2));
|
||||
}
|
||||
|
||||
public void caseKMap() {
|
||||
MapStateDescriptor<Integer, Integer> mapStateDescriptor = MapStateDescriptor
|
||||
.build("mvmap-" + currentTime, Integer.class, Integer.class);
|
||||
mapStateDescriptor.setTableName(table);
|
||||
MapState<Integer, Integer> state = this.keyStateBackend.getMapState(mapStateDescriptor);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(1l);
|
||||
|
||||
state.setCurrentKey("1");
|
||||
state.put(1, 1);
|
||||
state.setCurrentKey("2");
|
||||
state.put(2, 2);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
|
||||
this.keyStateBackend.finish(1);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(2);
|
||||
state.setCurrentKey(("3"));
|
||||
state.put(3, 3);
|
||||
state.setCurrentKey(("4"));
|
||||
state.put(4, 4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(4), Integer.valueOf(4));
|
||||
|
||||
this.keyStateBackend.commit(1);
|
||||
this.keyStateBackend.ackCommit(1, 1);
|
||||
|
||||
this.keyStateBackend.finish(2);
|
||||
this.keyStateBackend.setCheckpointId(3);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
state.put(5, 5);
|
||||
state.setCurrentKey(("4"));
|
||||
state.put(6, 6);
|
||||
|
||||
this.keyStateBackend.finish(3);
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
|
||||
state.setCurrentKey(("3"));
|
||||
state.put(7, 7);
|
||||
state.setCurrentKey(("2"));
|
||||
state.put(8, 8);
|
||||
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
Assert.assertEquals(state.get(5), Integer.valueOf(5));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(8), Integer.valueOf(8));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
Assert.assertEquals(state.get(7), Integer.valueOf(7));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(4), Integer.valueOf(4));
|
||||
Assert.assertEquals(state.get(6), Integer.valueOf(6));
|
||||
|
||||
this.keyStateBackend.commit(2);
|
||||
this.keyStateBackend.ackCommit(2, 2);
|
||||
|
||||
this.keyStateBackend.rollBack(2);
|
||||
state.setCurrentKey(("1"));
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
Assert.assertNull(state.get(5));
|
||||
state.setCurrentKey(("2"));
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertNull(state.get(8));
|
||||
state.setCurrentKey(("3"));
|
||||
Assert.assertEquals(state.get(3), Integer.valueOf(3));
|
||||
Assert.assertNull(state.get(7));
|
||||
state.setCurrentKey(("4"));
|
||||
Assert.assertEquals(state.get(4), Integer.valueOf(4));
|
||||
Assert.assertNull(state.get(6));
|
||||
|
||||
this.keyStateBackend.setCheckpointId(4);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
state.put(5, 5);
|
||||
this.keyStateBackend.finish(4);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(5);
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
state.put(8, 8);
|
||||
this.keyStateBackend.finish(5);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(6);
|
||||
state.put(7, 7);
|
||||
this.keyStateBackend.finish(6);
|
||||
|
||||
this.keyStateBackend.setCheckpointId(7);
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
Assert.assertEquals(state.get(5), Integer.valueOf(5));
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(8), Integer.valueOf(8));
|
||||
Assert.assertEquals(state.get(7), Integer.valueOf(7));
|
||||
|
||||
this.keyStateBackend.commit(5);
|
||||
this.keyStateBackend.ackCommit(5, 5);
|
||||
|
||||
this.keyStateBackend.rollBack(5);
|
||||
|
||||
this.keyStateBackend.setCurrentKey("1");
|
||||
Assert.assertEquals(state.get(1), Integer.valueOf(1));
|
||||
Assert.assertEquals(state.get(5), Integer.valueOf(5));
|
||||
|
||||
this.keyStateBackend.setCurrentKey("2");
|
||||
Assert.assertEquals(state.get(2), Integer.valueOf(2));
|
||||
Assert.assertEquals(state.get(8), Integer.valueOf(8));
|
||||
Assert.assertNull(state.get(7));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMemMV() {
|
||||
config.put(ConfigKey.STATE_BACKEND_TYPE, BackendType.MEMORY.name());
|
||||
this.keyStateBackend = new KeyStateBackend(10, new KeyGroup(1, 3),
|
||||
StateBackendBuilder.buildStateBackend(config));
|
||||
caseKV();
|
||||
caseKList();
|
||||
caseKMap();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user